aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.clang-format2
-rw-r--r--.dockerignore3
-rw-r--r--.github/issue_template.md2
-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--Brewfile1
-rw-r--r--CHANGELOG255
-rw-r--r--CODEOWNERS8
-rw-r--r--COPYING2
-rw-r--r--Makefile197
-rw-r--r--README.md38
-rw-r--r--backends/aiger/aiger.cc4
-rw-r--r--backends/aiger/xaiger.cc45
-rw-r--r--backends/blif/blif.cc112
-rw-r--r--backends/btor/.gitignore1
-rw-r--r--backends/btor/btor.cc248
-rwxr-xr-x[-rw-r--r--]backends/btor/test_cells.sh4
-rw-r--r--backends/cxxrtl/cxxrtl.h243
-rw-r--r--backends/cxxrtl/cxxrtl_backend.cc2029
-rw-r--r--backends/cxxrtl/cxxrtl_capi.cc31
-rw-r--r--backends/cxxrtl/cxxrtl_capi.h136
-rw-r--r--backends/cxxrtl/cxxrtl_vcd.h51
-rw-r--r--backends/edif/edif.cc10
-rw-r--r--backends/firrtl/firrtl.cc704
-rw-r--r--backends/ilang/Makefile.inc3
-rw-r--r--backends/intersynth/intersynth.cc8
-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/Makefile.inc3
-rw-r--r--backends/rtlil/rtlil_backend.cc (renamed from backends/ilang/ilang_backend.cc)116
-rw-r--r--backends/rtlil/rtlil_backend.h (renamed from backends/ilang/ilang_backend.h)10
-rw-r--r--backends/simplec/simplec.cc2
-rw-r--r--backends/smt2/smt2.cc498
-rw-r--r--backends/smt2/smtbmc.py54
-rw-r--r--backends/smt2/smtio.py36
-rw-r--r--backends/smv/.gitignore1
-rw-r--r--backends/smv/smv.cc25
-rw-r--r--backends/spice/spice.cc24
-rw-r--r--backends/table/table.cc2
-rw-r--r--backends/verilog/verilog_backend.cc1287
-rw-r--r--frontends/aiger/aigerparse.cc25
-rw-r--r--frontends/aiger/aigerparse.h2
-rw-r--r--frontends/ast/Makefile.inc1
-rw-r--r--frontends/ast/ast.cc340
-rw-r--r--frontends/ast/ast.h79
-rw-r--r--frontends/ast/ast_binding.cc49
-rw-r--r--frontends/ast/ast_binding.h58
-rw-r--r--frontends/ast/dpicall.cc19
-rw-r--r--frontends/ast/genrtlil.cc431
-rw-r--r--frontends/ast/simplify.cc1749
-rw-r--r--frontends/blif/blifparse.cc39
-rw-r--r--frontends/blif/blifparse.h2
-rw-r--r--frontends/ilang/.gitignore4
-rw-r--r--frontends/ilang/Makefile.inc19
-rw-r--r--frontends/json/jsonparse.cc64
-rw-r--r--frontends/liberty/liberty.cc2
-rw-r--r--frontends/rpc/rpc_frontend.cc5
-rw-r--r--frontends/rtlil/.gitignore4
-rw-r--r--frontends/rtlil/Makefile.inc19
-rw-r--r--frontends/rtlil/rtlil_frontend.cc (renamed from frontends/ilang/ilang_frontend.cc)63
-rw-r--r--frontends/rtlil/rtlil_frontend.h (renamed from frontends/ilang/ilang_frontend.h)24
-rw-r--r--frontends/rtlil/rtlil_lexer.l (renamed from frontends/ilang/ilang_lexer.l)26
-rw-r--r--frontends/rtlil/rtlil_parser.y (renamed from frontends/ilang/ilang_parser.y)69
-rw-r--r--frontends/verific/Makefile.inc2
-rw-r--r--frontends/verific/README8
-rw-r--r--frontends/verific/verific.cc929
-rw-r--r--frontends/verific/verific.h3
-rw-r--r--frontends/verific/verificsva.cc17
-rw-r--r--frontends/verilog/Makefile.inc2
-rw-r--r--frontends/verilog/const2ast.cc2
-rw-r--r--frontends/verilog/preproc.cc128
-rw-r--r--frontends/verilog/preproc.h3
-rw-r--r--frontends/verilog/verilog_frontend.cc37
-rw-r--r--frontends/verilog/verilog_frontend.h4
-rw-r--r--frontends/verilog/verilog_lexer.l55
-rw-r--r--frontends/verilog/verilog_parser.y926
-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.cc113
-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.h54
-rw-r--r--kernel/consteval.h37
-rw-r--r--kernel/constids.inc23
-rw-r--r--kernel/cost.h2
-rw-r--r--kernel/driver.cc44
-rw-r--r--kernel/ff.cc755
-rw-r--r--kernel/ff.h216
-rw-r--r--kernel/ffinit.h140
-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.cc40
-rw-r--r--kernel/log.h28
-rw-r--r--kernel/macc.h2
-rw-r--r--kernel/mem.cc1666
-rw-r--r--kernel/mem.h229
-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.cc493
-rw-r--r--kernel/rtlil.h108
-rw-r--r--kernel/satgen.cc1339
-rw-r--r--kernel/satgen.h1180
-rw-r--r--kernel/sigtools.h2
-rw-r--r--kernel/timinginfo.h54
-rw-r--r--kernel/utils.h2
-rw-r--r--kernel/yosys.cc123
-rw-r--r--kernel/yosys.h24
-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.tex393
-rw-r--r--manual/CHAPTER_Overview.tex26
-rw-r--r--manual/CHAPTER_Prog.tex11
-rw-r--r--manual/CHAPTER_StateOfTheArt/simlib_yosys.v2
-rw-r--r--manual/CHAPTER_TextRtlil.tex299
-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.tex22
-rw-r--r--manual/PRESENTATION_Prog.tex7
-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.tex8
-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.inc2
-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.cc153
-rw-r--r--passes/cmds/check.cc87
-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/logcmd.cc2
-rw-r--r--passes/cmds/logger.cc11
-rw-r--r--passes/cmds/ltp.cc2
-rw-r--r--passes/cmds/plugin.cc8
-rw-r--r--passes/cmds/portlist.cc2
-rw-r--r--passes/cmds/qwp.cc2
-rw-r--r--passes/cmds/rename.cc6
-rw-r--r--passes/cmds/scatter.cc2
-rw-r--r--passes/cmds/scc.cc79
-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.cc32
-rw-r--r--passes/cmds/splice.cc4
-rw-r--r--passes/cmds/splitnets.cc2
-rw-r--r--passes/cmds/sta.cc312
-rw-r--r--passes/cmds/stat.cc10
-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.cc11
-rw-r--r--passes/equiv/equiv_make.cc10
-rw-r--r--passes/equiv/equiv_mark.cc2
-rw-r--r--passes/equiv/equiv_miter.cc2
-rw-r--r--passes/equiv/equiv_purge.cc6
-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.cc509
-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.cc560
-rw-r--r--passes/memory/memory_collect.cc234
-rw-r--r--passes/memory/memory_dff.cc778
-rw-r--r--passes/memory/memory_map.cc252
-rw-r--r--passes/memory/memory_memx.cc75
-rw-r--r--passes/memory/memory_narrow.cc67
-rw-r--r--passes/memory/memory_nordff.cc75
-rw-r--r--passes/memory/memory_share.cc959
-rw-r--r--passes/memory/memory_unpack.cc118
-rw-r--r--passes/opt/Makefile.inc5
-rw-r--r--passes/opt/muxpack.cc2
-rw-r--r--passes/opt/opt.cc36
-rw-r--r--passes/opt/opt_clean.cc88
-rw-r--r--passes/opt/opt_demorgan.cc2
-rw-r--r--passes/opt/opt_dff.cc918
-rw-r--r--passes/opt/opt_expr.cc276
-rw-r--r--passes/opt/opt_lut.cc59
-rw-r--r--passes/opt/opt_lut_ins.cc12
-rw-r--r--passes/opt/opt_mem.cc113
-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.cc46
-rw-r--r--passes/opt/opt_muxtree.cc35
-rw-r--r--passes/opt/opt_reduce.cc403
-rw-r--r--passes/opt/opt_rmdff.cc711
-rw-r--r--passes/opt/opt_share.cc363
-rw-r--r--passes/opt/pmux2shiftx.cc21
-rw-r--r--passes/opt/rmports.cc2
-rw-r--r--passes/opt/share.cc86
-rw-r--r--passes/opt/wreduce.cc48
-rw-r--r--passes/pmgen/Makefile.inc10
-rw-r--r--passes/pmgen/generate.h2
-rw-r--r--passes/pmgen/ice40_dsp.cc40
-rw-r--r--passes/pmgen/ice40_dsp.pmg300
-rw-r--r--passes/pmgen/ice40_wrapcarry.cc2
-rw-r--r--passes/pmgen/peepopt.cc5
-rw-r--r--passes/pmgen/peepopt_dffmux.pmg171
-rw-r--r--passes/pmgen/peepopt_muldiv.pmg5
-rw-r--r--passes/pmgen/peepopt_shiftmul.pmg6
-rw-r--r--passes/pmgen/pmgen.py8
-rw-r--r--passes/pmgen/test_pmgen.cc2
-rw-r--r--passes/pmgen/xilinx_dsp.cc161
-rw-r--r--passes/pmgen/xilinx_dsp.pmg333
-rw-r--r--passes/pmgen/xilinx_dsp48a.pmg322
-rw-r--r--passes/pmgen/xilinx_dsp_CREG.pmg122
-rw-r--r--passes/pmgen/xilinx_dsp_cascade.pmg125
-rw-r--r--passes/pmgen/xilinx_srl.cc2
-rw-r--r--passes/proc/Makefile.inc1
-rw-r--r--passes/proc/proc.cc26
-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.cc22
-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.cc4
-rw-r--r--passes/sat/async2sync.cc336
-rw-r--r--passes/sat/clk2fflogic.cc451
-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.cc5
-rw-r--r--passes/sat/fminit.cc2
-rw-r--r--passes/sat/freduce.cc3
-rw-r--r--passes/sat/miter.cc2
-rw-r--r--passes/sat/mutate.cc8
-rw-r--r--passes/sat/qbfsat.cc291
-rw-r--r--passes/sat/qbfsat.h253
-rw-r--r--passes/sat/sat.cc4
-rw-r--r--passes/sat/sim.cc678
-rw-r--r--passes/sat/supercover.cc2
-rw-r--r--passes/techmap/Makefile.inc6
-rw-r--r--passes/techmap/abc.cc124
-rw-r--r--passes/techmap/abc9.cc28
-rw-r--r--passes/techmap/abc9_exe.cc15
-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.cc60
-rw-r--r--passes/techmap/deminout.cc2
-rw-r--r--passes/techmap/demuxmap.cc80
-rw-r--r--passes/techmap/dff2dffe.cc414
-rw-r--r--passes/techmap/dff2dffs.cc165
-rw-r--r--passes/techmap/dffinit.cc50
-rw-r--r--passes/techmap/dfflegalize.cc1235
-rw-r--r--passes/techmap/dfflibmap.cc291
-rw-r--r--passes/techmap/dffunmap.cc106
-rw-r--r--passes/techmap/extract.cc13
-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.cc4
-rw-r--r--passes/techmap/flatten.cc30
-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.cc51
-rw-r--r--passes/techmap/simplemap.cc334
-rw-r--r--passes/techmap/simplemap.h9
-rw-r--r--passes/techmap/techmap.cc179
-rw-r--r--passes/techmap/tribuf.cc2
-rw-r--r--passes/techmap/zinit.cc161
-rw-r--r--passes/tests/test_abcloop.cc4
-rw-r--r--passes/tests/test_autotb.cc2
-rw-r--r--passes/tests/test_cell.cc72
-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.cc5
-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/cells_map.v38
-rw-r--r--techlibs/anlogic/cells_sim.v45
-rw-r--r--techlibs/anlogic/synth_anlogic.cc25
-rw-r--r--techlibs/common/abc9_map.v2
-rw-r--r--techlibs/common/abc9_model.v4
-rw-r--r--techlibs/common/abc9_unmap.v5
-rw-r--r--techlibs/common/adff2dff.v2
-rw-r--r--techlibs/common/cmp2lcu.v29
-rw-r--r--techlibs/common/cmp2lut.v14
-rw-r--r--techlibs/common/gen_fine_ffs.py49
-rw-r--r--techlibs/common/mul2dsp.v632
-rw-r--r--techlibs/common/prep.cc15
-rw-r--r--techlibs/common/simcells.v286
-rw-r--r--techlibs/common/simlib.v342
-rw-r--r--techlibs/common/synth.cc8
-rw-r--r--techlibs/common/techmap.v145
-rw-r--r--techlibs/coolrunner2/synth_coolrunner2.cc1
-rw-r--r--techlibs/easic/synth_easic.cc3
-rw-r--r--techlibs/ecp5/Makefile.inc3
-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.v160
-rw-r--r--techlibs/ecp5/cells_sim.v2
-rw-r--r--techlibs/ecp5/ecp5_ffinit.cc197
-rw-r--r--techlibs/ecp5/ecp5_gsr.cc4
-rw-r--r--techlibs/ecp5/lutrams.txt2
-rw-r--r--techlibs/ecp5/synth_ecp5.cc33
-rw-r--r--techlibs/efinix/Makefile.inc2
-rw-r--r--techlibs/efinix/arith_map.v4
-rw-r--r--techlibs/efinix/cells_map.v66
-rw-r--r--techlibs/efinix/cells_sim.v6
-rw-r--r--techlibs/efinix/efinix_fixcarry.cc2
-rw-r--r--techlibs/efinix/efinix_gbuf.cc119
-rw-r--r--techlibs/efinix/gbuf_map.v3
-rw-r--r--techlibs/efinix/synth_efinix.cc10
-rw-r--r--techlibs/gatemate/Makefile.inc14
-rw-r--r--techlibs/gatemate/arith_map.v (renamed from techlibs/intel/arria10gx/cells_arith.v)140
-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/Makefile.inc1
-rw-r--r--techlibs/gowin/arith_map.v4
-rw-r--r--techlibs/gowin/cells_map.v186
-rw-r--r--techlibs/gowin/cells_sim.v677
-rw-r--r--techlibs/gowin/determine_init.cc72
-rw-r--r--techlibs/gowin/lutrams_map.v5
-rw-r--r--techlibs/gowin/synth_gowin.cc87
-rw-r--r--techlibs/greenpak4/greenpak4_dffinv.cc2
-rw-r--r--techlibs/greenpak4/synth_greenpak4.cc5
-rw-r--r--techlibs/ice40/Makefile.inc2
-rw-r--r--techlibs/ice40/abc9_model.v42
-rw-r--r--techlibs/ice40/arith_map.v2
-rw-r--r--techlibs/ice40/brams_map.v73
-rw-r--r--techlibs/ice40/cells_sim.v1164
-rw-r--r--techlibs/ice40/ff_map.v43
-rw-r--r--techlibs/ice40/ice40_braminit.cc2
-rw-r--r--techlibs/ice40/ice40_ffinit.cc179
-rw-r--r--techlibs/ice40/ice40_ffssr.cc131
-rw-r--r--techlibs/ice40/ice40_opt.cc6
-rw-r--r--techlibs/ice40/synth_ice40.cc24
-rw-r--r--techlibs/intel/Makefile.inc3
-rw-r--r--techlibs/intel/arria10gx/cells_map.v54
-rw-r--r--techlibs/intel/arria10gx/cells_sim.v59
-rw-r--r--techlibs/intel/common/altpll_bb.v2
-rw-r--r--techlibs/intel/common/ff_map.v11
-rw-r--r--techlibs/intel/common/m9k_bb.v4
-rw-r--r--techlibs/intel/cyclone10lp/cells_arith.v2
-rw-r--r--techlibs/intel/cyclone10lp/cells_map.v37
-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.v37
-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.v37
-rw-r--r--techlibs/intel/cycloneive/cells_sim.v2
-rw-r--r--techlibs/intel/cyclonev/cells_arith.v71
-rw-r--r--techlibs/intel/cyclonev/cells_map.v163
-rw-r--r--techlibs/intel/max10/cells_arith.v2
-rw-r--r--techlibs/intel/max10/cells_map.v37
-rw-r--r--techlibs/intel/max10/cells_sim.v2
-rw-r--r--techlibs/intel/synth_intel.cc26
-rw-r--r--techlibs/intel_alm/Makefile.inc14
-rw-r--r--techlibs/intel_alm/common/abc9_map.v18
-rw-r--r--techlibs/intel_alm/common/abc9_model.v10
-rw-r--r--techlibs/intel_alm/common/abc9_unmap.v11
-rw-r--r--techlibs/intel_alm/common/alm_sim.v156
-rw-r--r--techlibs/intel_alm/common/arith_alm_map.v2
-rw-r--r--techlibs/intel_alm/common/bram_m10k.txt16
-rw-r--r--techlibs/intel_alm/common/bram_m10k_map.v31
-rw-r--r--techlibs/intel_alm/common/bram_m20k_map.v62
-rw-r--r--techlibs/intel_alm/common/dff_map.v123
-rw-r--r--techlibs/intel_alm/common/dff_sim.v47
-rw-r--r--techlibs/intel_alm/common/dsp_map.v51
-rw-r--r--techlibs/intel_alm/common/dsp_sim.v130
-rw-r--r--techlibs/intel_alm/common/megafunction_bb.v586
-rw-r--r--techlibs/intel_alm/common/mem_sim.v97
-rw-r--r--techlibs/intel_alm/common/misc_sim.v21
-rw-r--r--techlibs/intel_alm/common/quartus_rename.v187
-rw-r--r--techlibs/intel_alm/cyclonev/cells_sim.v (renamed from techlibs/intel/cyclonev/cells_sim.v)30
-rw-r--r--techlibs/intel_alm/synth_intel_alm.cc130
-rw-r--r--techlibs/machxo2/Makefile.inc5
-rw-r--r--techlibs/machxo2/cells_map.v34
-rw-r--r--techlibs/machxo2/cells_sim.v212
-rw-r--r--techlibs/machxo2/synth_machxo2.cc249
-rw-r--r--techlibs/nexus/Makefile.inc18
-rw-r--r--techlibs/nexus/arith_map.v99
-rw-r--r--techlibs/nexus/brams.txt63
-rw-r--r--techlibs/nexus/brams_init.vh64
-rw-r--r--techlibs/nexus/brams_map.v115
-rw-r--r--techlibs/nexus/cells_map.v98
-rw-r--r--techlibs/nexus/cells_sim.v1058
-rw-r--r--techlibs/nexus/cells_xtra.py286
-rw-r--r--techlibs/nexus/cells_xtra.v10389
-rw-r--r--techlibs/nexus/dsp_map.v79
-rw-r--r--techlibs/nexus/latches_map.v11
-rw-r--r--techlibs/nexus/lrams.txt22
-rw-r--r--techlibs/nexus/lrams_init.vh128
-rw-r--r--techlibs/nexus/lrams_map.v56
-rw-r--r--techlibs/nexus/lutrams.txt26
-rw-r--r--techlibs/nexus/lutrams_map.v34
-rw-r--r--techlibs/nexus/parse_init.vh33
-rw-r--r--techlibs/nexus/synth_nexus.cc426
-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/Makefile.inc1
-rw-r--r--techlibs/sf2/arith_map.v2
-rw-r--r--techlibs/sf2/cells_map.v56
-rw-r--r--techlibs/sf2/cells_sim.v147
-rw-r--r--techlibs/sf2/sf2_iobs.cc197
-rw-r--r--techlibs/sf2/synth_sf2.cc18
-rw-r--r--techlibs/xilinx/Makefile.inc3
-rw-r--r--techlibs/xilinx/abc9_model.v2
-rw-r--r--techlibs/xilinx/arith_map.v120
-rw-r--r--techlibs/xilinx/cells_map.v47
-rw-r--r--techlibs/xilinx/cells_sim.v289
-rw-r--r--techlibs/xilinx/cells_xtra.py259
-rw-r--r--techlibs/xilinx/cells_xtra.v6840
-rw-r--r--techlibs/xilinx/ff_map.v120
-rw-r--r--techlibs/xilinx/lut_map.v2
-rw-r--r--techlibs/xilinx/mux_map.v2
-rw-r--r--techlibs/xilinx/synth_xilinx.cc77
-rw-r--r--techlibs/xilinx/xc6s_ff_map.v256
-rw-r--r--techlibs/xilinx/xc7_brams_map.v10
-rw-r--r--techlibs/xilinx/xc7_dsp_map.v1
-rw-r--r--techlibs/xilinx/xc7_ff_map.v178
-rw-r--r--techlibs/xilinx/xilinx_dffopt.cc8
-rw-r--r--tests/aiger/.gitignore4
-rwxr-xr-xtests/aiger/run-test.sh2
-rw-r--r--tests/arch/anlogic/blockram.ys13
-rw-r--r--tests/arch/anlogic/dffs.ys3
-rw-r--r--tests/arch/anlogic/latches.ys26
-rw-r--r--tests/arch/anlogic/lutram.ys11
-rwxr-xr-xtests/arch/anlogic/run-test.sh22
-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/mul.v7
-rw-r--r--tests/arch/common/shifter.v28
-rw-r--r--tests/arch/ecp5/bug2409.ys24
-rw-r--r--tests/arch/ecp5/bug2731.ys7
-rw-r--r--tests/arch/ecp5/fsm.ys6
-rw-r--r--tests/arch/ecp5/lutram.ys8
-rw-r--r--tests/arch/ecp5/memories.ys187
-rw-r--r--tests/arch/ecp5/mux.ys18
-rwxr-xr-xtests/arch/ecp5/run-test.sh22
-rw-r--r--tests/arch/efinix/adffs.ys6
-rw-r--r--tests/arch/efinix/dffs.ys3
-rwxr-xr-xtests/arch/efinix/run-test.sh22
-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/init-error.ys5
-rw-r--r--tests/arch/gowin/init.ys31
-rw-r--r--tests/arch/gowin/lutram.ys5
-rwxr-xr-xtests/arch/gowin/run-test.sh22
-rw-r--r--tests/arch/gowin/tribuf.ys3
-rw-r--r--tests/arch/ice40/bug2061.ys24
-rw-r--r--tests/arch/ice40/fsm.ys2
-rw-r--r--tests/arch/ice40/memories.ys97
-rwxr-xr-xtests/arch/ice40/run-test.sh22
-rw-r--r--tests/arch/intel_alm/add_sub.ys14
-rw-r--r--tests/arch/intel_alm/adffs.ys60
-rw-r--r--tests/arch/intel_alm/blockram.ys6
-rw-r--r--tests/arch/intel_alm/counter.ys18
-rw-r--r--tests/arch/intel_alm/dffs.ys26
-rw-r--r--tests/arch/intel_alm/fsm.ys35
-rw-r--r--tests/arch/intel_alm/logic.ys16
-rw-r--r--tests/arch/intel_alm/lutram.ys29
-rw-r--r--tests/arch/intel_alm/mul.ys60
-rw-r--r--tests/arch/intel_alm/mux.ys53
-rw-r--r--tests/arch/intel_alm/quartus_ice.ys14
-rwxr-xr-xtests/arch/intel_alm/run-test.sh22
-rw-r--r--tests/arch/intel_alm/shifter.ys13
-rw-r--r--tests/arch/intel_alm/tribuf.ys16
-rw-r--r--tests/arch/machxo2/.gitignore2
-rw-r--r--tests/arch/machxo2/add_sub.ys8
-rw-r--r--tests/arch/machxo2/dffs.ys19
-rw-r--r--tests/arch/machxo2/fsm.ys15
-rw-r--r--tests/arch/machxo2/logic.ys8
-rw-r--r--tests/arch/machxo2/mux.ys40
-rw-r--r--tests/arch/machxo2/run-test.sh4
-rw-r--r--tests/arch/machxo2/shifter.ys10
-rw-r--r--tests/arch/machxo2/tribuf.ys10
-rw-r--r--tests/arch/nexus/.gitignore2
-rw-r--r--tests/arch/nexus/add_sub.ys21
-rw-r--r--tests/arch/nexus/adffs.ys44
-rw-r--r--tests/arch/nexus/blockram.ys18
-rw-r--r--tests/arch/nexus/blockram_dc.v25
-rw-r--r--tests/arch/nexus/counter.ys11
-rw-r--r--tests/arch/nexus/dffs.ys19
-rw-r--r--tests/arch/nexus/fsm.ys19
-rw-r--r--tests/arch/nexus/logic.ys8
-rw-r--r--tests/arch/nexus/lutram.ys19
-rw-r--r--tests/arch/nexus/mul.ys50
-rw-r--r--tests/arch/nexus/mux.ys43
-rw-r--r--tests/arch/nexus/run-test.sh4
-rw-r--r--tests/arch/nexus/shifter.ys9
-rw-r--r--tests/arch/nexus/tribuf.ys12
-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/attributes_test.ys6
-rw-r--r--tests/arch/xilinx/dsp_abc9.ys37
-rw-r--r--tests/arch/xilinx/fsm.ys15
-rw-r--r--tests/arch/xilinx/latches.ys3
-rw-r--r--tests/arch/xilinx/mux.ys3
-rw-r--r--tests/arch/xilinx/nosrl.ys41
-rw-r--r--tests/arch/xilinx/pmgen_xilinx_srl.ys2
-rwxr-xr-xtests/arch/xilinx/run-test.sh22
-rw-r--r--tests/arch/xilinx/tribuf.sh4
-rw-r--r--tests/arch/xilinx/xilinx_dffopt.ys46
-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
-rwxr-xr-xtests/gen-tests-makefile.sh94
-rwxr-xr-xtests/liberty/run-test.sh2
-rw-r--r--tests/memories/read_arst.v27
-rw-r--r--tests/memories/read_two_mux.v5
-rwxr-xr-xtests/memories/run-test.sh38
-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/.gitignore1
-rw-r--r--tests/opt/bug1854.ys17
-rw-r--r--tests/opt/bug2221.ys16
-rw-r--r--tests/opt/bug2311.ys14
-rw-r--r--tests/opt/bug2318.ys12
-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.ys48
-rw-r--r--tests/opt/opt_dff_arst.ys101
-rw-r--r--tests/opt/opt_dff_clk.ys45
-rw-r--r--tests/opt/opt_dff_const.ys49
-rw-r--r--tests/opt/opt_dff_dffmux.ys129
-rw-r--r--tests/opt/opt_dff_en.ys157
-rw-r--r--tests/opt/opt_dff_mux.ys86
-rw-r--r--tests/opt/opt_dff_qd.ys56
-rw-r--r--tests/opt/opt_dff_sr.ys309
-rw-r--r--tests/opt/opt_dff_srst.ys113
-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/opt/opt_rmdff.ys3
-rw-r--r--tests/opt/opt_rmdff_sat.ys4
-rw-r--r--tests/opt/opt_share_bug2334.ys13
-rw-r--r--tests/opt/opt_share_bug2335.ys27
-rw-r--r--tests/opt/opt_share_bug2336.ys14
-rw-r--r--tests/opt/opt_share_bug2538.ys20
-rwxr-xr-xtests/opt/run-test.sh8
-rwxr-xr-xtests/opt_share/run-test.sh21
-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/.gitignore3
-rw-r--r--tests/sat/alu.v79
-rw-r--r--tests/sat/bug2595.ys18
-rw-r--r--tests/sat/dff.ys21
-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
-rwxr-xr-xtests/sat/run-test.sh10
-rw-r--r--tests/sat/sim_counter.ys48
-rw-r--r--tests/sat/sizebits.sv61
-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.v36
-rw-r--r--tests/simple/const_fold_func.v61
-rw-r--r--tests/simple/const_func_shadow.v33
-rw-r--r--tests/simple/defvalue.sv2
-rw-r--r--tests/simple/func_block.v33
-rw-r--r--tests/simple/func_recurse.v25
-rw-r--r--tests/simple/func_width_scope.v41
-rw-r--r--tests/simple/genblk_collide.v27
-rw-r--r--tests/simple/genblk_dive.v21
-rw-r--r--tests/simple/genblk_order.v18
-rw-r--r--tests/simple/genblk_port_shadow.v10
-rw-r--r--tests/simple/generate.v164
-rw-r--r--tests/simple/hierarchy.v2
-rw-r--r--tests/simple/ifdef_1.v88
-rw-r--r--tests/simple/ifdef_2.v21
-rw-r--r--tests/simple/lesser_size_cast.sv7
-rw-r--r--tests/simple/local_loop_var.sv11
-rw-r--r--tests/simple/loop_prefix_case.v18
-rw-r--r--tests/simple/loop_var_shadow.v15
-rw-r--r--tests/simple/macro_arg_spaces.sv28
-rw-r--r--tests/simple/macro_arg_surrounding_spaces.v20
-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.v27
-rw-r--r--tests/simple/nested_genblk_resolve.v14
-rwxr-xr-xtests/simple/run-test.sh1
-rw-r--r--tests/simple/signed_full_slice.v29
-rw-r--r--tests/simple/string_format.v7
-rw-r--r--tests/simple/unnamed_block_decl.sv17
-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/.gitignore1
-rw-r--r--tests/simple_abc9/abc9.box3
-rw-r--r--tests/simple_abc9/abc9.v24
-rwxr-xr-xtests/simple_abc9/run-test.sh30
-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/multirange_array.sv16
-rw-r--r--tests/svtypes/multirange_subarray_access.ys12
-rwxr-xr-xtests/svtypes/run-test.sh22
-rw-r--r--tests/svtypes/struct_array.sv22
-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/svtypes/typedef_struct_port.sv111
-rw-r--r--tests/svtypes/typedef_struct_port.ys6
-rw-r--r--tests/techmap/adff2dff.ys19
-rw-r--r--tests/techmap/bug2183.ys11
-rw-r--r--tests/techmap/bug2321.ys15
-rw-r--r--tests/techmap/bug2332.ys11
-rw-r--r--tests/techmap/bug2759.ys14
-rw-r--r--tests/techmap/bug2972.ys20
-rw-r--r--tests/techmap/cellname.ys41
-rw-r--r--tests/techmap/clkbufmap.ys79
-rw-r--r--tests/techmap/dff2dffs.ys50
-rw-r--r--tests/techmap/dff2ff.ys16
-rw-r--r--tests/techmap/dfflegalize_adff.ys135
-rw-r--r--tests/techmap/dfflegalize_adff_init.ys333
-rw-r--r--tests/techmap/dfflegalize_adlatch.ys51
-rw-r--r--tests/techmap/dfflegalize_adlatch_init.ys99
-rw-r--r--tests/techmap/dfflegalize_aldff.ys92
-rw-r--r--tests/techmap/dfflegalize_aldff_init.ys148
-rw-r--r--tests/techmap/dfflegalize_dff.ys351
-rw-r--r--tests/techmap/dfflegalize_dff_init.ys868
-rw-r--r--tests/techmap/dfflegalize_dffsr.ys88
-rw-r--r--tests/techmap/dfflegalize_dffsr_init.ys379
-rw-r--r--tests/techmap/dfflegalize_dlatch.ys64
-rw-r--r--tests/techmap/dfflegalize_dlatch_const.ys53
-rw-r--r--tests/techmap/dfflegalize_dlatch_init.ys120
-rw-r--r--tests/techmap/dfflegalize_dlatchsr.ys37
-rw-r--r--tests/techmap/dfflegalize_dlatchsr_init.ys127
-rw-r--r--tests/techmap/dfflegalize_inv.ys191
-rw-r--r--tests/techmap/dfflegalize_mince.ys53
-rw-r--r--tests/techmap/dfflegalize_minsrst.ys43
-rw-r--r--tests/techmap/dfflegalize_sr.ys74
-rw-r--r--tests/techmap/dfflegalize_sr_init.ys230
-rw-r--r--tests/techmap/dfflibmap-sim.v22
-rw-r--r--tests/techmap/dfflibmap.lib55
-rw-r--r--tests/techmap/dfflibmap.ys58
-rw-r--r--tests/techmap/dffunmap.ys100
-rw-r--r--tests/techmap/iopadmap.ys4
-rw-r--r--tests/techmap/mem_simple_4x1_runtest.sh4
-rw-r--r--tests/techmap/pmux2mux.ys15
-rw-r--r--tests/techmap/recursive_runtest.sh4
-rwxr-xr-xtests/techmap/run-test.sh22
-rw-r--r--tests/techmap/shiftx2mux.ys12
-rw-r--r--tests/techmap/zinit.ys9
-rwxr-xr-xtests/tools/autotest.sh6
-rwxr-xr-xtests/tools/vcdcd.pl6
-rw-r--r--tests/various/.gitignore1
-rw-r--r--tests/various/abc9.ys57
-rw-r--r--tests/various/async.sh8
-rw-r--r--tests/various/blackbox_wb.ys14
-rw-r--r--tests/various/const_arg_loop.sv92
-rw-r--r--tests/various/const_arg_loop.ys6
-rw-r--r--tests/various/const_func.sv (renamed from tests/various/const_func.v)49
-rw-r--r--tests/various/const_func.ys8
-rw-r--r--tests/various/const_func_block_var.v26
-rw-r--r--tests/various/const_func_block_var.ys1
-rw-r--r--tests/various/countbits.sv69
-rw-r--r--tests/various/countbits.ys7
-rw-r--r--tests/various/dynamic_part_select.ys76
-rw-r--r--tests/various/dynamic_part_select/forloop_select.v16
-rw-r--r--tests/various/dynamic_part_select/forloop_select_gate.v9
-rw-r--r--tests/various/dynamic_part_select/latch_002.v13
-rw-r--r--tests/various/dynamic_part_select/latch_002_gate.v18
-rw-r--r--tests/various/dynamic_part_select/latch_002_gate_good.v141
-rw-r--r--tests/various/dynamic_part_select/latch_1990.v12
-rw-r--r--tests/various/dynamic_part_select/latch_1990_gate.v6
-rw-r--r--tests/various/dynamic_part_select/multiple_blocking.v9
-rw-r--r--tests/various/dynamic_part_select/multiple_blocking_gate.v9
-rw-r--r--tests/various/dynamic_part_select/nonblocking.v9
-rw-r--r--tests/various/dynamic_part_select/nonblocking_gate.v9
-rw-r--r--tests/various/dynamic_part_select/original.v9
-rw-r--r--tests/various/dynamic_part_select/original_gate.v9
-rw-r--r--tests/various/dynamic_part_select/reset_test.v12
-rw-r--r--tests/various/dynamic_part_select/reset_test_gate.v12
-rw-r--r--tests/various/dynamic_part_select/reversed.v9
-rw-r--r--tests/various/dynamic_part_select/reversed_gate.v9
-rw-r--r--tests/various/equiv_opt_undef.ys35
-rw-r--r--tests/various/fib.v65
-rw-r--r--tests/various/fib.ys6
-rw-r--r--tests/various/fib_tern.v70
-rw-r--r--tests/various/fib_tern.ys6
-rw-r--r--tests/various/func_port_implied_dir.sv23
-rw-r--r--tests/various/func_port_implied_dir.ys6
-rw-r--r--tests/various/gen_if_null.v12
-rw-r--r--tests/various/gen_if_null.ys4
-rw-r--r--tests/various/integer_range_bad_syntax.ys6
-rw-r--r--tests/various/integer_real_bad_syntax.ys6
-rwxr-xr-xtests/various/logger_fail.sh42
-rw-r--r--tests/various/logic_param_simple.ys9
-rw-r--r--tests/various/memory_word_as_index.data4
-rw-r--r--tests/various/memory_word_as_index.v21
-rw-r--r--tests/various/memory_word_as_index.ys23
-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/peepopt.ys143
-rw-r--r--tests/various/port_sign_extend.v95
-rw-r--r--tests/various/port_sign_extend.ys29
-rw-r--r--tests/various/rand_const.sv8
-rw-r--r--tests/various/rand_const.ys1
-rwxr-xr-xtests/various/run-test.sh22
-rw-r--r--tests/various/sta.ys81
-rw-r--r--tests/verilog/.gitignore3
-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/atom_type_signedness.ys19
-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/block_labels.ys26
-rw-r--r--tests/verilog/bug2493.ys12
-rw-r--r--tests/verilog/bug656.v21
-rw-r--r--tests/verilog/bug656.ys13
-rw-r--r--tests/verilog/conflict_assert.ys8
-rw-r--r--tests/verilog/conflict_cell_memory.ys9
-rw-r--r--tests/verilog/conflict_interface_port.ys17
-rw-r--r--tests/verilog/conflict_memory_wire.ys7
-rw-r--r--tests/verilog/conflict_pwire.ys8
-rw-r--r--tests/verilog/conflict_wire_memory.ys7
-rw-r--r--tests/verilog/const_arst.ys24
-rw-r--r--tests/verilog/const_sr.ys25
-rw-r--r--tests/verilog/delay_mintypmax.ys213
-rw-r--r--tests/verilog/delay_risefall.ys225
-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_arg_mismatch_1.ys12
-rw-r--r--tests/verilog/func_arg_mismatch_2.ys12
-rw-r--r--tests/verilog/func_arg_mismatch_3.ys12
-rw-r--r--tests/verilog/func_arg_mismatch_4.ys12
-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/genblk_case.v26
-rw-r--r--tests/verilog/genblk_case.ys15
-rw-r--r--tests/verilog/genblk_port_decl.ys12
-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/hidden_decl.ys11
-rw-r--r--tests/verilog/ifdef_nest.ys7
-rw-r--r--tests/verilog/ifdef_unterminated.ys4
-rw-r--r--tests/verilog/include_self.v30
-rw-r--r--tests/verilog/include_self.ys2
-rw-r--r--tests/verilog/int_types.sv47
-rw-r--r--tests/verilog/int_types.ys7
-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/macro_unapplied.ys17
-rw-r--r--tests/verilog/macro_unapplied_newline.ys5
-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_int_types.sv19
-rw-r--r--tests/verilog/param_int_types.ys5
-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/port_int_types.sv50
-rw-r--r--tests/verilog/port_int_types.ys11
-rw-r--r--tests/verilog/prefix.sv95
-rw-r--r--tests/verilog/prefix.ys5
-rwxr-xr-xtests/verilog/run-test.sh22
-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_else.ys6
-rw-r--r--tests/verilog/unmatched_elsif.ys6
-rw-r--r--tests/verilog/unmatched_endif.ys6
-rw-r--r--tests/verilog/unmatched_endif_2.ys7
-rw-r--r--tests/verilog/unnamed_block.ys28
-rw-r--r--tests/verilog/unnamed_genblk.sv39
-rw-r--r--tests/verilog/unnamed_genblk.ys8
-rw-r--r--tests/verilog/wire_and_var.sv33
-rw-r--r--tests/verilog/wire_and_var.ys9
-rwxr-xr-xtests/vloghtb/run-test.sh2
1014 files changed, 82057 insertions, 19133 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/issue_template.md b/.github/issue_template.md
index 5a0723c3e..c72daae3e 100644
--- a/.github/issue_template.md
+++ b/.github/issue_template.md
@@ -13,7 +13,7 @@ create a Minimal, Complete, and Verifiable example (MCVE).
Please do not waste our time with issues that lack sufficient information
to reproduce the issue easily. We will simply close those issues.
-Contact https://www.symbioticeda.com/ if you need commercial support for Yosys.
+Contact https://www.yosyshq.com/ if you need commercial support for Yosys.
## Expected behavior
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/Brewfile b/Brewfile
index 2a985f09e..b50c70a4b 100644
--- a/Brewfile
+++ b/Brewfile
@@ -9,3 +9,4 @@ brew "python3"
brew "tcl-tk"
brew "xdot"
brew "bash"
+brew 'boost-python3'
diff --git a/CHANGELOG b/CHANGELOG
index 638ce558b..1451ea07c 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,71 +2,246 @@
List of major changes and improvements between releases
=======================================================
+Yosys 0.14 .. Yosys 0.14-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.9 .. Yosys 0.9-dev
+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_*_" attribute 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
- - Removed "dffsr2dff" (use opt_rmdff instead)
- - Added "design -delete"
- - Added "select -unset"
- - Use YosysHQ/abc instead of upstream berkeley-abc/abc
- - Added $divfloor and $modfloor cells
+
+ * 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 e3787e429..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
@@ -25,7 +27,12 @@ passes/opt/opt_lut.cc @whitequark
# These still override previous lines, so be careful not to
# accidentally disable any of the above rules.
+frontends/verilog/ @zachjs
+frontends/ast/ @zachjs
+
techlibs/intel_alm/ @ZirconiumX
+techlibs/gowin/ @pepijndevos
+techlibs/gatemate/ @pu-cc
# pyosys
misc/*.py @btut
@@ -33,6 +40,7 @@ misc/*.py @btut
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 3d3e60359..6e7e9f59f 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@ CONFIG := clang
# CONFIG := emcc
# CONFIG := wasi
# CONFIG := mxe
-# CONFIG := msys2
+# CONFIG := msys2-32
# CONFIG := msys2-64
# features (the more the better)
@@ -16,7 +16,10 @@ ENABLE_GLOB := 1
ENABLE_PLUGINS := 1
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
@@ -30,6 +33,9 @@ ENABLE_GCOV := 0
ENABLE_GPROF := 0
ENABLE_DEBUG := 0
ENABLE_NDEBUG := 0
+ENABLE_CCACHE := 0
+# sccache is not always a drop-in replacement for ccache in practice
+ENABLE_SCCACHE := 0
LINK_CURSES := 0
LINK_TERMCAP := 0
LINK_ABC := 0
@@ -81,7 +87,8 @@ all: top-all
YOSYS_SRC := $(dir $(firstword $(MAKEFILE_LIST)))
VPATH := $(YOSYS_SRC)
-CXXFLAGS := $(CXXFLAGS) -Wall -Wextra -ggdb -I. -I"$(YOSYS_SRC)" -MD -D_YOSYS_ -fPIC -I$(PREFIX)/include
+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 :=
@@ -122,12 +129,12 @@ LDFLAGS += -rdynamic
LDLIBS += -lrt
endif
-YOSYS_VER := 0.9+2406
-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
#
@@ -135,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 = 341db25
+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.
@@ -170,8 +177,7 @@ else
PYTHON_CONFIG := $(PYTHON_EXECUTABLE)-config
endif
-PYTHON_PREFIX := $(shell $(PYTHON_CONFIG) --prefix)
-PYTHON_DESTDIR := $(PYTHON_PREFIX)/lib/python$(PYTHON_VERSION)/site-packages
+PYTHON_DESTDIR := $(shell $(PYTHON_EXECUTABLE) -c "import site; print(site.getsitepackages()[-1]);")
# Reload Makefile.conf to override python specific variables if defined
ifneq ($(wildcard Makefile.conf),)
@@ -183,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
@@ -206,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)
@@ -214,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)
@@ -224,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)
@@ -242,11 +248,11 @@ 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
-EMCCFLAGS += -s EXPORTED_FUNCTIONS="['_main','_run','_prompt','_errmsg']"
+EMCCFLAGS += -s EXPORTED_FUNCTIONS="['_main','_run','_prompt','_errmsg','_memset']"
EMCCFLAGS += -s TOTAL_MEMORY=134217728
EMCCFLAGS += -s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]'
# https://github.com/kripken/emscripten/blob/master/src/settings.js
@@ -292,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)"
@@ -311,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))
@@ -320,10 +326,10 @@ ABCMKARGS += ARCHFLAGS="-DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w"
ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" LDFLAGS="-Wl,--allow-multiple-definition" ABC_USE_NO_READLINE=1 CC="/usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-gcc"
EXE = .exe
-else ifeq ($(CONFIG),msys2)
+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))
@@ -334,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))
@@ -343,7 +349,7 @@ ABCMKARGS += LIBS="-lpthread -s" ABC_USE_NO_READLINE=0 CC="x86_64-w64-mingw32-gc
EXE = .exe
else ifneq ($(CONFIG),none)
-$(error Invalid CONFIG setting '$(CONFIG)'. Valid values: clang, gcc, gcc-4.8, emcc, mxe, msys2, msys2-64)
+$(error Invalid CONFIG setting '$(CONFIG)'. Valid values: clang, gcc, gcc-4.8, emcc, mxe, msys2-32, msys2-64)
endif
ifeq ($(ENABLE_LIBYOSYS),1)
@@ -351,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)
+# 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 $(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
-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
@@ -509,9 +491,29 @@ endif
endif
endif
+ifeq ($(ENABLE_GHDL),1)
+GHDL_PREFIX ?= $(PREFIX)
+GHDL_INCLUDE_DIR ?= $(GHDL_PREFIX)/include
+GHDL_LIB_DIR ?= $(GHDL_PREFIX)/lib
+CXXFLAGS += -I$(GHDL_INCLUDE_DIR) -DYOSYS_ENABLE_GHDL
+LDLIBS += $(GHDL_LIB_DIR)/libghdl.a $(file <$(GHDL_LIB_DIR)/libghdl.link)
+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
@@ -528,6 +530,14 @@ ifeq ($(ENABLE_COVER),1)
CXXFLAGS += -DYOSYS_ENABLE_COVER
endif
+ifeq ($(ENABLE_CCACHE),1)
+CXX := ccache $(CXX)
+else
+ifeq ($(ENABLE_SCCACHE),1)
+CXX := sccache $(CXX)
+endif
+endif
+
define add_share_file
EXTRA_TARGETS += $(subst //,/,$(1)/$(notdir $(2)))
$(subst //,/,$(1)/$(notdir $(2))): $(2)
@@ -570,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))
@@ -580,13 +591,21 @@ $(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,backends/ilang/ilang_backend.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))
$(eval $(call add_include_file,backends/cxxrtl/cxxrtl_capi.cc))
@@ -595,7 +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/cellaigs.o kernel/celledges.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/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)"'
@@ -619,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
@@ -627,7 +656,7 @@ include $(YOSYS_SRC)/techlibs/*/Makefile.inc
else
include $(YOSYS_SRC)/frontends/verilog/Makefile.inc
-include $(YOSYS_SRC)/frontends/ilang/Makefile.inc
+include $(YOSYS_SRC)/frontends/rtlil/Makefile.inc
include $(YOSYS_SRC)/frontends/ast/Makefile.inc
include $(YOSYS_SRC)/frontends/blif/Makefile.inc
@@ -644,7 +673,7 @@ include $(YOSYS_SRC)/passes/opt/Makefile.inc
include $(YOSYS_SRC)/passes/techmap/Makefile.inc
include $(YOSYS_SRC)/backends/verilog/Makefile.inc
-include $(YOSYS_SRC)/backends/ilang/Makefile.inc
+include $(YOSYS_SRC)/backends/rtlil/Makefile.inc
include $(YOSYS_SRC)/techlibs/common/Makefile.inc
@@ -654,6 +683,10 @@ ifeq ($(LINK_ABC),1)
OBJS += $(PROGRAM_PREFIX)yosys-libabc.a
endif
+# prevent the CXXFLAGS set by this Makefile from reaching abc/Makefile,
+# especially the -MD flag which will break the build when CXX is clang
+unexport CXXFLAGS
+
top-all: $(TARGETS) $(EXTRA_TARGETS)
@echo ""
@echo " Build successful."
@@ -668,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
@@ -679,7 +712,7 @@ endif
%.pyh: %.h
$(Q) mkdir -p $(dir $@)
- $(P) cat $< | grep -E -v "#[ ]*(include|error)" | $(LD) -x c++ -o $@ -E -P -
+ $(P) cat $< | grep -E -v "#[ ]*(include|error)" | $(LD) $(CXXFLAGS) -x c++ -o $@ -E -P -
ifeq ($(ENABLE_PYOSYS),1)
$(PY_WRAPPER_FILE).cc: misc/$(PY_GEN_SCRIPT).py $(PY_WRAP_INCLUDES)
@@ -718,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
@@ -730,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)
@@ -773,16 +806,21 @@ 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
+cd tests/arch/ice40 && bash run-test.sh $(SEEDOPT)
+cd tests/arch/xilinx && bash run-test.sh $(SEEDOPT)
+cd tests/arch/ecp5 && bash run-test.sh $(SEEDOPT)
+ +cd tests/arch/machxo2 && bash run-test.sh $(SEEDOPT)
+cd tests/arch/efinix && bash run-test.sh $(SEEDOPT)
+cd tests/arch/anlogic && bash run-test.sh $(SEEDOPT)
+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
@@ -839,9 +877,9 @@ ifeq ($(ENABLE_LIBYOSYS),1)
$(INSTALL_SUDO) cp libyosys.so $(DESTDIR)$(LIBDIR)/
$(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(LIBDIR)/libyosys.so
ifeq ($(ENABLE_PYOSYS),1)
- $(INSTALL_SUDO) mkdir -p $(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys
- $(INSTALL_SUDO) cp libyosys.so $(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/libyosys.so
- $(INSTALL_SUDO) cp misc/__init__.py $(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/
+ $(INSTALL_SUDO) mkdir -p $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys
+ $(INSTALL_SUDO) cp libyosys.so $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/libyosys.so
+ $(INSTALL_SUDO) cp misc/__init__.py $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/
endif
endif
@@ -851,9 +889,9 @@ uninstall:
ifeq ($(ENABLE_LIBYOSYS),1)
$(INSTALL_SUDO) rm -vf $(DESTDIR)$(LIBDIR)/libyosys.so
ifeq ($(ENABLE_PYOSYS),1)
- $(INSTALL_SUDO) rm -vf $(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/libyosys.so
- $(INSTALL_SUDO) rm -vf $(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/__init__.py
- $(INSTALL_SUDO) rmdir $(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys
+ $(INSTALL_SUDO) rm -vf $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/libyosys.so
+ $(INSTALL_SUDO) rm -vf $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/__init__.py
+ $(INSTALL_SUDO) rmdir $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys
endif
endif
@@ -921,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
@@ -966,13 +1004,15 @@ config-mxe: clean
echo 'CONFIG := mxe' > Makefile.conf
echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
-config-msys2: clean
- echo 'CONFIG := msys2' > Makefile.conf
+config-msys2-32: clean
+ echo 'CONFIG := msys2-32' > Makefile.conf
echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
+ echo "PREFIX := $(MINGW_PREFIX)" >> Makefile.conf
config-msys2-64: clean
echo 'CONFIG := msys2-64' > Makefile.conf
echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
+ echo "PREFIX := $(MINGW_PREFIX)" >> Makefile.conf
config-cygwin: clean
echo 'CONFIG := cygwin' > Makefile.conf
@@ -1007,4 +1047,3 @@ echo-abc-rev:
.PHONY: all top-all abc test install install-abc manual clean mrproper qtcreator coverage vcxsrc mxebin
.PHONY: config-clean config-clang config-gcc config-gcc-static config-gcc-4.8 config-afl-gcc config-gprof config-sudo
-
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 81a3f483b..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
@@ -111,7 +111,7 @@ struct AigerWriter
// promote public wires
for (auto wire : module->wires())
- if (wire->name[0] == '\\')
+ if (wire->name.isPublic())
sigmap.add(wire);
// promote input wires
diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc
index ef0103c17..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
@@ -146,7 +146,7 @@ struct XAigerWriter
// promote public wires
for (auto wire : module->wires())
- if (wire->name[0] == '\\')
+ if (wire->name.isPublic())
sigmap.add(wire);
// promote input wires
@@ -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 780a16320..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
@@ -86,20 +86,18 @@ struct BlifDumper
}
}
- vector<shared_str> cstr_buf;
pool<SigBit> cstr_bits_seen;
- const char *cstr(RTLIL::IdString id)
+ const std::string str(RTLIL::IdString id)
{
std::string str = RTLIL::unescape_id(id);
for (size_t i = 0; i < str.size(); i++)
if (str[i] == '#' || str[i] == '=' || str[i] == '<' || str[i] == '>')
str[i] = '?';
- cstr_buf.push_back(str);
- return cstr_buf.back().c_str();
+ return str;
}
- const char *cstr(RTLIL::SigBit sig)
+ const std::string str(RTLIL::SigBit sig)
{
cstr_bits_seen.insert(sig);
@@ -117,11 +115,10 @@ struct BlifDumper
if (sig.wire->width != 1)
str += stringf("[%d]", sig.wire->upto ? sig.wire->start_offset+sig.wire->width-sig.offset-1 : sig.wire->start_offset+sig.offset);
- cstr_buf.push_back(str);
- return cstr_buf.back().c_str();
+ return str;
}
- const char *cstr_init(RTLIL::SigBit sig)
+ const std::string str_init(RTLIL::SigBit sig)
{
sigmap.apply(sig);
@@ -130,8 +127,7 @@ struct BlifDumper
string str = stringf(" %d", init_bits.at(sig));
- cstr_buf.push_back(str);
- return cstr_buf.back().c_str();
+ return str;
}
const char *subckt_or_gate(std::string cell_type)
@@ -168,7 +164,7 @@ struct BlifDumper
void dump()
{
f << stringf("\n");
- f << stringf(".model %s\n", cstr(module->name));
+ f << stringf(".model %s\n", str(module->name).c_str());
std::map<int, RTLIL::Wire*> inputs, outputs;
@@ -183,7 +179,7 @@ struct BlifDumper
for (auto &it : inputs) {
RTLIL::Wire *wire = it.second;
for (int i = 0; i < wire->width; i++)
- f << stringf(" %s", cstr(RTLIL::SigSpec(wire, i)));
+ f << stringf(" %s", str(RTLIL::SigSpec(wire, i)).c_str());
}
f << stringf("\n");
@@ -191,7 +187,7 @@ struct BlifDumper
for (auto &it : outputs) {
RTLIL::Wire *wire = it.second;
for (int i = 0; i < wire->width; i++)
- f << stringf(" %s", cstr(RTLIL::SigSpec(wire, i)));
+ f << stringf(" %s", str(RTLIL::SigSpec(wire, i)).c_str());
}
f << stringf("\n");
@@ -233,131 +229,131 @@ struct BlifDumper
if (config->unbuf_types.count(cell->type)) {
auto portnames = config->unbuf_types.at(cell->type);
f << stringf(".names %s %s\n1 1\n",
- cstr(cell->getPort(portnames.first)), cstr(cell->getPort(portnames.second)));
+ str(cell->getPort(portnames.first)).c_str(), str(cell->getPort(portnames.second)).c_str());
continue;
}
if (!config->icells_mode && cell->type == ID($_NOT_)) {
f << stringf(".names %s %s\n0 1\n",
- cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::Y)));
+ str(cell->getPort(ID::A)).c_str(), str(cell->getPort(ID::Y)).c_str());
goto internal_cell;
}
if (!config->icells_mode && cell->type == ID($_AND_)) {
f << stringf(".names %s %s %s\n11 1\n",
- cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)), cstr(cell->getPort(ID::Y)));
+ str(cell->getPort(ID::A)).c_str(), str(cell->getPort(ID::B)).c_str(), str(cell->getPort(ID::Y)).c_str());
goto internal_cell;
}
if (!config->icells_mode && cell->type == ID($_OR_)) {
f << stringf(".names %s %s %s\n1- 1\n-1 1\n",
- cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)), cstr(cell->getPort(ID::Y)));
+ str(cell->getPort(ID::A)).c_str(), str(cell->getPort(ID::B)).c_str(), str(cell->getPort(ID::Y)).c_str());
goto internal_cell;
}
if (!config->icells_mode && cell->type == ID($_XOR_)) {
f << stringf(".names %s %s %s\n10 1\n01 1\n",
- cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)), cstr(cell->getPort(ID::Y)));
+ str(cell->getPort(ID::A)).c_str(), str(cell->getPort(ID::B)).c_str(), str(cell->getPort(ID::Y)).c_str());
goto internal_cell;
}
if (!config->icells_mode && cell->type == ID($_NAND_)) {
f << stringf(".names %s %s %s\n0- 1\n-0 1\n",
- cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)), cstr(cell->getPort(ID::Y)));
+ str(cell->getPort(ID::A)).c_str(), str(cell->getPort(ID::B)).c_str(), str(cell->getPort(ID::Y)).c_str());
goto internal_cell;
}
if (!config->icells_mode && cell->type == ID($_NOR_)) {
f << stringf(".names %s %s %s\n00 1\n",
- cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)), cstr(cell->getPort(ID::Y)));
+ str(cell->getPort(ID::A)).c_str(), str(cell->getPort(ID::B)).c_str(), str(cell->getPort(ID::Y)).c_str());
goto internal_cell;
}
if (!config->icells_mode && cell->type == ID($_XNOR_)) {
f << stringf(".names %s %s %s\n11 1\n00 1\n",
- cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)), cstr(cell->getPort(ID::Y)));
+ str(cell->getPort(ID::A)).c_str(), str(cell->getPort(ID::B)).c_str(), str(cell->getPort(ID::Y)).c_str());
goto internal_cell;
}
if (!config->icells_mode && cell->type == ID($_ANDNOT_)) {
f << stringf(".names %s %s %s\n10 1\n",
- cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)), cstr(cell->getPort(ID::Y)));
+ str(cell->getPort(ID::A)).c_str(), str(cell->getPort(ID::B)).c_str(), str(cell->getPort(ID::Y)).c_str());
goto internal_cell;
}
if (!config->icells_mode && cell->type == ID($_ORNOT_)) {
f << stringf(".names %s %s %s\n1- 1\n-0 1\n",
- cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)), cstr(cell->getPort(ID::Y)));
+ str(cell->getPort(ID::A)).c_str(), str(cell->getPort(ID::B)).c_str(), str(cell->getPort(ID::Y)).c_str());
goto internal_cell;
}
if (!config->icells_mode && cell->type == ID($_AOI3_)) {
f << stringf(".names %s %s %s %s\n-00 1\n0-0 1\n",
- cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)), cstr(cell->getPort(ID::C)), cstr(cell->getPort(ID::Y)));
+ str(cell->getPort(ID::A)).c_str(), str(cell->getPort(ID::B)).c_str(), str(cell->getPort(ID::C)).c_str(), str(cell->getPort(ID::Y)).c_str());
goto internal_cell;
}
if (!config->icells_mode && cell->type == ID($_OAI3_)) {
f << stringf(".names %s %s %s %s\n00- 1\n--0 1\n",
- cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)), cstr(cell->getPort(ID::C)), cstr(cell->getPort(ID::Y)));
+ str(cell->getPort(ID::A)).c_str(), str(cell->getPort(ID::B)).c_str(), str(cell->getPort(ID::C)).c_str(), str(cell->getPort(ID::Y)).c_str());
goto internal_cell;
}
if (!config->icells_mode && cell->type == ID($_AOI4_)) {
f << stringf(".names %s %s %s %s %s\n-0-0 1\n-00- 1\n0--0 1\n0-0- 1\n",
- cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)),
- cstr(cell->getPort(ID::C)), cstr(cell->getPort(ID::D)), cstr(cell->getPort(ID::Y)));
+ str(cell->getPort(ID::A)).c_str(), str(cell->getPort(ID::B)).c_str(),
+ str(cell->getPort(ID::C)).c_str(), str(cell->getPort(ID::D)).c_str(), str(cell->getPort(ID::Y)).c_str());
goto internal_cell;
}
if (!config->icells_mode && cell->type == ID($_OAI4_)) {
f << stringf(".names %s %s %s %s %s\n00-- 1\n--00 1\n",
- cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)),
- cstr(cell->getPort(ID::C)), cstr(cell->getPort(ID::D)), cstr(cell->getPort(ID::Y)));
+ str(cell->getPort(ID::A)).c_str(), str(cell->getPort(ID::B)).c_str(),
+ str(cell->getPort(ID::C)).c_str(), str(cell->getPort(ID::D)).c_str(), str(cell->getPort(ID::Y)).c_str());
goto internal_cell;
}
if (!config->icells_mode && cell->type == ID($_MUX_)) {
f << stringf(".names %s %s %s %s\n1-0 1\n-11 1\n",
- cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)),
- cstr(cell->getPort(ID::S)), cstr(cell->getPort(ID::Y)));
+ str(cell->getPort(ID::A)).c_str(), str(cell->getPort(ID::B)).c_str(),
+ str(cell->getPort(ID::S)).c_str(), str(cell->getPort(ID::Y)).c_str());
goto internal_cell;
}
if (!config->icells_mode && cell->type == ID($_NMUX_)) {
f << stringf(".names %s %s %s %s\n0-0 1\n-01 1\n",
- cstr(cell->getPort(ID::A)), cstr(cell->getPort(ID::B)),
- cstr(cell->getPort(ID::S)), cstr(cell->getPort(ID::Y)));
+ str(cell->getPort(ID::A)).c_str(), str(cell->getPort(ID::B)).c_str(),
+ str(cell->getPort(ID::S)).c_str(), str(cell->getPort(ID::Y)).c_str());
goto internal_cell;
}
if (!config->icells_mode && cell->type == ID($_FF_)) {
- f << stringf(".latch %s %s%s\n", cstr(cell->getPort(ID::D)), cstr(cell->getPort(ID::Q)),
- cstr_init(cell->getPort(ID::Q)));
+ f << stringf(".latch %s %s%s\n", str(cell->getPort(ID::D)).c_str(), str(cell->getPort(ID::Q)).c_str(),
+ str_init(cell->getPort(ID::Q)).c_str());
goto internal_cell;
}
if (!config->icells_mode && cell->type == ID($_DFF_N_)) {
- f << stringf(".latch %s %s fe %s%s\n", cstr(cell->getPort(ID::D)), cstr(cell->getPort(ID::Q)),
- cstr(cell->getPort(ID::C)), cstr_init(cell->getPort(ID::Q)));
+ f << stringf(".latch %s %s fe %s%s\n", str(cell->getPort(ID::D)).c_str(), str(cell->getPort(ID::Q)).c_str(),
+ str(cell->getPort(ID::C)).c_str(), str_init(cell->getPort(ID::Q)).c_str());
goto internal_cell;
}
if (!config->icells_mode && cell->type == ID($_DFF_P_)) {
- f << stringf(".latch %s %s re %s%s\n", cstr(cell->getPort(ID::D)), cstr(cell->getPort(ID::Q)),
- cstr(cell->getPort(ID::C)), cstr_init(cell->getPort(ID::Q)));
+ f << stringf(".latch %s %s re %s%s\n", str(cell->getPort(ID::D)).c_str(), str(cell->getPort(ID::Q)).c_str(),
+ str(cell->getPort(ID::C)).c_str(), str_init(cell->getPort(ID::Q)).c_str());
goto internal_cell;
}
if (!config->icells_mode && cell->type == ID($_DLATCH_N_)) {
- f << stringf(".latch %s %s al %s%s\n", cstr(cell->getPort(ID::D)), cstr(cell->getPort(ID::Q)),
- cstr(cell->getPort(ID::E)), cstr_init(cell->getPort(ID::Q)));
+ f << stringf(".latch %s %s al %s%s\n", str(cell->getPort(ID::D)).c_str(), str(cell->getPort(ID::Q)).c_str(),
+ str(cell->getPort(ID::E)).c_str(), str_init(cell->getPort(ID::Q)).c_str());
goto internal_cell;
}
if (!config->icells_mode && cell->type == ID($_DLATCH_P_)) {
- f << stringf(".latch %s %s ah %s%s\n", cstr(cell->getPort(ID::D)), cstr(cell->getPort(ID::Q)),
- cstr(cell->getPort(ID::E)), cstr_init(cell->getPort(ID::Q)));
+ f << stringf(".latch %s %s ah %s%s\n", str(cell->getPort(ID::D)).c_str(), str(cell->getPort(ID::Q)).c_str(),
+ str(cell->getPort(ID::E)).c_str(), str_init(cell->getPort(ID::Q)).c_str());
goto internal_cell;
}
@@ -367,10 +363,10 @@ struct BlifDumper
auto width = cell->parameters.at(ID::WIDTH).as_int();
log_assert(inputs.size() == width);
for (int i = width-1; i >= 0; i--)
- f << stringf(" %s", cstr(inputs.extract(i, 1)));
+ f << stringf(" %s", str(inputs.extract(i, 1)).c_str());
auto &output = cell->getPort(ID::Y);
log_assert(output.size() == 1);
- f << stringf(" %s", cstr(output));
+ f << stringf(" %s", str(output).c_str());
f << stringf("\n");
RTLIL::SigSpec mask = cell->parameters.at(ID::LUT);
for (int i = 0; i < (1 << width); i++)
@@ -393,10 +389,10 @@ struct BlifDumper
table.push_back(State::S0);
log_assert(inputs.size() == width);
for (int i = 0; i < width; i++)
- f << stringf(" %s", cstr(inputs.extract(i, 1)));
+ f << stringf(" %s", str(inputs.extract(i, 1)).c_str());
auto &output = cell->getPort(ID::Y);
log_assert(output.size() == 1);
- f << stringf(" %s", cstr(output));
+ f << stringf(" %s", str(output).c_str());
f << stringf("\n");
for (int i = 0; i < depth; i++) {
for (int j = 0; j < width; j++) {
@@ -411,11 +407,11 @@ struct BlifDumper
goto internal_cell;
}
- f << stringf(".%s %s", subckt_or_gate(cell->type.str()), cstr(cell->type));
+ f << stringf(".%s %s", subckt_or_gate(cell->type.str()), str(cell->type).c_str());
for (auto &conn : cell->connections())
{
if (conn.second.size() == 1) {
- f << stringf(" %s=%s", cstr(conn.first), cstr(conn.second[0]));
+ f << stringf(" %s=%s", str(conn.first).c_str(), str(conn.second[0]).c_str());
continue;
}
@@ -424,20 +420,20 @@ struct BlifDumper
if (w == nullptr) {
for (int i = 0; i < GetSize(conn.second); i++)
- f << stringf(" %s[%d]=%s", cstr(conn.first), i, cstr(conn.second[i]));
+ f << stringf(" %s[%d]=%s", str(conn.first).c_str(), i, str(conn.second[i]).c_str());
} else {
for (int i = 0; i < std::min(GetSize(conn.second), GetSize(w)); i++) {
SigBit sig(w, i);
- f << stringf(" %s[%d]=%s", cstr(conn.first), sig.wire->upto ?
+ f << stringf(" %s[%d]=%s", str(conn.first).c_str(), sig.wire->upto ?
sig.wire->start_offset+sig.wire->width-sig.offset-1 :
- sig.wire->start_offset+sig.offset, cstr(conn.second[i]));
+ sig.wire->start_offset+sig.offset, str(conn.second[i]).c_str());
}
}
}
f << stringf("\n");
if (config->cname_mode)
- f << stringf(".cname %s\n", cstr(cell->name));
+ f << stringf(".cname %s\n", str(cell->name).c_str());
if (config->attr_mode)
dump_params(".attr", cell->attributes);
if (config->param_mode)
@@ -446,7 +442,7 @@ struct BlifDumper
if (0) {
internal_cell:
if (config->iname_mode)
- f << stringf(".cname %s\n", cstr(cell->name));
+ f << stringf(".cname %s\n", str(cell->name).c_str());
if (config->iattr_mode)
dump_params(".attr", cell->attributes);
}
@@ -462,12 +458,12 @@ struct BlifDumper
continue;
if (config->conn_mode)
- f << stringf(".conn %s %s\n", cstr(rhs_bit), cstr(lhs_bit));
+ f << stringf(".conn %s %s\n", str(rhs_bit).c_str(), str(lhs_bit).c_str());
else if (!config->buf_type.empty())
f << stringf(".%s %s %s=%s %s=%s\n", subckt_or_gate(config->buf_type), config->buf_type.c_str(),
- config->buf_in.c_str(), cstr(rhs_bit), config->buf_out.c_str(), cstr(lhs_bit));
+ config->buf_in.c_str(), str(rhs_bit).c_str(), config->buf_out.c_str(), str(lhs_bit).c_str());
else
- f << stringf(".names %s %s\n1 1\n", cstr(rhs_bit), cstr(lhs_bit));
+ f << stringf(".names %s %s\n1 1\n", str(rhs_bit).c_str(), str(lhs_bit).c_str());
}
f << stringf(".end\n");
diff --git a/backends/btor/.gitignore b/backends/btor/.gitignore
new file mode 100644
index 000000000..d23d492d7
--- /dev/null
+++ b/backends/btor/.gitignore
@@ -0,0 +1 @@
+/test_cells.tmp/
diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc
index e5da6c1e7..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/
@@ -27,6 +27,7 @@
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/log.h"
+#include "kernel/mem.h"
#include <string>
USING_YOSYS_NAMESPACE
@@ -68,12 +69,15 @@ struct BtorWorker
// ff inputs that need to be evaluated (<nid>, <ff_cell>)
vector<pair<int, Cell*>> ff_todo;
+ vector<pair<int, Mem*>> mem_todo;
pool<Cell*> cell_recursion_guard;
vector<int> bad_properties;
dict<SigBit, bool> initbits;
pool<Wire*> statewires;
pool<string> srcsymbols;
+ vector<Mem> memories;
+ dict<Cell*, Mem*> mem_cells;
string indent, info_filename;
vector<string> info_lines;
@@ -205,9 +209,8 @@ struct BtorWorker
if (cell->type.in(ID($xnor), ID($_XNOR_))) btor_op = "xnor";
log_assert(!btor_op.empty());
- int width = GetSize(cell->getPort(ID::Y));
- width = std::max(width, GetSize(cell->getPort(ID::A)));
- width = std::max(width, GetSize(cell->getPort(ID::B)));
+ int width_ay = std::max(GetSize(cell->getPort(ID::A)), GetSize(cell->getPort(ID::Y)));
+ int width = std::max(width_ay, GetSize(cell->getPort(ID::B)));
bool a_signed = cell->hasParam(ID::A_SIGNED) ? cell->getParam(ID::A_SIGNED).as_bool() : false;
bool b_signed = cell->hasParam(ID::B_SIGNED) ? cell->getParam(ID::B_SIGNED).as_bool() : false;
@@ -224,11 +227,23 @@ struct BtorWorker
int sid = get_bv_sid(width);
int nid;
+ int nid_a;
+ if (cell->type.in(ID($shl), ID($shr), ID($shift), ID($shiftx)) && a_signed && width_ay < width) {
+ // sign-extend A up to the width of Y
+ int nid_a_padded = get_sig_nid(cell->getPort(ID::A), width_ay, a_signed);
+
+ // zero-extend the rest
+ int zeroes = get_sig_nid(Const(0, width-width_ay));
+ nid_a = next_nid++;
+ btorf("%d concat %d %d %d\n", nid_a, sid, zeroes, nid_a_padded);
+ } else {
+ nid_a = get_sig_nid(cell->getPort(ID::A), width, a_signed);
+ }
+
+ int nid_b = get_sig_nid(cell->getPort(ID::B), width, b_signed);
+
if (btor_op == "shift")
{
- int nid_a = get_sig_nid(cell->getPort(ID::A), width, false);
- int nid_b = get_sig_nid(cell->getPort(ID::B), width, b_signed);
-
int nid_r = next_nid++;
btorf("%d srl %d %d %d\n", nid_r, sid, nid_a, nid_b);
@@ -248,9 +263,6 @@ struct BtorWorker
}
else
{
- int nid_a = get_sig_nid(cell->getPort(ID::A), width, a_signed);
- int nid_b = get_sig_nid(cell->getPort(ID::B), width, b_signed);
-
nid = next_nid++;
btorf("%d %s %d %d %d%s\n", nid, btor_op.c_str(), sid, nid_a, nid_b, getinfo(cell).c_str());
}
@@ -696,49 +708,46 @@ struct BtorWorker
goto okay;
}
- if (cell->type == ID($mem))
+ if (cell->is_mem_cell())
{
- int abits = cell->getParam(ID::ABITS).as_int();
- int width = cell->getParam(ID::WIDTH).as_int();
- int nwords = cell->getParam(ID::SIZE).as_int();
- int rdports = cell->getParam(ID::RD_PORTS).as_int();
- int wrports = cell->getParam(ID::WR_PORTS).as_int();
-
- Const wr_clk_en = cell->getParam(ID::WR_CLK_ENABLE);
- Const rd_clk_en = cell->getParam(ID::RD_CLK_ENABLE);
+ Mem *mem = mem_cells[cell];
- bool asyncwr = wr_clk_en.is_fully_zero();
+ int abits = ceil_log2(mem->size);
- if (!asyncwr && !wr_clk_en.is_fully_ones())
- log_error("Memory %s.%s has mixed async/sync write ports.\n",
- log_id(module), log_id(cell));
+ bool asyncwr = false;
+ bool syncwr = false;
- if (!rd_clk_en.is_fully_zero())
- log_error("Memory %s.%s has sync read ports.\n",
- log_id(module), log_id(cell));
+ for (auto &port : mem->wr_ports) {
+ if (port.clk_enable)
+ syncwr = true;
+ else
+ asyncwr = true;
+ }
- SigSpec sig_rd_addr = sigmap(cell->getPort(ID::RD_ADDR));
- SigSpec sig_rd_data = sigmap(cell->getPort(ID::RD_DATA));
+ if (asyncwr && syncwr)
+ log_error("Memory %s.%s has mixed async/sync write ports.\n",
+ log_id(module), log_id(mem->memid));
- SigSpec sig_wr_addr = sigmap(cell->getPort(ID::WR_ADDR));
- SigSpec sig_wr_data = sigmap(cell->getPort(ID::WR_DATA));
- SigSpec sig_wr_en = sigmap(cell->getPort(ID::WR_EN));
+ for (auto &port : mem->rd_ports) {
+ if (port.clk_enable)
+ 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(width);
+ int data_sid = get_bv_sid(mem->width);
int bool_sid = get_bv_sid(1);
- int sid = get_mem_sid(abits, width);
+ int sid = get_mem_sid(abits, mem->width);
- Const initdata = cell->getParam(ID::INIT);
- initdata.exts(nwords*width);
int nid_init_val = -1;
- if (!initdata.is_fully_undef())
+ if (!mem->inits.empty())
{
+ Const initdata = mem->get_init_data();
bool constword = true;
- Const firstword = initdata.extract(0, width);
+ Const firstword = initdata.extract(0, mem->width);
- for (int i = 1; i < nwords; i++) {
- Const thisword = initdata.extract(i*width, width);
+ for (int i = 1; i < mem->size; i++) {
+ Const thisword = initdata.extract(i*mem->width, mem->width);
if (thisword != firstword) {
constword = false;
break;
@@ -756,8 +765,8 @@ struct BtorWorker
nid_init_val = next_nid++;
btorf("%d state %d\n", nid_init_val, sid);
- for (int i = 0; i < nwords; i++) {
- Const thisword = initdata.extract(i*width, width);
+ for (int i = 0; i < mem->size; i++) {
+ Const thisword = initdata.extract(i*mem->width, mem->width);
if (thisword.is_fully_undef())
continue;
Const thisaddr(i, abits);
@@ -776,10 +785,10 @@ struct BtorWorker
int nid = next_nid++;
int nid_head = nid;
- if (cell->name[0] == '$')
+ if (mem->memid[0] == '$')
btorf("%d state %d\n", nid, sid);
else
- btorf("%d state %d %s\n", nid, sid, log_id(cell));
+ btorf("%d state %d %s\n", nid, sid, log_id(mem->memid));
if (nid_init_val >= 0)
{
@@ -789,15 +798,14 @@ struct BtorWorker
if (asyncwr)
{
- for (int port = 0; port < wrports; port++)
+ for (auto &port : mem->wr_ports)
{
- SigSpec wa = sig_wr_addr.extract(port*abits, abits);
- SigSpec wd = sig_wr_data.extract(port*width, width);
- SigSpec we = sig_wr_en.extract(port*width, width);
+ SigSpec wa = port.addr;
+ wa.extend_u0(abits);
int wa_nid = get_sig_nid(wa);
- int wd_nid = get_sig_nid(wd);
- int we_nid = get_sig_nid(we);
+ int wd_nid = get_sig_nid(port.data);
+ int we_nid = get_sig_nid(port.en);
int nid2 = next_nid++;
btorf("%d read %d %d %d\n", nid2, data_sid, nid_head, wa_nid);
@@ -827,22 +835,22 @@ struct BtorWorker
}
}
- for (int port = 0; port < rdports; port++)
+ for (auto &port : mem->rd_ports)
{
- SigSpec ra = sig_rd_addr.extract(port*abits, abits);
- SigSpec rd = sig_rd_data.extract(port*width, width);
+ SigSpec ra = port.addr;
+ ra.extend_u0(abits);
int ra_nid = get_sig_nid(ra);
int rd_nid = next_nid++;
btorf("%d read %d %d %d\n", rd_nid, data_sid, nid_head, ra_nid);
- add_nid_sig(rd_nid, rd);
+ add_nid_sig(rd_nid, port.data);
}
if (!asyncwr)
{
- ff_todo.push_back(make_pair(nid, cell));
+ mem_todo.push_back(make_pair(nid, mem));
}
else
{
@@ -853,7 +861,20 @@ struct BtorWorker
goto okay;
}
- log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell));
+ if (cell->type.in(ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)) || cell->type.str().substr(0, 6) == "$_SDFF" || (cell->type.str().substr(0, 6) == "$_DFFE" && cell->type.str().size() == 10)) {
+ 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($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));
+ }
+ if (cell->type.in(ID($sr), ID($dlatch), ID($adlatch), ID($dlatchsr)) || cell->type.str().substr(0, 8) == "$_DLATCH" || cell->type.str().substr(0, 5) == "$_SR_") {
+ log_error("Unsupported cell type %s for cell %s.%s -- please run `clk2fflogic` before `write_btor`.\n",
+ log_id(cell->type), log_id(module), log_id(cell));
+ }
+ log_error("Unsupported cell type %s for cell %s.%s.\n",
+ log_id(cell->type), log_id(module), log_id(cell));
okay:
btorf_pop(log_id(cell));
@@ -1057,6 +1078,17 @@ struct BtorWorker
if (!info_filename.empty())
infof("name %s\n", log_id(module));
+ memories = Mem::get_all_memories(module);
+
+ dict<IdString, Mem*> mem_dict;
+ for (auto &mem : memories) {
+ mem.narrow();
+ mem_dict[mem.memid] = &mem;
+ }
+ for (auto cell : module->cells())
+ if (cell->is_mem_cell())
+ mem_cells[cell] = mem_dict[cell->parameters.at(ID::MEMID).decode_string()];
+
btorf_push("inputs");
for (auto wire : module->wires())
@@ -1193,7 +1225,7 @@ struct BtorWorker
continue;
}
- while (!ff_todo.empty())
+ while (!ff_todo.empty() || !mem_todo.empty())
{
vector<pair<int, Cell*>> todo;
todo.swap(ff_todo);
@@ -1205,70 +1237,71 @@ struct BtorWorker
btorf_push(stringf("next %s", log_id(cell)));
- if (cell->type == ID($mem))
- {
- int abits = cell->getParam(ID::ABITS).as_int();
- int width = cell->getParam(ID::WIDTH).as_int();
- int wrports = cell->getParam(ID::WR_PORTS).as_int();
+ SigSpec sig = sigmap(cell->getPort(ID::D));
+ int nid_q = get_sig_nid(sig);
+ int sid = get_bv_sid(GetSize(sig));
+ btorf("%d next %d %d %d%s\n", next_nid++, sid, nid, nid_q, getinfo(cell).c_str());
- SigSpec sig_wr_addr = sigmap(cell->getPort(ID::WR_ADDR));
- SigSpec sig_wr_data = sigmap(cell->getPort(ID::WR_DATA));
- SigSpec sig_wr_en = sigmap(cell->getPort(ID::WR_EN));
+ btorf_pop(stringf("next %s", log_id(cell)));
+ }
- int data_sid = get_bv_sid(width);
- int bool_sid = get_bv_sid(1);
- int sid = get_mem_sid(abits, width);
- int nid_head = nid;
+ vector<pair<int, Mem*>> mtodo;
+ mtodo.swap(mem_todo);
- for (int port = 0; port < wrports; port++)
- {
- SigSpec wa = sig_wr_addr.extract(port*abits, abits);
- SigSpec wd = sig_wr_data.extract(port*width, width);
- SigSpec we = sig_wr_en.extract(port*width, width);
+ for (auto &it : mtodo)
+ {
+ int nid = it.first;
+ Mem *mem = it.second;
- int wa_nid = get_sig_nid(wa);
- int wd_nid = get_sig_nid(wd);
- int we_nid = get_sig_nid(we);
+ btorf_push(stringf("next %s", log_id(mem->memid)));
- int nid2 = next_nid++;
- btorf("%d read %d %d %d\n", nid2, data_sid, nid_head, wa_nid);
+ int abits = ceil_log2(mem->size);
- int nid3 = next_nid++;
- btorf("%d not %d %d\n", nid3, data_sid, we_nid);
+ int data_sid = get_bv_sid(mem->width);
+ int bool_sid = get_bv_sid(1);
+ int sid = get_mem_sid(abits, mem->width);
+ int nid_head = nid;
- int nid4 = next_nid++;
- btorf("%d and %d %d %d\n", nid4, data_sid, nid2, nid3);
+ for (auto &port : mem->wr_ports)
+ {
+ SigSpec wa = port.addr;
+ wa.extend_u0(abits);
- int nid5 = next_nid++;
- btorf("%d and %d %d %d\n", nid5, data_sid, wd_nid, we_nid);
+ int wa_nid = get_sig_nid(wa);
+ int wd_nid = get_sig_nid(port.data);
+ int we_nid = get_sig_nid(port.en);
- int nid6 = next_nid++;
- btorf("%d or %d %d %d\n", nid6, data_sid, nid5, nid4);
+ int nid2 = next_nid++;
+ btorf("%d read %d %d %d\n", nid2, data_sid, nid_head, wa_nid);
- int nid7 = next_nid++;
- btorf("%d write %d %d %d %d\n", nid7, sid, nid_head, wa_nid, nid6);
+ int nid3 = next_nid++;
+ btorf("%d not %d %d\n", nid3, data_sid, we_nid);
- int nid8 = next_nid++;
- btorf("%d redor %d %d\n", nid8, bool_sid, we_nid);
+ int nid4 = next_nid++;
+ btorf("%d and %d %d %d\n", nid4, data_sid, nid2, nid3);
- int nid9 = next_nid++;
- btorf("%d ite %d %d %d %d\n", nid9, sid, nid8, nid7, nid_head);
+ int nid5 = next_nid++;
+ btorf("%d and %d %d %d\n", nid5, data_sid, wd_nid, we_nid);
- nid_head = nid9;
- }
+ int nid6 = next_nid++;
+ btorf("%d or %d %d %d\n", nid6, data_sid, nid5, nid4);
- int nid2 = next_nid++;
- btorf("%d next %d %d %d%s\n", nid2, sid, nid, nid_head, getinfo(cell).c_str());
- }
- else
- {
- SigSpec sig = sigmap(cell->getPort(ID::D));
- int nid_q = get_sig_nid(sig);
- int sid = get_bv_sid(GetSize(sig));
- btorf("%d next %d %d %d%s\n", next_nid++, sid, nid, nid_q, getinfo(cell).c_str());
+ int nid7 = next_nid++;
+ btorf("%d write %d %d %d %d\n", nid7, sid, nid_head, wa_nid, nid6);
+
+ int nid8 = next_nid++;
+ btorf("%d redor %d %d\n", nid8, bool_sid, we_nid);
+
+ int nid9 = next_nid++;
+ btorf("%d ite %d %d %d %d\n", nid9, sid, nid8, nid7, nid_head);
+
+ nid_head = nid9;
}
- btorf_pop(stringf("next %s", log_id(cell)));
+ int nid2 = next_nid++;
+ btorf("%d next %d %d %d%s\n", nid2, sid, nid, nid_head, (mem->cell ? getinfo(mem->cell) : getinfo(mem->mem)).c_str());
+
+ btorf_pop(stringf("next %s", log_id(mem->memid)));
}
}
@@ -1366,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/btor/test_cells.sh b/backends/btor/test_cells.sh
index 3f077201a..0a011932d 100644..100755
--- a/backends/btor/test_cells.sh
+++ b/backends/btor/test_cells.sh
@@ -6,7 +6,7 @@ rm -rf test_cells.tmp
mkdir -p test_cells.tmp
cd test_cells.tmp
-../../../yosys -p 'test_cell -n 5 -w test all /$alu /$fa /$lcu /$lut /$sop /$macc /$mul /$div /$mod /$divfloor /$modfloor'
+../../../yosys -p 'test_cell -n 5 -w test all /$alu /$fa /$lcu /$lut /$sop /$macc /$mul /$div /$mod /$divfloor /$modfloor /$shiftx'
for fn in test_*.il; do
../../../yosys -p "
@@ -19,7 +19,7 @@ for fn in test_*.il; do
hierarchy -top main
write_btor ${fn%.il}.btor
"
- boolectormc -kmax 1 --trace-gen --stop-first -v ${fn%.il}.btor > ${fn%.il}.out
+ btormc -kmax 1 --trace-gen --stop-first -v ${fn%.il}.btor > ${fn%.il}.out
if grep " SATISFIABLE" ${fn%.il}.out; then
echo "Check failed for ${fn%.il}."
exit 1
diff --git a/backends/cxxrtl/cxxrtl.h b/backends/cxxrtl/cxxrtl.h
index f0d7b9fc7..b4ffa87cd 100644
--- a/backends/cxxrtl/cxxrtl.h
+++ b/backends/cxxrtl/cxxrtl.h
@@ -36,22 +36,48 @@
#include <map>
#include <algorithm>
#include <memory>
+#include <functional>
#include <sstream>
#include <backends/cxxrtl/cxxrtl_capi.h>
+#ifndef __has_attribute
+# define __has_attribute(x) 0
+#endif
+
// CXXRTL essentially uses the C++ compiler as a hygienic macro engine that feeds an instruction selector.
// It generates a lot of specialized template functions with relatively large bodies that, when inlined
// into the caller and (for those with loops) unrolled, often expose many new optimization opportunities.
// Because of this, most of the CXXRTL runtime must be always inlined for best performance.
-#ifndef __has_attribute
-# define __has_attribute(x) 0
-#endif
#if __has_attribute(always_inline)
#define CXXRTL_ALWAYS_INLINE inline __attribute__((__always_inline__))
#else
#define CXXRTL_ALWAYS_INLINE inline
#endif
+// Conversely, some functions in the generated code are extremely large yet very cold, with both of these
+// properties being extreme enough to confuse C++ compilers into spending pathological amounts of time
+// on a futile (the code becomes worse) attempt to optimize the least important parts of code.
+#if __has_attribute(optnone)
+#define CXXRTL_EXTREMELY_COLD __attribute__((__optnone__))
+#elif __has_attribute(optimize)
+#define CXXRTL_EXTREMELY_COLD __attribute__((__optimize__(0)))
+#else
+#define CXXRTL_EXTREMELY_COLD
+#endif
+
+// CXXRTL uses assert() to check for C++ contract violations (which may result in e.g. undefined behavior
+// of the simulation code itself), and CXXRTL_ASSERT to check for RTL contract violations (which may at
+// most result in undefined simulation results).
+//
+// Though by default, CXXRTL_ASSERT() expands to assert(), it may be overridden e.g. when integrating
+// the simulation into another process that should survive violating RTL contracts.
+#ifndef CXXRTL_ASSERT
+#ifndef CXXRTL_NDEBUG
+#define CXXRTL_ASSERT(x) assert(x)
+#else
+#define CXXRTL_ASSERT(x)
+#endif
+#endif
namespace cxxrtl {
@@ -96,9 +122,11 @@ struct value : public expr_base<value<Bits>> {
explicit constexpr value(Init ...init) : data{init...} {}
value(const value<Bits> &) = default;
- value(value<Bits> &&) = default;
value<Bits> &operator=(const value<Bits> &) = default;
+ value(value<Bits> &&) = default;
+ value<Bits> &operator=(value<Bits> &&) = default;
+
// A (no-op) helper that forces the cast to value<>.
CXXRTL_ALWAYS_INLINE
const value<Bits> &val() const {
@@ -289,6 +317,14 @@ struct value : public expr_base<value<Bits>> {
return sext_cast<NewBits>()(*this);
}
+ // Bit replication is far more efficient than the equivalent concatenation.
+ template<size_t Count>
+ CXXRTL_ALWAYS_INLINE
+ value<Bits * Count> repeat() const {
+ static_assert(Bits == 1, "repeat() is implemented only for 1-bit values");
+ return *this ? value<Bits * Count>().bit_not() : value<Bits * Count>();
+ }
+
// Operations with run-time parameters (offsets, amounts, etc).
//
// These operations are used for computations.
@@ -421,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++) {
@@ -452,10 +524,11 @@ struct value : public expr_base<value<Bits>> {
bool carry = CarryIn;
for (size_t n = 0; n < result.chunks; n++) {
result.data[n] = data[n] + (Invert ? ~other.data[n] : other.data[n]) + carry;
+ if (result.chunks - 1 == n)
+ result.data[result.chunks - 1] &= result.msb_mask;
carry = (result.data[n] < data[n]) ||
(result.data[n] == data[n] && carry);
}
- result.data[result.chunks - 1] &= result.msb_mask;
return {result, carry};
}
@@ -642,14 +715,20 @@ struct wire {
value<Bits> next;
wire() = default;
- constexpr wire(const value<Bits> &init) : curr(init), next(init) {}
+ explicit constexpr wire(const value<Bits> &init) : curr(init), next(init) {}
template<typename... Init>
explicit constexpr wire(Init ...init) : curr{init...}, next{init...} {}
+ // Copying and copy-assigning values is natural. If, however, a value is replaced with a wire,
+ // e.g. because a module is built with a different optimization level, then existing code could
+ // unintentionally copy a wire instead, which would create a subtle but serious bug. To make sure
+ // this doesn't happen, prohibit copying and copy-assigning wires.
wire(const wire<Bits> &) = delete;
- wire(wire<Bits> &&) = default;
wire<Bits> &operator=(const wire<Bits> &) = delete;
+ wire(wire<Bits> &&) = default;
+ wire<Bits> &operator=(wire<Bits> &&) = default;
+
template<class IntegerT>
CXXRTL_ALWAYS_INLINE
IntegerT get() const {
@@ -679,47 +758,32 @@ std::ostream &operator<<(std::ostream &os, const wire<Bits> &val) {
template<size_t Width>
struct memory {
- std::vector<value<Width>> data;
-
- size_t depth() const {
- return data.size();
- }
+ const size_t depth;
+ std::unique_ptr<value<Width>[]> data;
- 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;
- // 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(memory<Width> &&) = default;
+ 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];
}
@@ -744,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,
@@ -814,35 +878,52 @@ struct metadata {
typedef std::map<std::string, metadata> metadata_map;
-// Helper class to disambiguate values/wires and their aliases.
+// Tag class to disambiguate values/wires and their aliases.
struct debug_alias {};
+// Tag declaration to disambiguate values and debug outlines.
+using debug_outline = ::_cxxrtl_outline;
+
// This structure is intended for consumption via foreign function interfaces, like Python's ctypes.
// Because of this it uses a C-style layout that is easy to parse rather than more idiomatic C++.
//
// To avoid violating strict aliasing rules, this structure has to be a subclass of the one used
// in the C API, or it would not be possible to cast between the pointers to these.
struct debug_item : ::cxxrtl_object {
+ // Object types.
enum : uint32_t {
- VALUE = CXXRTL_VALUE,
- WIRE = CXXRTL_WIRE,
- MEMORY = CXXRTL_MEMORY,
- ALIAS = CXXRTL_ALIAS,
+ VALUE = CXXRTL_VALUE,
+ WIRE = CXXRTL_WIRE,
+ MEMORY = CXXRTL_MEMORY,
+ ALIAS = CXXRTL_ALIAS,
+ OUTLINE = CXXRTL_OUTLINE,
+ };
+
+ // Object flags.
+ enum : uint32_t {
+ INPUT = CXXRTL_INPUT,
+ OUTPUT = CXXRTL_OUTPUT,
+ INOUT = CXXRTL_INOUT,
+ DRIVEN_SYNC = CXXRTL_DRIVEN_SYNC,
+ DRIVEN_COMB = CXXRTL_DRIVEN_COMB,
+ UNDRIVEN = CXXRTL_UNDRIVEN,
};
debug_item(const ::cxxrtl_object &object) : cxxrtl_object(object) {}
template<size_t Bits>
- debug_item(value<Bits> &item, size_t lsb_offset = 0) {
+ debug_item(value<Bits> &item, size_t lsb_offset = 0, uint32_t flags_ = 0) {
static_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t),
"value<Bits> is not compatible with C layout");
type = VALUE;
+ flags = flags_;
width = Bits;
lsb_at = lsb_offset;
depth = 1;
zero_at = 0;
curr = item.data;
next = item.data;
+ outline = nullptr;
}
template<size_t Bits>
@@ -850,26 +931,30 @@ struct debug_item : ::cxxrtl_object {
static_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t),
"value<Bits> is not compatible with C layout");
type = VALUE;
+ flags = DRIVEN_COMB;
width = Bits;
lsb_at = lsb_offset;
depth = 1;
zero_at = 0;
curr = const_cast<chunk_t*>(item.data);
next = nullptr;
+ outline = nullptr;
}
template<size_t Bits>
- debug_item(wire<Bits> &item, size_t lsb_offset = 0) {
+ debug_item(wire<Bits> &item, size_t lsb_offset = 0, uint32_t flags_ = 0) {
static_assert(sizeof(item.curr) == value<Bits>::chunks * sizeof(chunk_t) &&
sizeof(item.next) == value<Bits>::chunks * sizeof(chunk_t),
"wire<Bits> is not compatible with C layout");
type = WIRE;
+ flags = flags_;
width = Bits;
lsb_at = lsb_offset;
depth = 1;
zero_at = 0;
curr = item.curr.data;
next = item.next.data;
+ outline = nullptr;
}
template<size_t Width>
@@ -877,12 +962,14 @@ struct debug_item : ::cxxrtl_object {
static_assert(sizeof(item.data[0]) == value<Width>::chunks * sizeof(chunk_t),
"memory<Width> is not compatible with C layout");
type = MEMORY;
+ 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;
}
template<size_t Bits>
@@ -890,12 +977,14 @@ struct debug_item : ::cxxrtl_object {
static_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t),
"value<Bits> is not compatible with C layout");
type = ALIAS;
+ flags = DRIVEN_COMB;
width = Bits;
lsb_at = lsb_offset;
depth = 1;
zero_at = 0;
curr = const_cast<chunk_t*>(item.data);
next = nullptr;
+ outline = nullptr;
}
template<size_t Bits>
@@ -904,12 +993,45 @@ struct debug_item : ::cxxrtl_object {
sizeof(item.next) == value<Bits>::chunks * sizeof(chunk_t),
"wire<Bits> is not compatible with C layout");
type = ALIAS;
+ flags = DRIVEN_COMB;
width = Bits;
lsb_at = lsb_offset;
depth = 1;
zero_at = 0;
curr = const_cast<chunk_t*>(item.curr.data);
next = nullptr;
+ outline = nullptr;
+ }
+
+ template<size_t Bits>
+ debug_item(debug_outline &group, const value<Bits> &item, size_t lsb_offset = 0) {
+ static_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t),
+ "value<Bits> is not compatible with C layout");
+ type = OUTLINE;
+ flags = DRIVEN_COMB;
+ width = Bits;
+ lsb_at = lsb_offset;
+ depth = 1;
+ zero_at = 0;
+ curr = const_cast<chunk_t*>(item.data);
+ 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");
@@ -947,13 +1069,25 @@ struct debug_items {
}
};
+// 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() {}
virtual ~module() {}
+ // Modules with black boxes cannot be copied. Although not all designs include black boxes,
+ // delete the copy constructor and copy assignment operator to make sure that any downstream
+ // code that manipulates modules doesn't accidentally depend on their availability.
module(const module &) = delete;
module &operator=(const module &) = delete;
+ module(module &&) = default;
+ module &operator=(module &&) = default;
+
+ virtual void reset() = 0;
+
virtual bool eval() = 0;
virtual bool commit() = 0;
@@ -974,11 +1108,16 @@ struct module {
} // namespace cxxrtl
-// Internal structure used to communicate with the implementation of the C interface.
+// Internal structures used to communicate with the implementation of the C interface.
+
typedef struct _cxxrtl_toplevel {
std::unique_ptr<cxxrtl::module> module;
} *cxxrtl_toplevel;
+typedef struct _cxxrtl_outline {
+ std::function<void()> eval;
+} *cxxrtl_outline;
+
// Definitions of internal Yosys cells. Other than the functions in this namespace, CXXRTL is fully generic
// and indepenent of Yosys implementation details.
//
@@ -1112,49 +1251,49 @@ value<BitsY> xnor_ss(const value<BitsA> &a, const value<BitsB> &b) {
template<size_t BitsY, size_t BitsA, size_t BitsB>
CXXRTL_ALWAYS_INLINE
value<BitsY> shl_uu(const value<BitsA> &a, const value<BitsB> &b) {
- return a.template zcast<BitsY>().template shl(b);
+ return a.template zcast<BitsY>().shl(b);
}
template<size_t BitsY, size_t BitsA, size_t BitsB>
CXXRTL_ALWAYS_INLINE
value<BitsY> shl_su(const value<BitsA> &a, const value<BitsB> &b) {
- return a.template scast<BitsY>().template shl(b);
+ return a.template scast<BitsY>().shl(b);
}
template<size_t BitsY, size_t BitsA, size_t BitsB>
CXXRTL_ALWAYS_INLINE
value<BitsY> sshl_uu(const value<BitsA> &a, const value<BitsB> &b) {
- return a.template zcast<BitsY>().template shl(b);
+ return a.template zcast<BitsY>().shl(b);
}
template<size_t BitsY, size_t BitsA, size_t BitsB>
CXXRTL_ALWAYS_INLINE
value<BitsY> sshl_su(const value<BitsA> &a, const value<BitsB> &b) {
- return a.template scast<BitsY>().template shl(b);
+ return a.template scast<BitsY>().shl(b);
}
template<size_t BitsY, size_t BitsA, size_t BitsB>
CXXRTL_ALWAYS_INLINE
value<BitsY> shr_uu(const value<BitsA> &a, const value<BitsB> &b) {
- return a.template shr(b).template zcast<BitsY>();
+ return a.shr(b).template zcast<BitsY>();
}
template<size_t BitsY, size_t BitsA, size_t BitsB>
CXXRTL_ALWAYS_INLINE
value<BitsY> shr_su(const value<BitsA> &a, const value<BitsB> &b) {
- return a.template shr(b).template scast<BitsY>();
+ return a.shr(b).template scast<BitsY>();
}
template<size_t BitsY, size_t BitsA, size_t BitsB>
CXXRTL_ALWAYS_INLINE
value<BitsY> sshr_uu(const value<BitsA> &a, const value<BitsB> &b) {
- return a.template shr(b).template zcast<BitsY>();
+ return a.shr(b).template zcast<BitsY>();
}
template<size_t BitsY, size_t BitsA, size_t BitsB>
CXXRTL_ALWAYS_INLINE
value<BitsY> sshr_su(const value<BitsA> &a, const value<BitsB> &b) {
- return a.template sshr(b).template scast<BitsY>();
+ return a.sshr(b).template scast<BitsY>();
}
template<size_t BitsY, size_t BitsA, size_t BitsB>
diff --git a/backends/cxxrtl/cxxrtl_backend.cc b/backends/cxxrtl/cxxrtl_backend.cc
index 5e5ba5ac0..404755b1e 100644
--- a/backends/cxxrtl/cxxrtl_backend.cc
+++ b/backends/cxxrtl/cxxrtl_backend.cc
@@ -22,6 +22,7 @@
#include "kernel/sigtools.h"
#include "kernel/utils.h"
#include "kernel/celltypes.h"
+#include "kernel/mem.h"
#include "kernel/log.h"
USING_YOSYS_NAMESPACE
@@ -194,27 +195,29 @@ bool is_extending_cell(RTLIL::IdString type)
ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool));
}
-bool is_elidable_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_sync_ff_cell(RTLIL::IdString type)
+bool is_ff_cell(RTLIL::IdString type)
{
return type.in(
- ID($dff), ID($dffe), ID($sdff), ID($sdffe), ID($sdffce));
+ 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));
}
-bool is_ff_cell(RTLIL::IdString type)
+bool is_internal_cell(RTLIL::IdString type)
{
- return is_sync_ff_cell(type) || type.in(
- ID($adff), ID($adffe), ID($dffsr), ID($dffsre), ID($dlatch), ID($adlatch), ID($dlatchsr), ID($sr));
+ return !type.isPublic() && !type.begins_with("$paramod");
}
-bool is_internal_cell(RTLIL::IdString type)
+bool is_effectful_cell(RTLIL::IdString type)
{
- return type[0] == '$' && !type.begins_with("$paramod");
+ return type.isPublic();
}
bool is_cxxrtl_blackbox_cell(const RTLIL::Cell *cell)
@@ -224,24 +227,29 @@ 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,
SYNC = 2,
};
-CxxrtlPortType cxxrtl_port_type(const RTLIL::Cell *cell, RTLIL::IdString port)
+CxxrtlPortType cxxrtl_port_type(RTLIL::Module *module, RTLIL::IdString port)
{
- RTLIL::Module *cell_module = cell->module->design->module(cell->type);
- if (cell_module == nullptr || !cell_module->get_bool_attribute(ID(cxxrtl_blackbox)))
- return CxxrtlPortType::UNKNOWN;
- RTLIL::Wire *cell_output_wire = cell_module->wire(port);
- log_assert(cell_output_wire != nullptr);
- bool is_comb = cell_output_wire->get_bool_attribute(ID(cxxrtl_comb));
- bool is_sync = cell_output_wire->get_bool_attribute(ID(cxxrtl_sync));
+ RTLIL::Wire *output_wire = module->wire(port);
+ log_assert(output_wire != nullptr);
+ bool is_comb = output_wire->get_bool_attribute(ID(cxxrtl_comb));
+ bool is_sync = output_wire->get_bool_attribute(ID(cxxrtl_sync));
if (is_comb && is_sync)
log_cmd_error("Port `%s.%s' is marked as both `cxxrtl_comb` and `cxxrtl_sync`.\n",
- log_id(cell_module), log_signal(cell_output_wire));
+ log_id(module), log_signal(output_wire));
else if (is_comb)
return CxxrtlPortType::COMB;
else if (is_sync)
@@ -249,6 +257,14 @@ CxxrtlPortType cxxrtl_port_type(const RTLIL::Cell *cell, RTLIL::IdString port)
return CxxrtlPortType::UNKNOWN;
}
+CxxrtlPortType cxxrtl_port_type(const RTLIL::Cell *cell, RTLIL::IdString port)
+{
+ RTLIL::Module *cell_module = cell->module->design->module(cell->type);
+ if (cell_module == nullptr || !cell_module->get_bool_attribute(ID(cxxrtl_blackbox)))
+ return CxxrtlPortType::UNKNOWN;
+ return cxxrtl_port_type(cell_module, port);
+}
+
bool is_cxxrtl_comb_port(const RTLIL::Cell *cell, RTLIL::IdString port)
{
return cxxrtl_port_type(cell, port) == CxxrtlPortType::COMB;
@@ -265,18 +281,26 @@ struct FlowGraph {
CONNECT,
CELL_SYNC,
CELL_EVAL,
- PROCESS
+ 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;
dict<const RTLIL::Wire*, pool<Node*, hash_ptr_ops>> wire_comb_defs, wire_sync_defs, wire_uses;
- dict<const RTLIL::Wire*, bool> wire_def_elidable, wire_use_elidable;
+ dict<Node*, pool<const RTLIL::Wire*>, hash_ptr_ops> node_comb_defs, node_sync_defs, node_uses;
+ dict<const RTLIL::Wire*, bool> wire_def_inlinable;
+ dict<const RTLIL::Wire*, dict<Node*, bool, hash_ptr_ops>> wire_use_inlinable;
+ dict<RTLIL::SigBit, bool> bit_has_state;
~FlowGraph()
{
@@ -284,18 +308,33 @@ struct FlowGraph {
delete node;
}
- void add_defs(Node *node, const RTLIL::SigSpec &sig, bool fully_sync, bool elidable)
+ void add_defs(Node *node, const RTLIL::SigSpec &sig, bool is_ff, bool inlinable)
{
for (auto chunk : sig.chunks())
if (chunk.wire) {
- if (fully_sync)
+ if (is_ff) {
+ // A sync def means that a wire holds design state because it is driven directly by
+ // a flip-flop output. Such a wire can never be unbuffered.
wire_sync_defs[chunk.wire].insert(node);
- else
+ node_sync_defs[node].insert(chunk.wire);
+ } else {
+ // A comb def means that a wire doesn't hold design state. It might still be connected,
+ // indirectly, to a flip-flop output.
wire_comb_defs[chunk.wire].insert(node);
+ node_comb_defs[node].insert(chunk.wire);
+ }
}
- // Only comb defs of an entire wire in the right order can be elided.
- if (!fully_sync && sig.is_wire())
- wire_def_elidable[sig.as_wire()] = elidable;
+ 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()) {
+ // 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)
@@ -303,26 +342,41 @@ struct FlowGraph {
for (auto chunk : sig.chunks())
if (chunk.wire) {
wire_uses[chunk.wire].insert(node);
- // Only a single use of an entire wire in the right order can be elided.
- // (But the use can include other chunks.)
- if (!wire_use_elidable.count(chunk.wire))
- wire_use_elidable[chunk.wire] = true;
+ node_uses[node].insert(chunk.wire);
+ // Only a single use of an entire wire in the right order can be inlined. (But the use can include
+ // other chunks.) This is tracked per-node because a wire used by multiple nodes can still be inlined
+ // if all but one of those nodes is dead.
+ if (!wire_use_inlinable[chunk.wire].count(node))
+ wire_use_inlinable[chunk.wire][node] = true;
else
- wire_use_elidable[chunk.wire] = false;
+ wire_use_inlinable[chunk.wire][node] = false;
}
}
- bool is_elidable(const RTLIL::Wire *wire) const
+ bool is_inlinable(const RTLIL::Wire *wire) const
{
- if (wire_def_elidable.count(wire) && wire_use_elidable.count(wire))
- return wire_def_elidable.at(wire) && wire_use_elidable.at(wire);
+ // Can the wire be inlined at all?
+ if (wire_def_inlinable.count(wire))
+ return wire_def_inlinable.at(wire);
+ return false;
+ }
+
+ bool is_inlinable(const RTLIL::Wire *wire, const pool<Node*, hash_ptr_ops> &nodes) const
+ {
+ // Can the wire be inlined, knowing that the given nodes are reachable?
+ if (nodes.size() != 1)
+ return false;
+ Node *node = *nodes.begin();
+ log_assert(node_uses.at(node).count(wire));
+ if (is_inlinable(wire) && wire_use_inlinable.count(wire) && wire_use_inlinable.at(wire).count(node))
+ return wire_use_inlinable.at(wire).at(node);
return false;
}
// Connections
void add_connect_defs_uses(Node *node, const RTLIL::SigSig &conn)
{
- add_defs(node, conn.first, /*fully_sync=*/false, /*elidable=*/true);
+ add_defs(node, conn.first, /*is_ff=*/false, /*inlinable=*/true);
add_uses(node, conn.second);
}
@@ -368,8 +422,8 @@ struct FlowGraph {
for (auto conn : cell->connections())
if (cell->output(conn.first))
if (is_cxxrtl_sync_port(cell, conn.first)) {
- // See note regarding elidability below.
- add_defs(node, conn.second, /*fully_sync=*/false, /*elidable=*/false);
+ // See note regarding inlinability below.
+ add_defs(node, conn.second, /*is_ff=*/false, /*inlinable=*/false);
}
}
@@ -377,19 +431,19 @@ struct FlowGraph {
{
for (auto conn : cell->connections()) {
if (cell->output(conn.first)) {
- if (is_elidable_cell(cell->type))
- add_defs(node, conn.second, /*fully_sync=*/false, /*elidable=*/true);
- else if (is_sync_ff_cell(cell->type) || (cell->type == ID($memrd) && cell->getParam(ID::CLK_ENABLE).as_bool()))
- add_defs(node, conn.second, /*fully_sync=*/true, /*elidable=*/false);
+ if (is_inlinable_cell(cell->type))
+ add_defs(node, conn.second, /*is_ff=*/false, /*inlinable=*/true);
+ 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, /*fully_sync=*/false, /*elidable=*/false);
+ add_defs(node, conn.second, /*is_ff=*/false, /*inlinable=*/false);
else if (!is_cxxrtl_sync_port(cell, conn.first)) {
- // Although at first it looks like outputs of user-defined cells may always be elided, the reality is
- // more complex. Fully sync outputs produce no defs and so don't participate in elision. Fully comb
+ // Although at first it looks like outputs of user-defined cells may always be inlined, the reality is
+ // more complex. Fully sync outputs produce no defs and so don't participate in inlining. Fully comb
// outputs are assigned in a different way depending on whether the cell's eval() immediately converged.
- // Unknown/mixed outputs could be elided, but should be rare in practical designs and don't justify
- // the infrastructure required to elide outputs of cells with many of them.
- add_defs(node, conn.second, /*fully_sync=*/false, /*elidable=*/false);
+ // Unknown/mixed outputs could be inlined, but should be rare in practical designs and don't justify
+ // the infrastructure required to inline outputs of cells with many of them.
+ add_defs(node, conn.second, /*is_ff=*/false, /*inlinable=*/false);
}
}
if (cell->input(conn.first))
@@ -424,10 +478,10 @@ struct FlowGraph {
}
// Processes
- void add_case_defs_uses(Node *node, const RTLIL::CaseRule *case_)
+ void add_case_rule_defs_uses(Node *node, const RTLIL::CaseRule *case_)
{
for (auto &action : case_->actions) {
- add_defs(node, action.first, /*is_sync=*/false, /*elidable=*/false);
+ add_defs(node, action.first, /*is_ff=*/false, /*inlinable=*/false);
add_uses(node, action.second);
}
for (auto sub_switch : case_->switches) {
@@ -435,33 +489,89 @@ struct FlowGraph {
for (auto sub_case : sub_switch->cases) {
for (auto &compare : sub_case->compare)
add_uses(node, compare);
- add_case_defs_uses(node, sub_case);
+ add_case_rule_defs_uses(node, sub_case);
}
}
}
- void add_process_defs_uses(Node *node, const RTLIL::Process *process)
+ void add_sync_rules_defs_uses(Node *node, const RTLIL::Process *process)
{
- add_case_defs_uses(node, &process->root_case);
- 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_sync=*/true, /*elidable=*/false);
+ add_defs(node, action.first, /*is_ff=*/true, /*inlinable=*/false);
else
- add_defs(node, action.first, /*is_sync=*/false, /*elidable=*/false);
+ 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)
{
Node *node = new Node;
- node->type = Node::Type::PROCESS;
+ node->type = Node::Type::PROCESS_SYNC;
node->process = process;
nodes.push_back(node);
- add_process_defs_uses(node, process);
+ add_sync_rules_defs_uses(node, process);
+
+ node = new Node;
+ node->type = Node::Type::PROCESS_CASE;
+ node->process = process;
+ nodes.push_back(node);
+ 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)
@@ -515,6 +625,58 @@ std::string get_hdl_name(T *object)
return object->name.str().substr(1);
}
+struct WireType {
+ enum Type {
+ // Non-referenced wire; is not a part of the design.
+ UNUSED,
+ // Double-buffered wire; is a class member, and holds design state.
+ BUFFERED,
+ // Single-buffered wire; is a class member, but holds no state.
+ MEMBER,
+ // Single-buffered wire; is a class member, and is computed on demand.
+ OUTLINE,
+ // Local wire; is a local variable in eval method.
+ LOCAL,
+ // Inline wire; is an unnamed temporary in eval method.
+ INLINE,
+ // Alias wire; is replaced with aliasee, except in debug info.
+ ALIAS,
+ // Const wire; is replaced with constant, except in debug info.
+ CONST,
+ };
+
+ Type type = UNUSED;
+ const RTLIL::Cell *cell_subst = nullptr; // for INLINE
+ RTLIL::SigSpec sig_subst = {}; // for INLINE, ALIAS, and CONST
+
+ WireType() = default;
+
+ WireType(Type type) : type(type) {
+ log_assert(type == UNUSED || type == BUFFERED || type == MEMBER || type == OUTLINE || type == LOCAL);
+ }
+
+ WireType(Type type, const RTLIL::Cell *cell) : type(type), cell_subst(cell) {
+ log_assert(type == INLINE && is_inlinable_cell(cell->type));
+ }
+
+ WireType(Type type, RTLIL::SigSpec sig) : type(type), sig_subst(sig) {
+ log_assert(type == INLINE || (type == ALIAS && sig.is_wire()) || (type == CONST && sig.is_fully_const()));
+ }
+
+ bool is_buffered() const { return type == BUFFERED; }
+ bool is_member() const { return type == BUFFERED || type == MEMBER || type == OUTLINE; }
+ bool is_outline() const { return type == OUTLINE; }
+ bool is_named() const { return is_member() || type == LOCAL; }
+ bool is_local() const { return type == LOCAL || type == INLINE; }
+ bool is_exact() const { return type == ALIAS || type == CONST; }
+};
+
+// Tests for a SigSpec that is a valid clock input, clocks have to have a backing wire and be a single bit
+// using this instead of sig.is_wire() solves issues when the clock is a slice instead of a full wire
+bool is_valid_clock(const RTLIL::SigSpec& sig) {
+ return sig.is_chunk() && sig.is_bit() && sig[0].wire;
+}
+
struct CxxrtlWorker {
bool split_intf = false;
std::string intf_filename;
@@ -522,6 +684,9 @@ 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;
@@ -529,26 +694,27 @@ struct CxxrtlWorker {
bool unbuffer_public = false;
bool localize_internal = false;
bool localize_public = false;
- bool elide_internal = false;
- bool elide_public = false;
+ bool inline_internal = false;
+ bool inline_public = false;
bool debug_info = false;
+ bool debug_member = false;
+ bool debug_alias = false;
+ bool debug_eval = false;
std::ostringstream f;
std::string indent;
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::Wire*, FlowGraph::Node> elided_wires;
- dict<const RTLIL::Module*, std::vector<FlowGraph::Node>> schedule;
- pool<const RTLIL::Wire*> unbuffered_wires;
- pool<const RTLIL::Wire*> localized_wires;
- dict<const RTLIL::Wire*, const RTLIL::Wire*> debug_alias_wires;
- dict<const RTLIL::Wire*, RTLIL::Const> debug_const_wires;
+ 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;
dict<const RTLIL::Module*, pool<std::string>> blackbox_specializations;
dict<const RTLIL::Module*, bool> eval_converges;
@@ -629,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);
@@ -763,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 << ">";
@@ -779,30 +945,37 @@ struct CxxrtlWorker {
dump_const(data, data.size());
}
- bool dump_sigchunk(const RTLIL::SigChunk &chunk, bool is_lhs)
+ bool dump_sigchunk(const RTLIL::SigChunk &chunk, bool is_lhs, bool for_debug = false)
{
if (chunk.wire == NULL) {
dump_const(chunk.data, chunk.width, chunk.offset);
return false;
} else {
- if (elided_wires.count(chunk.wire)) {
- log_assert(!is_lhs);
- const FlowGraph::Node &node = elided_wires[chunk.wire];
- switch (node.type) {
- case FlowGraph::Node::Type::CONNECT:
- dump_connect_elided(node.connect);
- break;
- case FlowGraph::Node::Type::CELL_EVAL:
- log_assert(is_elidable_cell(node.cell->type));
- dump_cell_elided(node.cell);
+ const auto &wire_type = (for_debug ? debug_wire_types : wire_types)[chunk.wire];
+ switch (wire_type.type) {
+ case WireType::BUFFERED:
+ f << mangle(chunk.wire) << (is_lhs ? ".next" : ".curr");
+ break;
+ case WireType::MEMBER:
+ case WireType::LOCAL:
+ case WireType::OUTLINE:
+ f << mangle(chunk.wire);
+ break;
+ case WireType::INLINE:
+ log_assert(!is_lhs);
+ if (wire_type.cell_subst != nullptr) {
+ dump_cell_expr(wire_type.cell_subst, for_debug);
break;
- default:
- log_assert(false);
- }
- } else if (unbuffered_wires[chunk.wire]) {
- f << mangle(chunk.wire);
- } else {
- f << mangle(chunk.wire) << (is_lhs ? ".next" : ".curr");
+ }
+ YS_FALLTHROUGH
+ case WireType::ALIAS:
+ case WireType::CONST:
+ log_assert(!is_lhs);
+ return dump_sigspec(wire_type.sig_subst.extract(chunk.offset, chunk.width), is_lhs, for_debug);
+ case WireType::UNUSED:
+ log_assert(is_lhs);
+ f << "value<" << chunk.width << ">()";
+ return false;
}
if (chunk.width == chunk.wire->width && chunk.offset == 0)
return false;
@@ -814,92 +987,116 @@ struct CxxrtlWorker {
}
}
- bool dump_sigspec(const RTLIL::SigSpec &sig, bool is_lhs)
+ bool dump_sigspec(const RTLIL::SigSpec &sig, bool is_lhs, bool for_debug = false)
{
if (sig.empty()) {
f << "value<0>()";
return false;
} else if (sig.is_chunk()) {
- return dump_sigchunk(sig.as_chunk(), is_lhs);
+ return dump_sigchunk(sig.as_chunk(), is_lhs, for_debug);
} else {
- dump_sigchunk(*sig.chunks().rbegin(), is_lhs);
- for (auto it = sig.chunks().rbegin() + 1; it != sig.chunks().rend(); ++it) {
- f << ".concat(";
- dump_sigchunk(*it, is_lhs);
- f << ")";
+ bool first = true;
+ auto chunks = sig.chunks();
+ for (auto it = chunks.rbegin(); it != chunks.rend(); it++) {
+ if (!first)
+ f << ".concat(";
+ bool is_complex = dump_sigchunk(*it, is_lhs, for_debug);
+ if (!is_lhs && it->width == 1) {
+ size_t repeat = 1;
+ while ((it + repeat) != chunks.rend() && *(it + repeat) == *it)
+ repeat++;
+ if (repeat > 1) {
+ if (is_complex)
+ f << ".val()";
+ f << ".repeat<" << repeat << ">()";
+ }
+ it += repeat - 1;
+ }
+ if (!first)
+ f << ")";
+ first = false;
}
return true;
}
}
- void dump_sigspec_lhs(const RTLIL::SigSpec &sig)
+ void dump_sigspec_lhs(const RTLIL::SigSpec &sig, bool for_debug = false)
{
- dump_sigspec(sig, /*is_lhs=*/true);
+ dump_sigspec(sig, /*is_lhs=*/true, for_debug);
}
- void dump_sigspec_rhs(const RTLIL::SigSpec &sig)
+ void dump_sigspec_rhs(const RTLIL::SigSpec &sig, bool for_debug = false)
{
// In the contexts where we want template argument deduction to occur for `template<size_t Bits> ... value<Bits>`,
// it is necessary to have the argument to already be a `value<N>`, since template argument deduction and implicit
// type conversion are mutually exclusive. In these contexts, we use dump_sigspec_rhs() to emit an explicit
// type conversion, but only if the expression needs it.
- bool is_complex = dump_sigspec(sig, /*is_lhs=*/false);
+ bool is_complex = dump_sigspec(sig, /*is_lhs=*/false, for_debug);
if (is_complex)
f << ".val()";
}
- void collect_sigspec_rhs(const RTLIL::SigSpec &sig, std::vector<RTLIL::IdString> &cells)
+ void dump_inlined_cells(const std::vector<const RTLIL::Cell*> &cells)
+ {
+ if (cells.empty()) {
+ f << indent << "// connection\n";
+ } else if (cells.size() == 1) {
+ dump_attrs(cells.front());
+ f << indent << "// cell " << cells.front()->name.str() << "\n";
+ } else {
+ f << indent << "// cells";
+ for (auto cell : cells)
+ f << " " << cell->name.str();
+ f << "\n";
+ }
+ }
+
+ void collect_sigspec_rhs(const RTLIL::SigSpec &sig, bool for_debug, std::vector<const RTLIL::Cell*> &cells)
{
for (auto chunk : sig.chunks()) {
- if (!chunk.wire || !elided_wires.count(chunk.wire))
+ if (!chunk.wire)
continue;
-
- const FlowGraph::Node &node = elided_wires[chunk.wire];
- switch (node.type) {
- case FlowGraph::Node::Type::CONNECT:
- collect_connect(node.connect, cells);
- break;
- case FlowGraph::Node::Type::CELL_EVAL:
- collect_cell_eval(node.cell, cells);
+ const auto &wire_type = wire_types[chunk.wire];
+ switch (wire_type.type) {
+ case WireType::INLINE:
+ if (wire_type.cell_subst != nullptr) {
+ collect_cell_eval(wire_type.cell_subst, for_debug, cells);
+ break;
+ }
+ YS_FALLTHROUGH
+ case WireType::ALIAS:
+ collect_sigspec_rhs(wire_type.sig_subst, for_debug, cells);
break;
default:
- log_assert(false);
+ break;
}
}
}
- void dump_connect_elided(const RTLIL::SigSig &conn)
- {
- dump_sigspec_rhs(conn.second);
- }
-
- bool is_connect_elided(const RTLIL::SigSig &conn)
+ void dump_connect_expr(const RTLIL::SigSig &conn, bool for_debug = false)
{
- return conn.first.is_wire() && elided_wires.count(conn.first.as_wire());
+ dump_sigspec_rhs(conn.second, for_debug);
}
- void collect_connect(const RTLIL::SigSig &conn, std::vector<RTLIL::IdString> &cells)
+ void dump_connect(const RTLIL::SigSig &conn, bool for_debug = false)
{
- if (!is_connect_elided(conn))
- return;
-
- collect_sigspec_rhs(conn.second, cells);
- }
+ std::vector<const RTLIL::Cell*> inlined_cells;
+ collect_sigspec_rhs(conn.second, for_debug, inlined_cells);
+ dump_inlined_cells(inlined_cells);
- void dump_connect(const RTLIL::SigSig &conn)
- {
- if (is_connect_elided(conn))
- return;
-
- f << indent << "// connection\n";
f << indent;
- dump_sigspec_lhs(conn.first);
+ dump_sigspec_lhs(conn.first, for_debug);
f << " = ";
- dump_connect_elided(conn);
+ dump_connect_expr(conn, for_debug);
f << ";\n";
}
- void dump_cell_sync(const RTLIL::Cell *cell)
+ void collect_connect(const RTLIL::SigSig &conn, bool for_debug, std::vector<const RTLIL::Cell*> &cells)
+ {
+ collect_sigspec_rhs(conn.second, for_debug, cells);
+ }
+
+ void dump_cell_sync(const RTLIL::Cell *cell, bool for_debug = false)
{
const char *access = is_cxxrtl_blackbox_cell(cell) ? "->" : ".";
f << indent << "// cell " << cell->name.str() << " syncs\n";
@@ -907,12 +1104,12 @@ struct CxxrtlWorker {
if (cell->output(conn.first))
if (is_cxxrtl_sync_port(cell, conn.first)) {
f << indent;
- dump_sigspec_lhs(conn.second);
+ dump_sigspec_lhs(conn.second, for_debug);
f << " = " << mangle(cell) << access << mangle_wire_name(conn.first) << ".curr;\n";
}
}
- void dump_cell_elided(const RTLIL::Cell *cell)
+ void dump_cell_expr(const RTLIL::Cell *cell, bool for_debug = false)
{
// Unary cells
if (is_unary_cell(cell->type)) {
@@ -920,7 +1117,7 @@ struct CxxrtlWorker {
if (is_extending_cell(cell->type))
f << '_' << (cell->getParam(ID::A_SIGNED).as_bool() ? 's' : 'u');
f << "<" << cell->getParam(ID::Y_WIDTH).as_int() << ">(";
- dump_sigspec_rhs(cell->getPort(ID::A));
+ dump_sigspec_rhs(cell->getPort(ID::A), for_debug);
f << ")";
// Binary cells
} else if (is_binary_cell(cell->type)) {
@@ -929,18 +1126,18 @@ struct CxxrtlWorker {
f << '_' << (cell->getParam(ID::A_SIGNED).as_bool() ? 's' : 'u') <<
(cell->getParam(ID::B_SIGNED).as_bool() ? 's' : 'u');
f << "<" << cell->getParam(ID::Y_WIDTH).as_int() << ">(";
- dump_sigspec_rhs(cell->getPort(ID::A));
+ dump_sigspec_rhs(cell->getPort(ID::A), for_debug);
f << ", ";
- dump_sigspec_rhs(cell->getPort(ID::B));
+ dump_sigspec_rhs(cell->getPort(ID::B), for_debug);
f << ")";
// Muxes
} else if (cell->type == ID($mux)) {
f << "(";
- dump_sigspec_rhs(cell->getPort(ID::S));
+ dump_sigspec_rhs(cell->getPort(ID::S), for_debug);
f << " ? ";
- dump_sigspec_rhs(cell->getPort(ID::B));
+ dump_sigspec_rhs(cell->getPort(ID::B), for_debug);
f << " : ";
- dump_sigspec_rhs(cell->getPort(ID::A));
+ dump_sigspec_rhs(cell->getPort(ID::A), for_debug);
f << ")";
// Parallel (one-hot) muxes
} else if (cell->type == ID($pmux)) {
@@ -948,24 +1145,40 @@ struct CxxrtlWorker {
int s_width = cell->getParam(ID::S_WIDTH).as_int();
for (int part = 0; part < s_width; part++) {
f << "(";
- dump_sigspec_rhs(cell->getPort(ID::S).extract(part));
+ dump_sigspec_rhs(cell->getPort(ID::S).extract(part), for_debug);
f << " ? ";
- dump_sigspec_rhs(cell->getPort(ID::B).extract(part * width, width));
+ dump_sigspec_rhs(cell->getPort(ID::B).extract(part * width, width), for_debug);
f << " : ";
}
- dump_sigspec_rhs(cell->getPort(ID::A));
+ dump_sigspec_rhs(cell->getPort(ID::A), for_debug);
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));
+ dump_sigspec_rhs(cell->getPort(ID::B), for_debug);
f << ".concat(";
- dump_sigspec_rhs(cell->getPort(ID::A));
+ dump_sigspec_rhs(cell->getPort(ID::A), for_debug);
f << ").val()";
// Slices
} else if (cell->type == ID($slice)) {
- dump_sigspec_rhs(cell->getPort(ID::A));
+ dump_sigspec_rhs(cell->getPort(ID::A), for_debug);
f << ".slice<";
f << cell->getParam(ID::OFFSET).as_int() + cell->getParam(ID::Y_WIDTH).as_int() - 1;
f << ",";
@@ -976,61 +1189,33 @@ struct CxxrtlWorker {
}
}
- bool is_cell_elided(const RTLIL::Cell *cell)
- {
- return is_elidable_cell(cell->type) && cell->hasPort(ID::Y) && cell->getPort(ID::Y).is_wire() &&
- elided_wires.count(cell->getPort(ID::Y).as_wire());
- }
-
- void collect_cell_eval(const RTLIL::Cell *cell, std::vector<RTLIL::IdString> &cells)
+ void dump_cell_eval(const RTLIL::Cell *cell, bool for_debug = false)
{
- if (!is_cell_elided(cell))
- return;
-
- cells.push_back(cell->name);
- for (auto port : cell->connections())
- if (port.first != ID::Y)
- collect_sigspec_rhs(port.second, cells);
- }
-
- void dump_cell_eval(const RTLIL::Cell *cell)
- {
- if (is_cell_elided(cell))
- return;
- if (cell->type == ID($meminit))
- return; // Handled elsewhere.
-
- std::vector<RTLIL::IdString> elided_cells;
- if (is_elidable_cell(cell->type)) {
- for (auto port : cell->connections())
- if (port.first != ID::Y)
- collect_sigspec_rhs(port.second, elided_cells);
- }
- if (elided_cells.empty()) {
- dump_attrs(cell);
- f << indent << "// cell " << cell->name.str() << "\n";
- } else {
- f << indent << "// cells";
- for (auto elided_cell : elided_cells)
- f << " " << elided_cell.str();
- f << "\n";
- }
+ std::vector<const RTLIL::Cell*> inlined_cells;
+ collect_cell_eval(cell, for_debug, inlined_cells);
+ dump_inlined_cells(inlined_cells);
// Elidable cells
- if (is_elidable_cell(cell->type)) {
+ if (is_inlinable_cell(cell->type)) {
f << indent;
- dump_sigspec_lhs(cell->getPort(ID::Y));
+ dump_sigspec_lhs(cell->getPort(ID::Y), for_debug);
f << " = ";
- dump_cell_elided(cell);
+ dump_cell_expr(cell, for_debug);
f << ";\n";
// Flip-flops
} else if (is_ff_cell(cell->type)) {
- if (cell->hasPort(ID::CLK) && cell->getPort(ID::CLK).is_wire()) {
+ log_assert(!for_debug);
+ // Clocks might be slices of larger signals but should only ever be single bit
+ if (cell->hasPort(ID::CLK) && is_valid_clock(cell->getPort(ID::CLK))) {
// Edge-sensitive logic
RTLIL::SigBit clk_bit = cell->getPort(ID::CLK)[0];
clk_bit = sigmaps[clk_bit.wire->module](clk_bit);
- f << indent << "if (" << (cell->getParam(ID::CLK_POLARITY).as_bool() ? "posedge_" : "negedge_")
- << mangle(clk_bit) << ") {\n";
+ 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();
if (cell->hasPort(ID::EN)) {
f << indent << "if (";
@@ -1094,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;
@@ -1118,120 +1317,29 @@ 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()) {
- RTLIL::SigBit clk_bit = cell->getPort(ID::CLK)[0];
- clk_bit = sigmaps[clk_bit.wire->module](clk_bit);
- f << indent << "if (" << (cell->getParam(ID::CLK_POLARITY).as_bool() ? "posedge_" : "negedge_")
- << mangle(clk_bit) << ") {\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 -NDEBUG not
- // just 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 << "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 << "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());
// User cells
} else {
+ log_assert(!for_debug);
log_assert(cell->known());
+ bool buffered_inputs = false;
const char *access = is_cxxrtl_blackbox_cell(cell) ? "->" : ".";
for (auto conn : cell->connections())
- if (cell->input(conn.first) && !cell->output(conn.first)) {
- f << indent << mangle(cell) << access << mangle_wire_name(conn.first) << " = ";
+ 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));
+ 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()) {
+ buffered_inputs = true;
+ f << ".next";
+ }
+ 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:
@@ -1240,19 +1348,11 @@ struct CxxrtlWorker {
// with:
// top.prev_p_clk = value<1>{0u}; top.p_clk = value<1>{1u}; top.step();
// Don't rely on this; it will be removed without warning.
- RTLIL::Module *cell_module = cell->module->design->module(cell->type);
- if (cell_module != nullptr && cell_module->wire(conn.first) && conn.second.is_wire()) {
- RTLIL::Wire *cell_module_wire = cell_module->wire(conn.first);
- if (edge_wires[conn.second.as_wire()] && edge_wires[cell_module_wire]) {
- f << indent << mangle(cell) << access << "prev_" << mangle(cell_module_wire) << " = ";
- f << "prev_" << mangle(conn.second.as_wire()) << ";\n";
- }
+ if (edge_wires[conn.second.as_wire()] && edge_wires[cell_module_wire]) {
+ f << indent << mangle(cell) << access << "prev_" << mangle(cell_module_wire) << " = ";
+ f << "prev_" << mangle(conn.second.as_wire()) << ";\n";
}
}
- } else if (cell->input(conn.first)) {
- f << indent << mangle(cell) << access << mangle_wire_name(conn.first) << ".next = ";
- dump_sigspec_rhs(conn.second);
- f << ";\n";
}
auto assign_from_outputs = [&](bool cell_converged) {
for (auto conn : cell->connections()) {
@@ -1270,9 +1370,9 @@ struct CxxrtlWorker {
// have any buffered wires if they were not output ports. Imagine inlining the cell's eval() function,
// and consider the fate of the localized wires that used to be output ports.)
//
- // Unlike cell inputs (which are never buffered), it is not possible to know apriori whether the cell
- // (which may be late bound) will converge immediately. Because of this, the choice between using .curr
- // (appropriate for buffered outputs) and .next (appropriate for unbuffered outputs) is made at runtime.
+ // It is not possible to know apriori whether the cell (which may be late bound) will converge immediately.
+ // Because of this, the choice between using .curr (appropriate for buffered outputs) and .next (appropriate
+ // for unbuffered outputs) is made at runtime.
if (cell_converged && is_cxxrtl_comb_port(cell, conn.first))
f << ".next;\n";
else
@@ -1280,43 +1380,58 @@ struct CxxrtlWorker {
}
}
};
- f << indent << "if (" << mangle(cell) << access << "eval()) {\n";
- inc_indent();
- assign_from_outputs(/*cell_converged=*/true);
- dec_indent();
- f << indent << "} else {\n";
- inc_indent();
+ if (buffered_inputs) {
+ // If we have any buffered inputs, there's no chance of converging immediately.
+ f << indent << mangle(cell) << access << "eval();\n";
f << indent << "converged = false;\n";
assign_from_outputs(/*cell_converged=*/false);
- dec_indent();
- f << indent << "}\n";
+ } else {
+ f << indent << "if (" << mangle(cell) << access << "eval()) {\n";
+ inc_indent();
+ assign_from_outputs(/*cell_converged=*/true);
+ dec_indent();
+ f << indent << "} else {\n";
+ inc_indent();
+ f << indent << "converged = false;\n";
+ assign_from_outputs(/*cell_converged=*/false);
+ dec_indent();
+ f << indent << "}\n";
+ }
}
}
- void dump_assign(const RTLIL::SigSig &sigsig)
+ void collect_cell_eval(const RTLIL::Cell *cell, bool for_debug, std::vector<const RTLIL::Cell*> &cells)
+ {
+ cells.push_back(cell);
+ for (auto port : cell->connections())
+ if (cell->input(port.first))
+ collect_sigspec_rhs(port.second, for_debug, cells);
+ }
+
+ 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;
@@ -1336,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()) {
@@ -1370,24 +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(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() << "\n";
+ 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, 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;
@@ -1427,129 +1552,364 @@ 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_wire(const RTLIL::Wire *wire, bool is_local_context)
+ void dump_mem_rdport(const Mem *mem, int portidx, bool for_debug = false)
{
- if (elided_wires.count(wire))
- return;
-
- if (localized_wires[wire] && is_local_context) {
- dump_attrs(wire);
- f << indent << "value<" << wire->width << "> " << mangle(wire) << ";\n";
+ 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();
}
- if (!localized_wires[wire] && !is_local_context) {
- std::string width;
- if (wire->module->has_attribute(ID(cxxrtl_blackbox)) && wire->has_attribute(ID(cxxrtl_width))) {
- width = wire->get_string_attribute(ID(cxxrtl_width));
+ 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 {
- width = std::to_string(wire->width);
+ f << indent;
+ dump_sigspec_lhs(port.data);
+ f << " = " << mangle(mem) << "[" << valid_index_temp << ".index];\n";
}
-
- dump_attrs(wire);
+ dec_indent();
+ f << indent << "} else {\n";
+ inc_indent();
f << indent;
- if (wire->port_input && wire->port_output)
- f << "/*inout*/ ";
- else if (wire->port_input)
- f << "/*input*/ ";
- else if (wire->port_output)
- f << "/*output*/ ";
- f << (unbuffered_wires[wire] ? "value" : "wire") << "<" << width << "> " << mangle(wire);
- if (wire->has_attribute(ID::init)) {
- f << " ";
- dump_const_init(wire->attributes.at(ID::init));
+ 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();
}
- f << ";\n";
- if (edge_wires[wire]) {
- if (unbuffered_wires[wire]) {
- f << indent << "value<" << width << "> prev_" << mangle(wire);
- if (wire->has_attribute(ID::init)) {
- f << " ";
- dump_const_init(wire->attributes.at(ID::init));
+ 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";
+ }
+ }
+ }
+
+ void dump_wire(const RTLIL::Wire *wire, bool is_local)
+ {
+ const auto &wire_type = wire_types[wire];
+ if (!wire_type.is_named() || wire_type.is_local() != is_local)
+ return;
+
+ dump_attrs(wire);
+ f << indent;
+ if (wire->port_input && wire->port_output)
+ f << "/*inout*/ ";
+ else if (wire->port_input)
+ f << "/*input*/ ";
+ else if (wire->port_output)
+ f << "/*output*/ ";
+ f << (wire_type.is_buffered() ? "wire" : "value");
+ if (wire->module->has_attribute(ID(cxxrtl_blackbox)) && wire->has_attribute(ID(cxxrtl_width))) {
+ f << "<" << wire->get_string_attribute(ID(cxxrtl_width)) << ">";
+ } else {
+ f << "<" << wire->width << ">";
+ }
+ f << " " << mangle(wire) << ";\n";
+ if (edge_wires[wire]) {
+ if (!wire_type.is_buffered()) {
+ f << indent << "value<" << wire->width << "> prev_" << mangle(wire) << ";\n";
+ }
+ for (auto edge_type : edge_types) {
+ if (edge_type.first.wire == wire) {
+ std::string prev, next;
+ if (!wire_type.is_buffered()) {
+ prev = "prev_" + mangle(edge_type.first.wire);
+ next = mangle(edge_type.first.wire);
+ } else {
+ prev = mangle(edge_type.first.wire) + ".curr";
+ next = mangle(edge_type.first.wire) + ".next";
}
- f << ";\n";
- }
- for (auto edge_type : edge_types) {
- if (edge_type.first.wire == wire) {
- std::string prev, next;
- if (unbuffered_wires[wire]) {
- prev = "prev_" + mangle(edge_type.first.wire);
- next = mangle(edge_type.first.wire);
- } else {
- prev = mangle(edge_type.first.wire) + ".curr";
- next = mangle(edge_type.first.wire) + ".next";
- }
- prev += ".slice<" + std::to_string(edge_type.first.offset) + ">().val()";
- next += ".slice<" + std::to_string(edge_type.first.offset) + ">().val()";
- if (edge_type.second != RTLIL::STn) {
- f << indent << "bool posedge_" << mangle(edge_type.first) << "() const {\n";
- inc_indent();
- f << indent << "return !" << prev << " && " << next << ";\n";
- dec_indent();
- f << indent << "}\n";
- }
- if (edge_type.second != RTLIL::STp) {
- f << indent << "bool negedge_" << mangle(edge_type.first) << "() const {\n";
- inc_indent();
- f << indent << "return " << prev << " && !" << next << ";\n";
- dec_indent();
- f << indent << "}\n";
- }
+ prev += ".slice<" + std::to_string(edge_type.first.offset) + ">().val()";
+ next += ".slice<" + std::to_string(edge_type.first.offset) + ">().val()";
+ if (edge_type.second != RTLIL::STn) {
+ f << indent << "bool posedge_" << mangle(edge_type.first) << "() const {\n";
+ inc_indent();
+ f << indent << "return !" << prev << " && " << next << ";\n";
+ dec_indent();
+ f << indent << "}\n";
+ }
+ if (edge_type.second != RTLIL::STp) {
+ f << indent << "bool negedge_" << mangle(edge_type.first) << "() const {\n";
+ inc_indent();
+ f << indent << "return " << prev << " && !" << next << ";\n";
+ dec_indent();
+ f << indent << "}\n";
}
}
}
}
}
- void dump_memory(RTLIL::Module *module, const RTLIL::Memory *memory)
+ void dump_debug_wire(const RTLIL::Wire *wire, bool is_local)
{
- 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);
+ const auto &wire_type = wire_types[wire];
+ if (wire_type.is_member())
+ return;
- 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);
- });
+ const auto &debug_wire_type = debug_wire_types[wire];
+ if (!debug_wire_type.is_named() || debug_wire_type.is_local() != is_local)
+ return;
- 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()) << ", {";
+ dump_attrs(wire);
+ f << indent;
+ if (debug_wire_type.is_outline())
+ f << "/*outline*/ ";
+ f << "value<" << wire->width << "> " << mangle(wire) << ";\n";
+ }
+
+ void dump_reset_method(RTLIL::Module *module)
+ {
+ 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;
+
+ 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";
+
+ 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)
@@ -1574,7 +1934,7 @@ struct CxxrtlWorker {
}
}
for (auto wire : module->wires())
- dump_wire(wire, /*is_local_context=*/true);
+ dump_wire(wire, /*is_local=*/true);
for (auto node : schedule[module]) {
switch (node.type) {
case FlowGraph::Node::Type::CONNECT:
@@ -1586,8 +1946,17 @@ struct CxxrtlWorker {
case FlowGraph::Node::Type::CELL_EVAL:
dump_cell_eval(node.cell);
break;
- case FlowGraph::Node::Type::PROCESS:
- dump_process(node.process);
+ 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::MEM_RDPORT:
+ dump_mem_rdport(node.mem, node.portidx);
+ break;
+ case FlowGraph::Node::Type::MEM_WRPORTS:
+ dump_mem_wrports(node.mem);
break;
}
}
@@ -1596,32 +1965,63 @@ struct CxxrtlWorker {
dec_indent();
}
+ void dump_debug_eval_method(RTLIL::Module *module)
+ {
+ inc_indent();
+ for (auto wire : module->wires())
+ dump_debug_wire(wire, /*is_local=*/true);
+ for (auto node : debug_schedule[module]) {
+ switch (node.type) {
+ case FlowGraph::Node::Type::CONNECT:
+ dump_connect(node.connect, /*for_debug=*/true);
+ break;
+ case FlowGraph::Node::Type::CELL_SYNC:
+ dump_cell_sync(node.cell, /*for_debug=*/true);
+ break;
+ 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();
+ }
+ }
+ dec_indent();
+ }
+
void dump_commit_method(RTLIL::Module *module)
{
inc_indent();
f << indent << "bool changed = false;\n";
for (auto wire : module->wires()) {
- if (elided_wires.count(wire))
- continue;
- if (unbuffered_wires[wire]) {
- if (edge_wires[wire])
- f << indent << "prev_" << mangle(wire) << " = " << mangle(wire) << ";\n";
- continue;
- }
- if (!module->get_bool_attribute(ID(cxxrtl_blackbox)) || wire->port_id != 0)
- f << indent << "changed |= " << mangle(wire) << ".commit();\n";
+ const auto &wire_type = wire_types[wire];
+ if (wire_type.type == WireType::MEMBER && edge_wires[wire])
+ f << indent << "prev_" << mangle(wire) << " = " << mangle(wire) << ";\n";
+ if (wire_type.is_buffered())
+ 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 << "changed |= " << mangle(memory.second) << ".commit();\n";
+ f << indent << "if (" << mangle(&mem) << ".commit()) changed = true;\n";
}
for (auto cell : module->cells()) {
if (is_internal_cell(cell->type))
continue;
const char *access = is_cxxrtl_blackbox_cell(cell) ? "->" : ".";
- f << indent << "changed |= " << mangle(cell) << access << "commit();\n";
+ f << indent << "if (" << mangle(cell) << access << "commit()) changed = true;\n";
}
}
f << indent << "return changed;\n";
@@ -1631,50 +2031,138 @@ struct CxxrtlWorker {
void dump_debug_info_method(RTLIL::Module *module)
{
size_t count_public_wires = 0;
- size_t count_const_wires = 0;
- size_t count_alias_wires = 0;
size_t count_member_wires = 0;
+ size_t count_undriven = 0;
+ size_t count_driven_sync = 0;
+ size_t count_driven_comb = 0;
+ size_t count_mixed_driver = 0;
+ size_t count_alias_wires = 0;
+ size_t count_const_wires = 0;
+ size_t count_inline_wires = 0;
size_t count_skipped_wires = 0;
inc_indent();
f << indent << "assert(path.empty() || path[path.size() - 1] == ' ');\n";
for (auto wire : module->wires()) {
- if (wire->name[0] != '\\')
- continue;
- if (module->get_bool_attribute(ID(cxxrtl_blackbox)) && (wire->port_id == 0))
+ const auto &debug_wire_type = debug_wire_types[wire];
+ if (!wire->name.isPublic())
continue;
count_public_wires++;
- if (debug_const_wires.count(wire)) {
- // Wire tied to a constant
- f << indent << "static const value<" << wire->width << "> const_" << mangle(wire) << " = ";
- dump_const(debug_const_wires[wire]);
- f << ";\n";
- f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(wire));
- f << ", debug_item(const_" << mangle(wire) << ", ";
- f << wire->start_offset << "));\n";
- count_const_wires++;
- } else if (debug_alias_wires.count(wire)) {
- // Alias of a member wire
- f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(wire));
- f << ", debug_item(debug_alias(), " << mangle(debug_alias_wires[wire]) << ", ";
- f << wire->start_offset << "));\n";
- count_alias_wires++;
- } else if (!localized_wires.count(wire)) {
- // Member wire
- f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(wire));
- f << ", debug_item(" << mangle(wire) << ", ";
- f << wire->start_offset << "));\n";
- count_member_wires++;
- } else {
- count_skipped_wires++;
+ switch (debug_wire_type.type) {
+ case WireType::BUFFERED:
+ case WireType::MEMBER: {
+ // Member wire
+ std::vector<std::string> flags;
+
+ if (wire->port_input && wire->port_output)
+ flags.push_back("INOUT");
+ else if (wire->port_output)
+ flags.push_back("OUTPUT");
+ else if (wire->port_input)
+ flags.push_back("INPUT");
+
+ bool has_driven_sync = false;
+ bool has_driven_comb = false;
+ bool has_undriven = false;
+ if (!module->get_bool_attribute(ID(cxxrtl_blackbox))) {
+ for (auto bit : SigSpec(wire))
+ if (!bit_has_state.count(bit))
+ has_undriven = true;
+ else if (bit_has_state[bit])
+ has_driven_sync = true;
+ else
+ has_driven_comb = true;
+ } else if (wire->port_output) {
+ switch (cxxrtl_port_type(module, wire->name)) {
+ case CxxrtlPortType::SYNC:
+ has_driven_sync = true;
+ break;
+ case CxxrtlPortType::COMB:
+ has_driven_comb = true;
+ break;
+ case CxxrtlPortType::UNKNOWN:
+ has_driven_sync = has_driven_comb = true;
+ break;
+ }
+ } else {
+ has_undriven = true;
+ }
+ if (has_undriven)
+ flags.push_back("UNDRIVEN");
+ if (!has_driven_sync && !has_driven_comb && has_undriven)
+ count_undriven++;
+ if (has_driven_sync)
+ flags.push_back("DRIVEN_SYNC");
+ if (has_driven_sync && !has_driven_comb && !has_undriven)
+ count_driven_sync++;
+ if (has_driven_comb)
+ flags.push_back("DRIVEN_COMB");
+ if (!has_driven_sync && has_driven_comb && !has_undriven)
+ count_driven_comb++;
+ if (has_driven_sync + has_driven_comb + has_undriven > 1)
+ count_mixed_driver++;
+
+ f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(wire));
+ f << ", debug_item(" << mangle(wire) << ", " << wire->start_offset;
+ bool first = true;
+ for (auto flag : flags) {
+ if (first) {
+ first = false;
+ f << ", ";
+ } else {
+ f << "|";
+ }
+ f << "debug_item::" << flag;
+ }
+ f << "));\n";
+ count_member_wires++;
+ break;
+ }
+ case WireType::ALIAS: {
+ // Alias of a member wire
+ const RTLIL::Wire *aliasee = debug_wire_type.sig_subst.as_wire();
+ f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(wire));
+ f << ", debug_item(";
+ // If the aliasee is an outline, then the alias must be an outline, too; otherwise downstream
+ // tooling has no way to find out about the outline.
+ if (debug_wire_types[aliasee].is_outline())
+ f << "debug_eval_outline";
+ else
+ f << "debug_alias()";
+ f << ", " << mangle(aliasee) << ", " << wire->start_offset << "));\n";
+ count_alias_wires++;
+ break;
+ }
+ case WireType::CONST: {
+ // Wire tied to a constant
+ f << indent << "static const value<" << wire->width << "> const_" << mangle(wire) << " = ";
+ dump_const(debug_wire_type.sig_subst.as_const());
+ f << ";\n";
+ f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(wire));
+ f << ", debug_item(const_" << mangle(wire) << ", " << wire->start_offset << "));\n";
+ count_const_wires++;
+ break;
+ }
+ case WireType::OUTLINE: {
+ // Localized or inlined, but rematerializable wire
+ f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(wire));
+ f << ", debug_item(debug_eval_outline, " << mangle(wire) << ", " << wire->start_offset << "));\n";
+ count_inline_wires++;
+ break;
+ }
+ default: {
+ // Localized or inlined wire with no debug information
+ count_skipped_wires++;
+ break;
+ }
}
}
if (!module->get_bool_attribute(ID(cxxrtl_blackbox))) {
- for (auto &memory_it : module->memories) {
- if (memory_it.first[0] != '\\')
+ 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))
@@ -1688,10 +2176,18 @@ struct CxxrtlWorker {
log_debug("Debug information statistics for module `%s':\n", log_id(module));
log_debug(" Public wires: %zu, of which:\n", count_public_wires);
- log_debug(" Const wires: %zu\n", count_const_wires);
- log_debug(" Alias wires: %zu\n", count_alias_wires);
- log_debug(" Member wires: %zu\n", count_member_wires);
- log_debug(" Other wires: %zu (no debug information)\n", count_skipped_wires);
+ log_debug(" Member wires: %zu, of which:\n", count_member_wires);
+ log_debug(" Undriven: %zu (incl. inputs)\n", count_undriven);
+ log_debug(" Driven sync: %zu\n", count_driven_sync);
+ log_debug(" Driven comb: %zu\n", count_driven_comb);
+ log_debug(" Mixed driver: %zu\n", count_mixed_driver);
+ if (!module->get_bool_attribute(ID(cxxrtl_blackbox))) {
+ log_debug(" Inline wires: %zu\n", count_inline_wires);
+ log_debug(" Alias wires: %zu\n", count_alias_wires);
+ log_debug(" Const wires: %zu\n", count_const_wires);
+ log_debug(" Other wires: %zu%s\n", count_skipped_wires,
+ count_skipped_wires > 0 ? " (debug unavailable)" : "");
+ }
}
void dump_metadata_map(const dict<RTLIL::IdString, RTLIL::Const> &metadata_map)
@@ -1731,9 +2227,13 @@ struct CxxrtlWorker {
inc_indent();
for (auto wire : module->wires()) {
if (wire->port_id != 0)
- dump_wire(wire, /*is_local_context=*/false);
+ 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";
@@ -1777,11 +2277,14 @@ struct CxxrtlWorker {
f << indent << "struct " << mangle(module) << " : public module {\n";
inc_indent();
for (auto wire : module->wires())
- dump_wire(wire, /*is_local_context=*/false);
- f << "\n";
+ dump_wire(wire, /*is_local=*/false);
+ 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)
@@ -1802,16 +2305,36 @@ 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) << "(interior) {}\n";
+ f << indent << mangle(module) << "() {\n";
+ inc_indent();
+ f << indent << "reset();\n";
+ dec_indent();
+ 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)
+ if (debug_info) {
+ if (debug_eval) {
+ f << "\n";
+ f << indent << "void debug_eval();\n";
+ for (auto wire : module->wires())
+ if (debug_wire_types[wire].is_outline()) {
+ f << indent << "debug_outline debug_eval_outline { std::bind(&"
+ << mangle(module) << "::debug_eval, this) };\n";
+ break;
+ }
+ }
+ f << "\n";
f << indent << "void debug_info(debug_items &items, std::string path = \"\") override;\n";
+ }
dec_indent();
f << indent << "}; // struct " << mangle(module) << "\n";
f << "\n";
@@ -1822,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";
@@ -1831,6 +2358,13 @@ struct CxxrtlWorker {
f << indent << "}\n";
f << "\n";
if (debug_info) {
+ if (debug_eval) {
+ f << indent << "void " << mangle(module) << "::debug_eval() {\n";
+ dump_debug_eval_method(module);
+ f << indent << "}\n";
+ f << "\n";
+ }
+ f << indent << "CXXRTL_EXTREMELY_COLD\n";
f << indent << "void " << mangle(module) << "::debug_info(debug_items &items, std::string path) {\n";
dump_debug_info_method(module);
f << indent << "}\n";
@@ -1935,6 +2469,7 @@ struct CxxrtlWorker {
f << "} // namespace " << design_ns << "\n";
f << "\n";
if (top_module != nullptr && debug_info) {
+ f << "extern \"C\"\n";
f << "cxxrtl_toplevel " << design_ns << "_create() {\n";
inc_indent();
std::string top_type = design_ns + "::" + mangle(top_module);
@@ -1959,7 +2494,9 @@ struct CxxrtlWorker {
void register_edge_signal(SigMap &sigmap, RTLIL::SigSpec signal, RTLIL::SyncType type)
{
signal = sigmap(signal);
- log_assert(signal.is_wire() && signal.is_bit());
+ 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);
RTLIL::SigBit sigbit = signal[0];
@@ -1967,7 +2504,8 @@ struct CxxrtlWorker {
edge_types[sigbit] = type;
else if (edge_types[sigbit] != type)
edge_types[sigbit] = RTLIL::STe;
- edge_wires.insert(signal.as_wire());
+ // Cannot use as_wire because signal might not be a full wire, instead extract the wire from the sigbit
+ edge_wires.insert(sigbit.wire);
}
void analyze_design(RTLIL::Design *design)
@@ -1982,11 +2520,21 @@ 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);
- if (wire->port_input && !wire->port_output)
- unbuffered_wires.insert(wire);
+ if (wire->port_input && !wire->port_output) {
+ wire_types[wire] = debug_wire_types[wire] = {WireType::MEMBER};
+ } else if (wire->port_input || wire->port_output) {
+ wire_types[wire] = debug_wire_types[wire] = {WireType::BUFFERED};
+ }
if (wire->has_attribute(ID(cxxrtl_edge))) {
RTLIL::Const edge_attr = wire->attributes[ID(cxxrtl_edge)];
if (!(edge_attr.flags & RTLIL::CONST_FLAG_STRING) || (int)edge_attr.decode_string().size() != GetSize(wire))
@@ -2016,18 +2564,24 @@ 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;
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() &&
@@ -2039,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->getPort(ID::CLK).is_wire())
+ 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 (cell->getPort(ID::CLK).is_wire())
- 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() && cell->getPort(ID::CLK).is_wire()) {
- 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() && cell->getPort(ID::CLK).is_wire() &&
- 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:
@@ -2113,59 +2663,46 @@ struct CxxrtlWorker {
case RTLIL::STi:
log_assert(false);
}
+ for (auto &memwr : sync->mem_write_actions) {
+ writable_memories.insert({module, memwr.memid});
+ }
+ }
}
- for (auto wire : module->wires()) {
- if (!flow.is_elidable(wire)) continue;
- if (wire->port_id != 0) continue;
- if (wire->get_bool_attribute(ID::keep)) continue;
- if (wire->name.begins_with("$") && !elide_internal) continue;
- if (wire->name.begins_with("\\") && !elide_public) continue;
- if (edge_wires[wire]) continue;
- log_assert(flow.wire_comb_defs[wire].size() == 1);
- elided_wires[wire] = **flow.wire_comb_defs[wire].begin();
- }
-
- dict<FlowGraph::Node*, pool<const RTLIL::Wire*>, hash_ptr_ops> node_defs;
- for (auto wire_comb_def : flow.wire_comb_defs)
- for (auto node : wire_comb_def.second)
- node_defs[node].insert(wire_comb_def.first);
-
+ // Construct a linear order of the flow graph that minimizes the amount of feedback arcs. A flow graph
+ // without feedback arcs can generally be evaluated in a single pass, i.e. it always requires only
+ // a single delta cycle.
Scheduler<FlowGraph::Node> scheduler;
- dict<FlowGraph::Node*, Scheduler<FlowGraph::Node>::Vertex*, hash_ptr_ops> node_map;
+ dict<FlowGraph::Node*, Scheduler<FlowGraph::Node>::Vertex*, hash_ptr_ops> node_vertex_map;
for (auto node : flow.nodes)
- node_map[node] = scheduler.add(node);
- for (auto node_def : node_defs) {
- auto vertex = node_map[node_def.first];
- for (auto wire : node_def.second)
+ node_vertex_map[node] = scheduler.add(node);
+ for (auto node_comb_def : flow.node_comb_defs) {
+ auto vertex = node_vertex_map[node_comb_def.first];
+ for (auto wire : node_comb_def.second)
for (auto succ_node : flow.wire_uses[wire]) {
- auto succ_vertex = node_map[succ_node];
+ auto succ_vertex = node_vertex_map[succ_node];
vertex->succs.insert(succ_vertex);
succ_vertex->preds.insert(vertex);
}
}
- auto eval_order = scheduler.schedule();
- pool<FlowGraph::Node*, hash_ptr_ops> evaluated;
+ // Find out whether the order includes any feedback arcs.
+ std::vector<FlowGraph::Node*> node_order;
+ pool<FlowGraph::Node*, hash_ptr_ops> evaluated_nodes;
pool<const RTLIL::Wire*> feedback_wires;
- for (auto vertex : eval_order) {
+ for (auto vertex : scheduler.schedule()) {
auto node = vertex->data;
- schedule[module].push_back(*node);
+ node_order.push_back(node);
// Any wire that is an output of node vo and input of node vi where vo is scheduled later than vi
// is a feedback wire. Feedback wires indicate apparent logic loops in the design, which may be
// caused by a true logic loop, but usually are a benign result of dependency tracking that works
- // on wire, not bit, level. Nevertheless, feedback wires cannot be localized.
- evaluated.insert(node);
- for (auto wire : node_defs[node])
+ // on wire, not bit, level. Nevertheless, feedback wires cannot be unbuffered.
+ evaluated_nodes.insert(node);
+ for (auto wire : flow.node_comb_defs[node])
for (auto succ_node : flow.wire_uses[wire])
- if (evaluated[succ_node]) {
+ if (evaluated_nodes[succ_node])
feedback_wires.insert(wire);
- // Feedback wires may never be elided because feedback requires state, but the point of elision
- // (and localization) is to eliminate state.
- elided_wires.erase(wire);
- }
}
-
if (!feedback_wires.empty()) {
has_feedback_arcs = true;
log("Module `%s' contains feedback arcs through wires:\n", log_id(module));
@@ -2173,21 +2710,92 @@ struct CxxrtlWorker {
log(" %s\n", log_id(wire));
}
+ // Conservatively assign wire types. Assignment of types BUFFERED and MEMBER is final, but assignment
+ // of type LOCAL may be further refined to UNUSED or INLINE.
for (auto wire : module->wires()) {
+ auto &wire_type = wire_types[wire];
+ wire_type = {WireType::BUFFERED};
+
if (feedback_wires[wire]) continue;
if (wire->port_output && !module->get_bool_attribute(ID::top)) continue;
- if (wire->name.begins_with("$") && !unbuffer_internal) continue;
- if (wire->name.begins_with("\\") && !unbuffer_public) continue;
+ if (!wire->name.isPublic() && !unbuffer_internal) continue;
+ if (wire->name.isPublic() && !unbuffer_public) continue;
if (flow.wire_sync_defs.count(wire) > 0) continue;
- unbuffered_wires.insert(wire);
+ wire_type = {WireType::MEMBER};
+
if (edge_wires[wire]) continue;
if (wire->get_bool_attribute(ID::keep)) continue;
if (wire->port_input || wire->port_output) continue;
- if (wire->name.begins_with("$") && !localize_internal) continue;
- if (wire->name.begins_with("\\") && !localize_public) continue;
- localized_wires.insert(wire);
+ if (!wire->name.isPublic() && !localize_internal) continue;
+ if (wire->name.isPublic() && !localize_public) continue;
+ wire_type = {WireType::LOCAL};
+ }
+
+ // Discover nodes reachable from primary outputs (i.e. members) and collect reachable wire users.
+ pool<FlowGraph::Node*, hash_ptr_ops> worklist;
+ 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)) {
+ for (auto wire : flow.node_comb_defs[node])
+ if (wire_types[wire].is_member())
+ worklist.insert(node); // node drives public wires
+ }
+ }
+ dict<const RTLIL::Wire*, pool<FlowGraph::Node*, hash_ptr_ops>> live_wires;
+ pool<FlowGraph::Node*, hash_ptr_ops> live_nodes;
+ while (!worklist.empty()) {
+ auto node = worklist.pop();
+ live_nodes.insert(node);
+ for (auto wire : flow.node_uses[node]) {
+ live_wires[wire].insert(node);
+ for (auto pred_node : flow.wire_comb_defs[wire])
+ if (!live_nodes[pred_node])
+ worklist.insert(pred_node);
+ }
}
+ // Refine wire types taking into account the amount of uses from reachable nodes only.
+ for (auto wire : module->wires()) {
+ auto &wire_type = wire_types[wire];
+ if (!wire_type.is_local()) continue;
+ if (live_wires[wire].empty()) {
+ wire_type = {WireType::UNUSED}; // wire never used
+ 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);
+ FlowGraph::Node *node = *flow.wire_comb_defs[wire].begin();
+ switch (node->type) {
+ case FlowGraph::Node::Type::CELL_EVAL:
+ if (!is_inlinable_cell(node->cell->type)) continue;
+ wire_type = {WireType::INLINE, node->cell}; // wire replaced with cell
+ break;
+ case FlowGraph::Node::Type::CONNECT:
+ wire_type = {WireType::INLINE, node->connect.second}; // wire replaced with sig
+ break;
+ default: continue;
+ }
+ live_nodes.erase(node);
+ }
+ }
+
+ // Emit reachable nodes in eval().
+ for (auto node : node_order)
+ if (live_nodes[node])
+ schedule[module].push_back(*node);
+
// For maximum performance, the state of the simulation (which is the same as the set of its double buffered
// wires, since using a singly buffered wire for any kind of state introduces a race condition) should contain
// no wires attached to combinatorial outputs. Feedback wires, by definition, make that impossible. However,
@@ -2195,10 +2803,9 @@ struct CxxrtlWorker {
// as a wire with multiple drivers where one of them is combinatorial and the other is synchronous. Such designs
// also require more than one delta cycle to converge.
pool<const RTLIL::Wire*> buffered_comb_wires;
- for (auto wire : module->wires()) {
- if (flow.wire_comb_defs[wire].size() > 0 && !unbuffered_wires[wire] && !feedback_wires[wire])
+ for (auto wire : module->wires())
+ if (wire_types[wire].is_buffered() && !feedback_wires[wire] && flow.wire_comb_defs[wire].size() > 0)
buffered_comb_wires.insert(wire);
- }
if (!buffered_comb_wires.empty()) {
has_buffered_comb_wires = true;
log("Module `%s' contains buffered combinatorial wires:\n", log_id(module));
@@ -2206,44 +2813,154 @@ struct CxxrtlWorker {
log(" %s\n", log_id(wire));
}
+ // Record whether eval() requires only one delta cycle in this module.
eval_converges[module] = feedback_wires.empty() && buffered_comb_wires.empty();
if (debug_info) {
- // Find wires that alias other wires or are tied to a constant; debug information can be enriched with these
- // at essentially zero additional cost.
- //
- // Note that the information collected here can't be used for optimizing the netlist: debug information queries
- // are pure and run on a design in a stable state, which allows assumptions that do not otherwise hold.
+ // Annotate wire bits with the type of their driver; this is exposed in the debug metadata.
+ for (auto item : flow.bit_has_state)
+ bit_has_state.insert(item);
+
+ // Assign debug information wire types to public wires according to the chosen debug level.
+ // Unlike with optimized wire types, all assignments here are final.
for (auto wire : module->wires()) {
- if (wire->name[0] != '\\')
- continue;
- if (!unbuffered_wires[wire])
- continue;
- const RTLIL::Wire *wire_it = wire;
- while (1) {
- if (!(flow.wire_def_elidable.count(wire_it) && flow.wire_def_elidable[wire_it]))
- break; // not an alias: complex def
- log_assert(flow.wire_comb_defs[wire_it].size() == 1);
- FlowGraph::Node *node = *flow.wire_comb_defs[wire_it].begin();
- if (node->type != FlowGraph::Node::Type::CONNECT)
- break; // not an alias: def by cell
- RTLIL::SigSpec rhs_sig = node->connect.second;
- if (rhs_sig.is_wire()) {
- RTLIL::Wire *rhs_wire = rhs_sig.as_wire();
- if (unbuffered_wires[rhs_wire]) {
- wire_it = rhs_wire; // maybe an alias
- } else {
- debug_alias_wires[wire] = rhs_wire; // is an alias
+ const auto &wire_type = wire_types[wire];
+ auto &debug_wire_type = debug_wire_types[wire];
+
+ 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())
+ debug_wire_type = wire_type; // wire is a member
+
+ if (!debug_alias) continue;
+ const RTLIL::Wire *it = wire;
+ while (flow.is_inlinable(it)) {
+ log_assert(flow.wire_comb_defs[it].size() == 1);
+ FlowGraph::Node *node = *flow.wire_comb_defs[it].begin();
+ if (node->type != FlowGraph::Node::Type::CONNECT) break; // not an alias
+ RTLIL::SigSpec rhs = node->connect.second;
+ if (rhs.is_fully_const()) {
+ debug_wire_type = {WireType::CONST, rhs}; // wire replaced with const
+ } else if (rhs.is_wire()) {
+ if (wire_types[rhs.as_wire()].is_member())
+ debug_wire_type = {WireType::ALIAS, rhs}; // wire replaced with wire
+ else if (debug_eval && rhs.as_wire()->name.isPublic())
+ debug_wire_type = {WireType::ALIAS, rhs}; // wire replaced with outline
+ it = rhs.as_wire(); // and keep looking
+ continue;
+ }
+ break;
+ }
+
+ if (!debug_eval) continue;
+ if (!debug_wire_type.is_exact() && !wire_type.is_member())
+ debug_wire_type = {WireType::OUTLINE}; // wire is local or inlined
+ }
+
+ // Discover nodes reachable from primary outputs (i.e. outlines) up until primary inputs (i.e. members)
+ // and collect reachable wire users.
+ pool<FlowGraph::Node*, hash_ptr_ops> worklist;
+ for (auto node : flow.nodes) {
+ if (flow.node_comb_defs.count(node))
+ for (auto wire : flow.node_comb_defs[node])
+ if (debug_wire_types[wire].is_outline())
+ worklist.insert(node); // node drives outline
+ }
+ dict<const RTLIL::Wire*, pool<FlowGraph::Node*, hash_ptr_ops>> debug_live_wires;
+ pool<FlowGraph::Node*, hash_ptr_ops> debug_live_nodes;
+ while (!worklist.empty()) {
+ auto node = worklist.pop();
+ debug_live_nodes.insert(node);
+ for (auto wire : flow.node_uses[node]) {
+ if (debug_wire_types[wire].is_member())
+ continue; // node uses member
+ if (debug_wire_types[wire].is_exact())
+ continue; // node uses alias or const
+ debug_live_wires[wire].insert(node);
+ for (auto pred_node : flow.wire_comb_defs[wire])
+ if (!debug_live_nodes[pred_node])
+ worklist.insert(pred_node);
+ }
+ }
+
+ // Assign debug information wire types to internal wires used by reachable nodes. This is similar
+ // to refining optimized wire types with the exception that the assignments here are first and final.
+ for (auto wire : module->wires()) {
+ const auto &wire_type = wire_types[wire];
+ auto &debug_wire_type = debug_wire_types[wire];
+ if (wire->name.isPublic()) continue;
+
+ 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);
+ FlowGraph::Node *node = *flow.wire_comb_defs[wire].begin();
+ switch (node->type) {
+ case FlowGraph::Node::Type::CELL_EVAL:
+ if (!is_inlinable_cell(node->cell->type)) continue;
+ 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
break;
+ default: continue;
+ }
+ debug_live_nodes.erase(node);
+ } else if (wire_type.is_member() || wire_type.type == WireType::LOCAL) {
+ debug_wire_type = wire_type; // wire not inlinable
+ } else {
+ 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 if (rhs_sig.is_fully_const()) {
- debug_const_wires[wire] = rhs_sig.as_const(); // is a const
- break;
} else {
- break; // not an alias: complex rhs
+ debug_wire_type = {WireType::LOCAL}; // wire used only for debug
}
}
}
+
+ // Emit reachable nodes in debug_eval().
+ for (auto node : node_order)
+ 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) {
@@ -2263,9 +2980,9 @@ struct CxxrtlWorker {
}
}
- void check_design(RTLIL::Design *design, bool &has_sync_init, bool &has_packed_mem)
+ void check_design(RTLIL::Design *design, bool &has_sync_init)
{
- has_sync_init = has_packed_mem = false;
+ has_sync_init = false;
for (auto module : design->modules()) {
if (module->get_blackbox_attribute() && !module->has_attribute(ID(cxxrtl_blackbox)))
@@ -2281,19 +2998,19 @@ struct CxxrtlWorker {
for (auto sync : proc.second->syncs)
if (sync->type == RTLIL::STi)
has_sync_init = true;
-
- for (auto cell : module->cells())
- if (cell->type == ID($mem))
- has_packed_mem = true;
}
}
void prepare_design(RTLIL::Design *design)
{
bool did_anything = false;
- bool has_sync_init, has_packed_mem;
+ bool has_sync_init;
log_push();
- check_design(design, has_sync_init, has_packed_mem);
+ check_design(design, has_sync_init);
+ if (run_hierarchy) {
+ Pass::call(design, "hierarchy -auto-top");
+ did_anything = true;
+ }
if (run_flatten) {
Pass::call(design, "flatten");
did_anything = true;
@@ -2309,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 (has_sync_init || has_packed_mem)
- check_design(design, has_sync_init, has_packed_mem);
- log_assert(!(has_sync_init || has_packed_mem));
+ if (did_anything)
+ check_design(design, has_sync_init);
+ log_assert(!has_sync_init);
log_pop();
if (did_anything)
log_spacer();
@@ -2326,8 +3039,7 @@ struct CxxrtlWorker {
struct CxxrtlBackend : public Backend {
static const int DEFAULT_OPT_LEVEL = 6;
- static const int OPT_LEVEL_DEBUG = 4;
- static const int DEFAULT_DEBUG_LEVEL = 1;
+ static const int DEFAULT_DEBUG_LEVEL = 4;
CxxrtlBackend() : Backend("cxxrtl", "convert design to C++ RTL simulation") { }
void help() override
@@ -2488,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");
@@ -2498,6 +3213,11 @@ struct CxxrtlBackend : public Backend {
log(" place the generated code into namespace <ns-name>. if not specified,\n");
log(" \"cxxrtl_design\" is used.\n");
log("\n");
+ log(" -nohierarchy\n");
+ log(" use design hierarchy as-is. in most designs, a top module should be\n");
+ log(" present as it is exposed through the C API and has unbuffered outputs\n");
+ log(" for improved performance; it will be determined automatically if absent.\n");
+ log("\n");
log(" -noflatten\n");
log(" don't flatten the design. fully flattened designs can evaluate within\n");
log(" one delta cycle if they have no combinatorial feedback.\n");
@@ -2518,13 +3238,13 @@ struct CxxrtlBackend : public Backend {
log(" no optimization.\n");
log("\n");
log(" -O1\n");
- log(" localize internal wires if possible.\n");
+ log(" unbuffer internal wires if possible.\n");
log("\n");
log(" -O2\n");
- log(" like -O1, and unbuffer internal wires if possible.\n");
+ log(" like -O1, and localize internal wires if possible.\n");
log("\n");
log(" -O3\n");
- log(" like -O2, and elide internal wires if possible.\n");
+ log(" like -O2, and inline internal wires if possible.\n");
log("\n");
log(" -O4\n");
log(" like -O3, and unbuffer public wires not marked (*keep*) if possible.\n");
@@ -2533,27 +3253,38 @@ struct CxxrtlBackend : public Backend {
log(" like -O4, and localize public wires not marked (*keep*) if possible.\n");
log("\n");
log(" -O6\n");
- log(" like -O5, and elide public wires not marked (*keep*) if possible.\n");
- log("\n");
- log(" -Og\n");
- log(" highest optimization level that provides debug information for all\n");
- log(" public wires. currently, alias for -O%d.\n", OPT_LEVEL_DEBUG);
+ log(" like -O5, and inline public wires not marked (*keep*) if possible.\n");
log("\n");
log(" -g <level>\n");
log(" set the debug level. the default is -g%d. higher debug levels provide\n", DEFAULT_DEBUG_LEVEL);
log(" more visibility and generate more code, but do not pessimize evaluation.\n");
log("\n");
log(" -g0\n");
- log(" no debug information.\n");
+ log(" no debug information. the C API is disabled.\n");
log("\n");
log(" -g1\n");
- log(" debug information for non-optimized public wires. this also makes it\n");
- log(" possible to use the C API.\n");
+ log(" include bare minimum of debug information necessary to access all design\n");
+ log(" state. the C API is enabled.\n");
+ log("\n");
+ log(" -g2\n");
+ log(" like -g1, but include debug information for all public wires that are\n");
+ log(" directly accessible through the C++ interface.\n");
+ log("\n");
+ log(" -g3\n");
+ log(" like -g2, and include debug information for public wires that are tied\n");
+ log(" to a constant or another public wire.\n");
+ log("\n");
+ log(" -g4\n");
+ log(" like -g3, and compute debug information on demand for all public wires\n");
+ log(" that were optimized out.\n");
log("\n");
}
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;
int opt_level = DEFAULT_OPT_LEVEL;
@@ -2565,6 +3296,18 @@ 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;
+ }
if (args[argidx] == "-noflatten") {
noflatten = true;
continue;
@@ -2574,12 +3317,14 @@ struct CxxrtlBackend : public Backend {
continue;
}
if (args[argidx] == "-Og") {
- opt_level = OPT_LEVEL_DEBUG;
+ log_warning("The `-Og` option has been removed. Use `-g3` instead for complete "
+ "design coverage regardless of optimization level.\n");
continue;
}
if (args[argidx] == "-O" && argidx+1 < args.size() && args[argidx+1] == "g") {
argidx++;
- opt_level = OPT_LEVEL_DEBUG;
+ log_warning("The `-Og` option has been removed. Use `-g3` instead for complete "
+ "design coverage regardless of optimization level.\n");
continue;
}
if (args[argidx] == "-O" && argidx+1 < args.size()) {
@@ -2610,12 +3355,15 @@ 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;
switch (opt_level) {
// the highest level here must match DEFAULT_OPT_LEVEL
case 6:
- worker.elide_public = true;
+ worker.inline_public = true;
YS_FALLTHROUGH
case 5:
worker.localize_public = true;
@@ -2624,7 +3372,7 @@ struct CxxrtlBackend : public Backend {
worker.unbuffer_public = true;
YS_FALLTHROUGH
case 3:
- worker.elide_internal = true;
+ worker.inline_internal = true;
YS_FALLTHROUGH
case 2:
worker.localize_internal = true;
@@ -2639,6 +3387,15 @@ struct CxxrtlBackend : public Backend {
}
switch (debug_level) {
// the highest level here must match DEFAULT_DEBUG_LEVEL
+ case 4:
+ worker.debug_eval = true;
+ YS_FALLTHROUGH
+ case 3:
+ worker.debug_alias = true;
+ YS_FALLTHROUGH
+ case 2:
+ worker.debug_member = true;
+ YS_FALLTHROUGH
case 1:
worker.debug_info = true;
YS_FALLTHROUGH
diff --git a/backends/cxxrtl/cxxrtl_capi.cc b/backends/cxxrtl/cxxrtl_capi.cc
index e0566e152..227173ba8 100644
--- a/backends/cxxrtl/cxxrtl_capi.cc
+++ b/backends/cxxrtl/cxxrtl_capi.cc
@@ -32,9 +32,22 @@ const cxxrtl::debug_items &cxxrtl_debug_items_from_handle(cxxrtl_handle handle)
}
cxxrtl_handle cxxrtl_create(cxxrtl_toplevel design) {
+ return cxxrtl_create_at(design, "");
+}
+
+cxxrtl_handle cxxrtl_create_at(cxxrtl_toplevel design, const char *root) {
+ std::string path = root;
+ if (!path.empty()) {
+ // module::debug_info() accepts either an empty path, or a path ending in space to simplify
+ // the logic in generated code. While this is sketchy at best to expose in the C++ API, this
+ // would be a lot worse in the C API, so don't expose it here.
+ assert(path.back() != ' ');
+ path += ' ';
+ }
+
cxxrtl_handle handle = new _cxxrtl_handle;
handle->module = std::move(design->module);
- handle->module->debug_info(handle->objects);
+ handle->module->debug_info(handle->objects, path);
delete design;
return handle;
}
@@ -43,6 +56,18 @@ void cxxrtl_destroy(cxxrtl_handle handle) {
delete handle;
}
+void cxxrtl_reset(cxxrtl_handle handle) {
+ handle->module->reset();
+}
+
+int cxxrtl_eval(cxxrtl_handle handle) {
+ return handle->module->eval();
+}
+
+int cxxrtl_commit(cxxrtl_handle handle) {
+ return handle->module->commit();
+}
+
size_t cxxrtl_step(cxxrtl_handle handle) {
return handle->module->step();
}
@@ -61,3 +86,7 @@ void cxxrtl_enum(cxxrtl_handle handle, void *data,
for (auto &it : handle->objects.table)
callback(data, it.first.c_str(), static_cast<cxxrtl_object*>(&it.second[0]), it.second.size());
}
+
+void cxxrtl_outline_eval(cxxrtl_outline outline) {
+ outline->eval();
+}
diff --git a/backends/cxxrtl/cxxrtl_capi.h b/backends/cxxrtl/cxxrtl_capi.h
index 599284898..2df2b7287 100644
--- a/backends/cxxrtl/cxxrtl_capi.h
+++ b/backends/cxxrtl/cxxrtl_capi.h
@@ -52,15 +52,45 @@ typedef struct _cxxrtl_handle *cxxrtl_handle;
// The `design` is consumed by this operation and cannot be used afterwards.
cxxrtl_handle cxxrtl_create(cxxrtl_toplevel design);
+// Create a design handle at a given hierarchy position from a design toplevel.
+//
+// This operation is similar to `cxxrtl_create`, except the full hierarchical name of every object
+// is prepended with `root`.
+cxxrtl_handle cxxrtl_create_at(cxxrtl_toplevel design, const char *root);
+
// Release all resources used by a design and its handle.
void cxxrtl_destroy(cxxrtl_handle handle);
+// Reinitialize the design, replacing the internal state with the reset values while preserving
+// black boxes.
+//
+// This operation is essentially equivalent to a power-on reset. Values, wires, and memories are
+// returned to their reset state while preserving the state of black boxes and keeping all of
+// the interior pointers obtained with e.g. `cxxrtl_get` valid.
+void cxxrtl_reset(cxxrtl_handle handle);
+
+// Evaluate the design, propagating changes on inputs to the `next` value of internal state and
+// output wires.
+//
+// Returns 1 if the design is known to immediately converge, 0 otherwise.
+int cxxrtl_eval(cxxrtl_handle handle);
+
+// Commit the design, replacing the `curr` value of internal state and output wires with the `next`
+// value.
+//
+// Return 1 if any of the `curr` values were updated, 0 otherwise.
+int cxxrtl_commit(cxxrtl_handle handle);
+
// Simulate the design to a fixed point.
//
// Returns the number of delta cycles.
size_t cxxrtl_step(cxxrtl_handle handle);
// Type of a simulated object.
+//
+// The type of a simulated object indicates the way it is stored and the operations that are legal
+// to perform on it (i.e. won't crash the simulation). It says very little about object semantics,
+// which is specified through flags.
enum cxxrtl_type {
// Values correspond to singly buffered netlist nodes, i.e. nodes driven exclusively by
// combinatorial cells, or toplevel input nodes.
@@ -74,7 +104,8 @@ enum cxxrtl_type {
CXXRTL_VALUE = 0,
// Wires correspond to doubly buffered netlist nodes, i.e. nodes driven, at least in part, by
- // storage cells, or by combinatorial cells that are a part of a feedback path.
+ // storage cells, or by combinatorial cells that are a part of a feedback path. They are also
+ // present in non-optimized builds.
//
// Wires can be inspected via the `curr` pointer and modified via the `next` pointer (which are
// distinct for wires). Note that changes to the bits driven by combinatorial cells will be
@@ -91,19 +122,91 @@ enum cxxrtl_type {
CXXRTL_MEMORY = 2,
// Aliases correspond to netlist nodes driven by another node such that their value is always
- // exactly equal, or driven by a constant value.
+ // exactly equal.
//
// Aliases can be inspected via the `curr` pointer. They cannot be modified, and the `next`
// pointer is always NULL.
CXXRTL_ALIAS = 3,
+ // Outlines correspond to netlist nodes that were optimized in a way that makes them inaccessible
+ // outside of a module's `eval()` function. At the highest debug information level, every inlined
+ // node has a corresponding outline object.
+ //
+ // Outlines can be inspected via the `curr` pointer and can never be modified; the `next` pointer
+ // is always NULL. Unlike all other objects, the bits of an outline object are meaningful only
+ // after a call to `cxxrtl_outline_eval` and until any subsequent modification to the netlist.
+ // Observing this requirement is the responsibility of the caller; it is not enforced.
+ //
+ // Outlines always correspond to combinatorial netlist nodes that are not ports.
+ CXXRTL_OUTLINE = 4,
+
// More object types may be added in the future, but the existing ones will never change.
};
+// Flags of a simulated object.
+//
+// The flags of a simulated object indicate its role in the netlist:
+// * The flags `CXXRTL_INPUT` and `CXXRTL_OUTPUT` designate module ports.
+// * The flags `CXXRTL_DRIVEN_SYNC`, `CXXRTL_DRIVEN_COMB`, and `CXXRTL_UNDRIVEN` specify
+// the semantics of node state. An object with several of these flags set has different bits
+// follow different semantics.
+enum cxxrtl_flag {
+ // Node is a module input port.
+ //
+ // This flag can be set on objects of type `CXXRTL_VALUE` and `CXXRTL_WIRE`. It may be combined
+ // with `CXXRTL_OUTPUT`, as well as other flags.
+ CXXRTL_INPUT = 1 << 0,
+
+ // Node is a module output port.
+ //
+ // This flag can be set on objects of type `CXXRTL_WIRE`. It may be combined with `CXXRTL_INPUT`,
+ // as well as other flags.
+ CXXRTL_OUTPUT = 1 << 1,
+
+ // Node is a module inout port.
+ //
+ // This flag can be set on objects of type `CXXRTL_WIRE`. It may be combined with other flags.
+ CXXRTL_INOUT = (CXXRTL_INPUT|CXXRTL_OUTPUT),
+
+ // Node has bits that are driven by a storage cell.
+ //
+ // This flag can be set on objects of type `CXXRTL_WIRE`. It may be combined with
+ // `CXXRTL_DRIVEN_COMB` and `CXXRTL_UNDRIVEN`, as well as other flags.
+ //
+ // This flag is set on wires that have bits connected directly to the output of a flip-flop or
+ // a latch, and hold its state. Many `CXXRTL_WIRE` objects may not have the `CXXRTL_DRIVEN_SYNC`
+ // flag set; for example, output ports and feedback wires generally won't. Writing to the `next`
+ // pointer of these wires updates stored state, and for designs without combinatorial loops,
+ // capturing the value from every of these wires through the `curr` pointer creates a complete
+ // snapshot of the design state.
+ CXXRTL_DRIVEN_SYNC = 1 << 2,
+
+ // Node has bits that are driven by a combinatorial cell or another node.
+ //
+ // This flag can be set on objects of type `CXXRTL_VALUE`, `CXXRTL_WIRE`, and `CXXRTL_OUTLINE`.
+ // It may be combined with `CXXRTL_DRIVEN_SYNC` and `CXXRTL_UNDRIVEN`, as well as other flags.
+ //
+ // This flag is set on objects that have bits connected to the output of a combinatorial cell,
+ // or directly to another node. For designs without combinatorial loops, writing to such bits
+ // through the `next` pointer (if it is not NULL) has no effect.
+ CXXRTL_DRIVEN_COMB = 1 << 3,
+
+ // Node has bits that are not driven.
+ //
+ // This flag can be set on objects of type `CXXRTL_VALUE` and `CXXRTL_WIRE`. It may be combined
+ // with `CXXRTL_DRIVEN_SYNC` and `CXXRTL_DRIVEN_COMB`, as well as other flags.
+ //
+ // This flag is set on objects that have bits not driven by an output of any cell or by another
+ // node, such as inputs and dangling wires.
+ CXXRTL_UNDRIVEN = 1 << 4,
+
+ // More object flags may be added in the future, but the existing ones will never change.
+};
+
// Description of a simulated object.
//
-// The `data` array can be accessed directly to inspect and, if applicable, modify the bits
-// stored in the object.
+// The `curr` and `next` arrays can be accessed directly to inspect and, if applicable, modify
+// the bits stored in the object.
struct cxxrtl_object {
// Type of the object.
//
@@ -111,6 +214,9 @@ struct cxxrtl_object {
// determines all other properties of the object.
uint32_t type; // actually `enum cxxrtl_type`
+ // Flags of the object.
+ uint32_t flags; // actually bit mask of `enum cxxrtl_flags`
+
// Width of the object in bits.
size_t width;
@@ -137,6 +243,12 @@ struct cxxrtl_object {
uint32_t *curr;
uint32_t *next;
+ // Opaque reference to an outline. Only meaningful for outline objects.
+ //
+ // See the documentation of `cxxrtl_outline` for details. When creating a `cxxrtl_object`, set
+ // this field to NULL.
+ struct _cxxrtl_outline *outline;
+
// More description fields may be added in the future, but the existing ones will never change.
};
@@ -160,7 +272,7 @@ struct cxxrtl_object *cxxrtl_get_parts(cxxrtl_handle handle, const char *name, s
// This function is a shortcut for the most common use of `cxxrtl_get_parts`. It asserts that,
// if the object exists, it consists of a single part. If assertions are disabled, it returns NULL
// for multi-part objects.
-inline struct cxxrtl_object *cxxrtl_get(cxxrtl_handle handle, const char *name) {
+static inline struct cxxrtl_object *cxxrtl_get(cxxrtl_handle handle, const char *name) {
size_t parts = 0;
struct cxxrtl_object *object = cxxrtl_get_parts(handle, name, &parts);
assert(object == NULL || parts == 1);
@@ -178,6 +290,20 @@ void cxxrtl_enum(cxxrtl_handle handle, void *data,
void (*callback)(void *data, const char *name,
struct cxxrtl_object *object, size_t parts));
+// Opaque reference to an outline.
+//
+// An outline is a group of outline objects that are evaluated simultaneously. The identity of
+// an outline can be compared to determine whether any two objects belong to the same outline.
+typedef struct _cxxrtl_outline *cxxrtl_outline;
+
+// Evaluate an outline.
+//
+// After evaluating an outline, the bits of every outline object contained in it are consistent
+// with the current state of the netlist. In general, any further modification to the netlist
+// causes every outline object to become stale, after which the corresponding outline must be
+// re-evaluated, otherwise the bits read from that object are meaningless.
+void cxxrtl_outline_eval(cxxrtl_outline outline);
+
#ifdef __cplusplus
}
#endif
diff --git a/backends/cxxrtl/cxxrtl_vcd.h b/backends/cxxrtl/cxxrtl_vcd.h
index dbeabbaf2..b76922bbd 100644
--- a/backends/cxxrtl/cxxrtl_vcd.h
+++ b/backends/cxxrtl/cxxrtl_vcd.h
@@ -28,10 +28,13 @@ class vcd_writer {
size_t ident;
size_t width;
chunk_t *curr;
- size_t prev_off;
+ size_t cache_offset;
+ debug_outline *outline;
+ bool *outline_warm;
};
std::vector<std::string> current_scope;
+ std::map<debug_outline*, bool> outlines;
std::vector<variable> variables;
std::vector<chunk_t> cache;
std::map<chunk_t*, size_t> aliases;
@@ -66,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) + "]";
@@ -112,16 +128,22 @@ class vcd_writer {
buffer += '\n';
}
- const variable &register_variable(size_t width, chunk_t *curr, bool constant = false) {
+ void reset_outlines() {
+ for (auto &outline_it : outlines)
+ outline_it.second = /*warm=*/(outline_it.first == nullptr);
+ }
+
+ variable &register_variable(size_t width, chunk_t *curr, bool constant = false, debug_outline *outline = nullptr) {
if (aliases.count(curr)) {
return variables[aliases[curr]];
} else {
+ auto outline_it = outlines.emplace(outline, /*warm=*/(outline == nullptr)).first;
const size_t chunks = (width + (sizeof(chunk_t) * 8 - 1)) / (sizeof(chunk_t) * 8);
aliases[curr] = variables.size();
if (constant) {
- variables.emplace_back(variable { variables.size(), width, curr, (size_t)-1 });
+ variables.emplace_back(variable { variables.size(), width, curr, (size_t)-1, outline_it->first, &outline_it->second });
} else {
- variables.emplace_back(variable { variables.size(), width, curr, cache.size() });
+ variables.emplace_back(variable { variables.size(), width, curr, cache.size(), outline_it->first, &outline_it->second });
cache.insert(cache.end(), &curr[0], &curr[chunks]);
}
return variables.back();
@@ -129,13 +151,17 @@ class vcd_writer {
}
bool test_variable(const variable &var) {
- if (var.prev_off == (size_t)-1)
+ if (var.cache_offset == (size_t)-1)
return false; // constant
+ if (!*var.outline_warm) {
+ var.outline->eval();
+ *var.outline_warm = true;
+ }
const size_t chunks = (var.width + (sizeof(chunk_t) * 8 - 1)) / (sizeof(chunk_t) * 8);
- if (std::equal(&var.curr[0], &var.curr[chunks], &cache[var.prev_off])) {
+ if (std::equal(&var.curr[0], &var.curr[chunks], &cache[var.cache_offset])) {
return false;
} else {
- std::copy(&var.curr[0], &var.curr[chunks], &cache[var.prev_off]);
+ std::copy(&var.curr[0], &var.curr[chunks], &cache[var.cache_offset]);
return true;
}
}
@@ -197,6 +223,10 @@ public:
emit_var(register_variable(item.width, item.curr),
"wire", name, item.lsb_at, multipart);
break;
+ case debug_item::OUTLINE:
+ emit_var(register_variable(item.width, item.curr, /*constant=*/false, item.outline),
+ "wire", name, item.lsb_at, multipart);
+ break;
}
}
@@ -211,13 +241,13 @@ public:
}
void add(const debug_items &items) {
- this->template add(items, [](const std::string &, const debug_item &) {
+ this->add(items, [](const std::string &, const debug_item &) {
return true;
});
}
void add_without_memories(const debug_items &items) {
- this->template add(items, [](const std::string &, const debug_item &item) {
+ this->add(items, [](const std::string &, const debug_item &item) {
return item.type != debug_item::MEMORY;
});
}
@@ -228,6 +258,7 @@ public:
emit_scope({});
emit_enddefinitions();
}
+ reset_outlines();
emit_time(timestamp);
for (auto var : variables)
if (test_variable(var) || first_sample) {
diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc
index 5e6becfd0..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
@@ -330,7 +330,7 @@ struct EdifBackend : public Backend {
}
*f << stringf("\n (property %s (string \"%d'h%s\"))", EDIF_DEF(name), GetSize(val.bits), hex_string.c_str());
}
- };
+ };
for (auto module : sorted_modules)
{
if (module->get_blackbox_attribute())
@@ -373,8 +373,8 @@ struct EdifBackend : public Backend {
}
{
- int c1 = w1->name[0] == '\\';
- int c2 = w2->name[0] == '\\';
+ int c1 = w1->name.isPublic();
+ int c2 = w2->name.isPublic();
if (c1 > c2) goto promote;
if (c1 < c2) goto nopromote;
@@ -524,7 +524,7 @@ struct EdifBackend : public Backend {
*f << stringf(" (portRef %c (instanceRef GND))\n", gndvccy ? 'Y' : 'G');
if (sig == RTLIL::State::S1)
*f << stringf(" (portRef %c (instanceRef VCC))\n", gndvccy ? 'Y' : 'P');
- }
+ }
*f << stringf(" )");
if (attr_properties && sig.wire != NULL)
for (auto &p : sig.wire->attributes)
diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc
index 9739a7a9f..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>
@@ -102,135 +103,269 @@ const char *make_id(IdString id)
return namecache.at(id).c_str();
}
-struct FirrtlWorker
+std::string dump_const_string(const RTLIL::Const &data)
{
- Module *module;
- std::ostream &f;
+ std::string res_str;
- dict<SigBit, pair<string, int>> reverse_wire_map;
- string unconn_id;
- RTLIL::Design *design;
- std::string indent;
+ std::string str = data.decode_string();
+ for (size_t i = 0; i < str.size(); i++)
+ {
+ if (str[i] == '\n')
+ res_str += "\\n";
+ else if (str[i] == '\t')
+ res_str += "\\t";
+ else if (str[i] < 32)
+ res_str += stringf("\\%03o", str[i]);
+ else if (str[i] == '"')
+ res_str += "\\\"";
+ else if (str[i] == '\\')
+ res_str += "\\\\";
+ else
+ res_str += str[i];
+ }
- // 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());
- }
- }
+ return res_str;
+}
- // We need a default constructor for the dict insert.
- memory() : pCell(0), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec(""){}
+std::string dump_const(const RTLIL::Const &data)
+{
+ std::string res_str;
+
+ // // For debugging purposes to find out how Yosys encodes flags.
+ // res_str += stringf("flags_%x --> ", data.flags);
- const char *atLine() {
- if (srcLine == "") {
- if (pCell) {
- auto p = pCell->attributes.find(ID::src);
- srcLine = " at " + p->second.decode_string();
+ // Real-valued parameter.
+ if (data.flags & RTLIL::CONST_FLAG_REAL)
+ {
+ // Yosys stores real values as strings, so we call the string dumping code.
+ res_str += dump_const_string(data);
+ }
+ // String parameter.
+ else if (data.flags & RTLIL::CONST_FLAG_STRING)
+ {
+ res_str += "\"";
+ res_str += dump_const_string(data);
+ res_str += "\"";
+ }
+ // Numeric (non-real) parameter.
+ else
+ {
+ int width = data.bits.size();
+
+ // If a standard 32-bit int, then emit standard int value like "56" or
+ // "-56". Firrtl supports negative-valued int literals.
+ //
+ // SignedInt
+ // : ( '+' | '-' ) PosInt
+ // ;
+ if (width <= 32)
+ {
+ int32_t int_val = 0;
+
+ for (int i = 0; i < width; i++)
+ {
+ switch (data.bits[i])
+ {
+ case State::S0: break;
+ case State::S1: int_val |= (1 << i); break;
+ default:
+ log_error("Unexpected int value\n");
+ break;
}
}
- return srcLine.c_str();
- }
- void add_memory_read_port(read_port &rp) {
- read_ports.push_back(rp);
+
+ res_str += stringf("%d", int_val);
}
- void add_memory_write_port(write_port &wp) {
- write_ports.push_back(wp);
+ else
+ {
+ // If value is larger than 32 bits, then emit a binary representation of
+ // the number as integers are not large enough to contain the result.
+ // There is a caveat to this approach though:
+ //
+ // Note that parameter may be defined as having a fixed width as follows:
+ //
+ // parameter signed [26:0] test_signed;
+ // parameter [26:0] test_unsigned;
+ // parameter signed [40:0] test_signed_large;
+ //
+ // However, if you assign a value on the RHS without specifying the
+ // precision, then yosys considers the value you used as an int and
+ // assigns it a width of 32 bits regardless of the type of the parameter.
+ //
+ // defparam <inst_name> .test_signed = 49; (width = 32, though should be 27 based on definition)
+ // defparam <inst_name> .test_unsigned = 40'd35; (width = 40, though should be 27 based on definition)
+ // defparam <inst_name> .test_signed_large = 40'd12; (width = 40)
+ //
+ // We therefore may lose the precision of the original verilog literal if
+ // it was written without its bitwidth specifier.
+
+ // Emit binary prefix for string.
+ res_str += "\"b";
+
+ // Emit bits.
+ for (int i = width - 1; i >= 0; i--)
+ {
+ log_assert(i < width);
+ switch (data.bits[i])
+ {
+ case State::S0: res_str += "0"; break;
+ case State::S1: res_str += "1"; break;
+ case State::Sx: res_str += "x"; break;
+ case State::Sz: res_str += "z"; break;
+ case State::Sa: res_str += "-"; break;
+ case State::Sm: res_str += "m"; break;
+ }
+ }
+
+ res_str += "\"";
}
- 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;
+ }
+
+ return res_str;
+}
+
+std::string extmodule_name(RTLIL::Cell *cell, RTLIL::Module *mod_instance)
+{
+ // Since we are creating a custom extmodule for every cell that instantiates
+ // this blackbox, we need to create a custom name for it. We just use the
+ // name of the blackbox itself followed by the name of the cell.
+ const std::string cell_name = std::string(make_id(cell->name));
+ const std::string blackbox_name = std::string(make_id(mod_instance->name));
+ const std::string extmodule_name = blackbox_name + "_" + cell_name;
+ return extmodule_name;
+}
+
+/**
+ * Emits a parameterized extmodule. Instance parameters are obtained from
+ * ''cell'' as it represents the instantiation of the blackbox defined by
+ * ''mod_instance'' and therefore contains all its instance parameters.
+ */
+void emit_extmodule(RTLIL::Cell *cell, RTLIL::Module *mod_instance, std::ostream &f)
+{
+ const std::string indent = " ";
+
+ const std::string blackbox_name = std::string(make_id(mod_instance->name));
+ const std::string exported_name = extmodule_name(cell, mod_instance);
+
+ // We use the cell's fileinfo for this extmodule as its parameters come from
+ // the cell and not from the module itself (the module contains default
+ // parameters, not the instance-specific ones we're using to emit the
+ // extmodule).
+ const std::string extmoduleFileinfo = getFileinfo(cell);
+
+ // Emit extmodule header.
+ f << stringf(" extmodule %s: %s\n", exported_name.c_str(), extmoduleFileinfo.c_str());
+
+ // Emit extmodule ports.
+ for (auto wire : mod_instance->wires())
+ {
+ const auto wireName = make_id(wire->name);
+ const std::string wireFileinfo = getFileinfo(wire);
+
+ if (wire->port_input && wire->port_output)
+ {
+ log_error("Module port %s.%s is inout!\n", log_id(mod_instance), log_id(wire));
}
- };
- dict<string, memory> memories;
+ const std::string portDecl = stringf("%s%s %s: UInt<%d> %s\n",
+ indent.c_str(),
+ wire->port_input ? "input" : "output",
+ wireName,
+ wire->width,
+ wireFileinfo.c_str()
+ );
+
+ f << portDecl;
+ }
- void register_memory(memory &m)
+ // Emit extmodule "defname" field. This is the name of the verilog blackbox
+ // that is used when verilog is emitted, so we use the name of mod_instance
+ // here.
+ f << stringf("%sdefname = %s\n", indent.c_str(), blackbox_name.c_str());
+
+ // Emit extmodule generic parameters.
+ for (const auto &p : cell->parameters)
{
- memories[m.name] = m;
+ const RTLIL::IdString p_id = p.first;
+ const RTLIL::Const p_value = p.second;
+
+ std::string param_name(p_id.c_str());
+ const std::string param_value = dump_const(p_value);
+
+ // Remove backslashes from parameters as these come from the internal RTLIL
+ // naming scheme, but should not exist in the emitted firrtl blackboxes.
+ // When firrtl is converted to verilog and given to downstream synthesis
+ // tools, these tools expect to find blackbox names and parameters as they
+ // were originally defined, i.e. without the extra RTLIL naming conventions.
+ param_name.erase(
+ std::remove(param_name.begin(), param_name.end(), '\\'),
+ param_name.end()
+ );
+
+ f << stringf("%sparameter %s = %s\n", indent.c_str(), param_name.c_str(), param_value.c_str());
+ }
+
+ f << "\n";
+}
+
+/**
+ * Emits extmodules for every instantiated blackbox in the design.
+ *
+ * RTLIL stores instance parameters at the cell's instantiation location.
+ * However, firrtl does not support module parameterization (everything is
+ * already elaborated). Firrtl instead supports external modules (extmodule),
+ * i.e. blackboxes that are defined by verilog and which have no body in
+ * firrtl itself other than the declaration of the blackboxes ports and
+ * parameters.
+ *
+ * Furthermore, firrtl does not support parameterization (even of extmodules)
+ * at a module's instantiation location and users must instead declare
+ * different extmodules with different instance parameters in the extmodule
+ * definition itself.
+ *
+ * This function goes through the design to identify all RTLIL blackboxes
+ * and emit parameterized extmodules with a unique name for each of them. The
+ * name that's given to the extmodule is
+ *
+ * <blackbox_name>_<instance_name>
+ *
+ * Beware that it is therefore necessary for users to replace "parameterized"
+ * instances in the RTLIL sense with these custom extmodules for the firrtl to
+ * be valid.
+ */
+void emit_elaborated_extmodules(RTLIL::Design *design, std::ostream &f)
+{
+ for (auto module : design->modules())
+ {
+ for (auto cell : module->cells())
+ {
+ // Is this cell a module instance?
+ bool cellIsModuleInstance = cell->type[0] != '$';
+
+ if (cellIsModuleInstance)
+ {
+ // Find the module corresponding to this instance.
+ auto modInstance = design->module(cell->type);
+ bool modIsBlackbox = modInstance->get_blackbox_attribute();
+
+ if (modIsBlackbox)
+ {
+ emit_extmodule(cell, modInstance, f);
+ }
+ }
+ }
}
+}
+
+struct FirrtlWorker
+{
+ Module *module;
+ std::ostream &f;
+
+ dict<SigBit, pair<string, int>> reverse_wire_map;
+ string unconn_id;
+ RTLIL::Design *design;
+ std::string indent;
void register_reverse_wire_map(string id, SigSpec sig)
{
@@ -328,8 +463,16 @@ struct FirrtlWorker
log_warning("No instance for %s.%s\n", cell_type.c_str(), cell_name.c_str());
return;
}
+
+ // If the instance is that of a blackbox, use the modified extmodule name
+ // that contains per-instance parameterizations. These instances were
+ // emitted earlier in the firrtl backend.
+ const std::string instanceName = instModule->get_blackbox_attribute() ?
+ extmodule_name(cell, instModule) :
+ instanceOf;
+
std::string cellFileinfo = getFileinfo(cell);
- wire_exprs.push_back(stringf("%s" "inst %s%s of %s %s", indent.c_str(), cell_name.c_str(), cell_name_comment.c_str(), instanceOf.c_str(), cellFileinfo.c_str()));
+ wire_exprs.push_back(stringf("%s" "inst %s%s of %s %s", indent.c_str(), cell_name.c_str(), cell_name_comment.c_str(), instanceName.c_str(), cellFileinfo.c_str()));
for (auto it = cell->connections().begin(); it != cell->connections().end(); ++it) {
if (it->second.size() > 0) {
@@ -392,38 +535,15 @@ struct FirrtlWorker
return result;
}
- void emit_extmodule()
- {
- std::string moduleFileinfo = getFileinfo(module);
- f << stringf(" extmodule %s: %s\n", make_id(module->name), moduleFileinfo.c_str());
- vector<std::string> port_decls;
-
- for (auto wire : module->wires())
- {
- const auto wireName = make_id(wire->name);
- std::string wireFileinfo = getFileinfo(wire);
-
- if (wire->port_input && wire->port_output)
- {
- log_error("Module port %s.%s is inout!\n", log_id(module), log_id(wire));
- }
- port_decls.push_back(stringf(" %s %s: UInt<%d> %s\n", wire->port_input ? "input" : "output",
- wireName, wire->width, wireFileinfo.c_str()));
- }
-
- for (auto &str : port_decls)
- {
- f << str;
- }
-
- f << stringf("\n");
- }
-
void emit_module()
{
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())
{
@@ -440,25 +560,26 @@ struct FirrtlWorker
{
if (wire->port_input && wire->port_output)
log_error("Module port %s.%s is inout!\n", log_id(module), log_id(wire));
- port_decls.push_back(stringf(" %s %s: UInt<%d> %s\n", wire->port_input ? "input" : "output",
+ port_decls.push_back(stringf("%s%s %s: UInt<%d> %s\n", indent.c_str(), wire->port_input ? "input" : "output",
wireName, wire->width, wireFileinfo.c_str()));
}
else
{
- wire_decls.push_back(stringf(" wire %s: UInt<%d> %s\n", wireName, wire->width, wireFileinfo.c_str()));
+ wire_decls.push_back(stringf("%swire %s: UInt<%d> %s\n", indent.c_str(), wireName, wire->width, wireFileinfo.c_str()));
}
}
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"
@@ -476,7 +597,7 @@ struct FirrtlWorker
if (cell->type.in(ID($not), ID($logic_not), ID($_NOT_), ID($neg), ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_bool), ID($reduce_xnor)))
{
string a_expr = make_expr(cell->getPort(ID::A));
- wire_decls.push_back(stringf(" wire %s: UInt<%d> %s\n", y_id.c_str(), y_width, cellFileinfo.c_str()));
+ wire_decls.push_back(stringf("%swire %s: UInt<%d> %s\n", indent.c_str(), y_id.c_str(), y_width, cellFileinfo.c_str()));
if (a_signed) {
a_expr = "asSInt(" + a_expr + ")";
@@ -516,7 +637,7 @@ struct FirrtlWorker
if ((firrtl_is_signed && !always_uint))
expr = stringf("asUInt(%s)", expr.c_str());
- cell_exprs.push_back(stringf(" %s <= %s %s\n", y_id.c_str(), expr.c_str(), cellFileinfo.c_str()));
+ cell_exprs.push_back(stringf("%s%s <= %s %s\n", indent.c_str(), y_id.c_str(), expr.c_str(), cellFileinfo.c_str()));
register_reverse_wire_map(y_id, cell->getPort(ID::Y));
continue;
@@ -528,7 +649,7 @@ struct FirrtlWorker
string a_expr = make_expr(cell->getPort(ID::A));
string b_expr = make_expr(cell->getPort(ID::B));
std::string cellFileinfo = getFileinfo(cell);
- wire_decls.push_back(stringf(" wire %s: UInt<%d> %s\n", y_id.c_str(), y_width, cellFileinfo.c_str()));
+ wire_decls.push_back(stringf("%swire %s: UInt<%d> %s\n", indent.c_str(), y_id.c_str(), y_width, cellFileinfo.c_str()));
if (a_signed) {
a_expr = "asSInt(" + a_expr + ")";
@@ -746,7 +867,7 @@ struct FirrtlWorker
if ((firrtl_is_signed && !always_uint))
expr = stringf("asUInt(%s)", expr.c_str());
- cell_exprs.push_back(stringf(" %s <= %s %s\n", y_id.c_str(), expr.c_str(), cellFileinfo.c_str()));
+ cell_exprs.push_back(stringf("%s%s <= %s %s\n", indent.c_str(), y_id.c_str(), expr.c_str(), cellFileinfo.c_str()));
register_reverse_wire_map(y_id, cell->getPort(ID::Y));
continue;
@@ -759,136 +880,19 @@ struct FirrtlWorker
string a_expr = make_expr(cell->getPort(ID::A));
string b_expr = make_expr(cell->getPort(ID::B));
string s_expr = make_expr(cell->getPort(ID::S));
- wire_decls.push_back(stringf(" wire %s: UInt<%d> %s\n", y_id.c_str(), width, cellFileinfo.c_str()));
+ wire_decls.push_back(stringf("%swire %s: UInt<%d> %s\n", indent.c_str(), y_id.c_str(), width, cellFileinfo.c_str()));
string expr = stringf("mux(%s, %s, %s)", s_expr.c_str(), b_expr.c_str(), a_expr.c_str());
- cell_exprs.push_back(stringf(" %s <= %s %s\n", y_id.c_str(), expr.c_str(), cellFileinfo.c_str()));
+ cell_exprs.push_back(stringf("%s%s <= %s %s\n", indent.c_str(), y_id.c_str(), expr.c_str(), cellFileinfo.c_str()));
register_reverse_wire_map(y_id, cell->getPort(ID::Y));
continue;
}
- if (cell->type.in(ID($mem)))
+ if (cell->is_mem_cell())
{
- 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)))
- {
- 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;
}
@@ -902,20 +906,14 @@ struct FirrtlWorker
string expr = make_expr(cell->getPort(ID::D));
string clk_expr = "asClock(" + make_expr(cell->getPort(ID::CLK)) + ")";
- wire_decls.push_back(stringf(" reg %s: UInt<%d>, %s %s\n", y_id.c_str(), width, clk_expr.c_str(), cellFileinfo.c_str()));
+ wire_decls.push_back(stringf("%sreg %s: UInt<%d>, %s %s\n", indent.c_str(), y_id.c_str(), width, clk_expr.c_str(), cellFileinfo.c_str()));
- cell_exprs.push_back(stringf(" %s <= %s %s\n", y_id.c_str(), expr.c_str(), cellFileinfo.c_str()));
+ cell_exprs.push_back(stringf("%s%s <= %s %s\n", indent.c_str(), y_id.c_str(), expr.c_str(), cellFileinfo.c_str()));
register_reverse_wire_map(y_id, cell->getPort(ID::Q));
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.
@@ -923,7 +921,7 @@ struct FirrtlWorker
string a_expr = make_expr(cell->getPort(ID::A));
// Get the initial bit selector
string b_expr = make_expr(cell->getPort(ID::B));
- wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width));
+ wire_decls.push_back(stringf("%swire %s: UInt<%d>\n", indent.c_str(), y_id.c_str(), y_width));
if (cell->getParam(ID::B_SIGNED).as_bool()) {
// Use validif to constrain the selection (test the sign bit)
@@ -933,7 +931,7 @@ struct FirrtlWorker
}
string expr = stringf("dshr(%s, %s)", a_expr.c_str(), b_expr.c_str());
- cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str()));
+ cell_exprs.push_back(stringf("%s%s <= %s\n", indent.c_str(), y_id.c_str(), expr.c_str()));
register_reverse_wire_map(y_id, cell->getPort(ID::Y));
continue;
}
@@ -945,7 +943,7 @@ struct FirrtlWorker
string b_expr = make_expr(cell->getPort(ID::B));
auto b_string = b_expr.c_str();
string expr;
- wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width));
+ wire_decls.push_back(stringf("%swire %s: UInt<%d>\n", indent.c_str(), y_id.c_str(), y_width));
if (cell->getParam(ID::B_SIGNED).as_bool()) {
// We generate a left or right shift based on the sign of b.
@@ -959,7 +957,7 @@ struct FirrtlWorker
} else {
expr = stringf("dshr(%s, %s)", a_expr.c_str(), b_string);
}
- cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str()));
+ cell_exprs.push_back(stringf("%s%s <= %s\n", indent.c_str(), y_id.c_str(), expr.c_str()));
register_reverse_wire_map(y_id, cell->getPort(ID::Y));
continue;
}
@@ -972,22 +970,98 @@ struct FirrtlWorker
if (a_width < y_width) {
a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width);
}
- wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width));
- cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), a_expr.c_str()));
+ wire_decls.push_back(stringf("%swire %s: UInt<%d>\n", indent.c_str(), y_id.c_str(), y_width));
+ cell_exprs.push_back(stringf("%s%s <= %s\n", indent.c_str(), y_id.c_str(), a_expr.c_str()));
register_reverse_wire_map(y_id, cell->getPort(ID::Y));
continue;
}
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();
int y_width = GetSize(conn.first);
string expr = make_expr(conn.second);
- wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width));
- cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str()));
+ wire_decls.push_back(stringf("%swire %s: UInt<%d>\n", indent.c_str(), y_id.c_str(), y_width));
+ cell_exprs.push_back(stringf("%s%s <= %s\n", indent.c_str(), y_id.c_str(), expr.c_str()));
register_reverse_wire_map(y_id, conn.first);
}
@@ -1053,13 +1127,13 @@ struct FirrtlWorker
if (is_valid) {
if (make_unconn_id) {
- wire_decls.push_back(stringf(" wire %s: UInt<1> %s\n", unconn_id.c_str(), wireFileinfo.c_str()));
+ wire_decls.push_back(stringf("%swire %s: UInt<1> %s\n", indent.c_str(), unconn_id.c_str(), wireFileinfo.c_str()));
// `invalid` is a firrtl construction for simulation so we will not
// tag it with a @[fileinfo] tag as it doesn't directly correspond to
// a specific line of verilog code.
- wire_decls.push_back(stringf(" %s is invalid\n", unconn_id.c_str()));
+ wire_decls.push_back(stringf("%s%s is invalid\n", indent.c_str(), unconn_id.c_str()));
}
- wire_exprs.push_back(stringf(" %s <= %s %s\n", make_id(wire->name), expr.c_str(), wireFileinfo.c_str()));
+ wire_exprs.push_back(stringf("%s%s <= %s %s\n", indent.c_str(), make_id(wire->name), expr.c_str(), wireFileinfo.c_str()));
} else {
if (make_unconn_id) {
unconn_id.clear();
@@ -1067,7 +1141,7 @@ struct FirrtlWorker
// `invalid` is a firrtl construction for simulation so we will not
// tag it with a @[fileinfo] tag as it doesn't directly correspond to
// a specific line of verilog code.
- wire_decls.push_back(stringf(" %s is invalid\n", make_id(wire->name)));
+ wire_decls.push_back(stringf("%s%s is invalid\n", indent.c_str(), make_id(wire->name)));
}
}
@@ -1081,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)
@@ -1112,12 +1173,7 @@ struct FirrtlWorker
void run()
{
- // Blackboxes should be emitted as `extmodule`s in firrtl. Only ports are
- // emitted in such a case.
- if (module->get_blackbox_attribute())
- emit_extmodule();
- else
- emit_module();
+ emit_module();
}
};
@@ -1132,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
@@ -1154,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;
@@ -1180,10 +1240,16 @@ struct FirrtlBackend : public Backend {
std::string circuitFileinfo = getFileinfo(top);
*f << stringf("circuit %s: %s\n", make_id(top->name), circuitFileinfo.c_str());
+ emit_elaborated_extmodules(design, *f);
+
+ // Emit non-blackbox modules.
for (auto module : design->modules())
{
- FirrtlWorker worker(module, *f, design);
- worker.run();
+ if (!module->get_blackbox_attribute())
+ {
+ FirrtlWorker worker(module, *f, design);
+ worker.run();
+ }
}
namecache.clear();
diff --git a/backends/ilang/Makefile.inc b/backends/ilang/Makefile.inc
deleted file mode 100644
index 52fc2b891..000000000
--- a/backends/ilang/Makefile.inc
+++ /dev/null
@@ -1,3 +0,0 @@
-
-OBJS += backends/ilang/ilang_backend.o
-
diff --git a/backends/intersynth/intersynth.cc b/backends/intersynth/intersynth.cc
index 98a14173b..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
@@ -59,7 +59,7 @@ struct IntersynthBackend : public Backend {
log(" do not generate celltypes and conntypes commands. i.e. just output\n");
log(" the netlists. this is used for postsilicon synthesis.\n");
log("\n");
- log(" -lib <verilog_or_ilang_file>\n");
+ log(" -lib <verilog_or_rtlil_file>\n");
log(" Use the specified library file for determining whether cell ports are\n");
log(" inputs or outputs. This option can be used multiple times to specify\n");
log(" more than one library.\n");
@@ -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
@@ -108,7 +108,7 @@ struct IntersynthBackend : public Backend {
if (f.fail())
log_error("Can't open lib file `%s'.\n", filename.c_str());
RTLIL::Design *lib = new RTLIL::Design;
- Frontend::frontend_call(lib, &f, filename, (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".il") == 0 ? "ilang" : "verilog"));
+ Frontend::frontend_call(lib, &f, filename, (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".il") == 0 ? "rtlil" : "verilog"));
libs.push_back(lib);
}
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/Makefile.inc b/backends/rtlil/Makefile.inc
new file mode 100644
index 000000000..f691282ca
--- /dev/null
+++ b/backends/rtlil/Makefile.inc
@@ -0,0 +1,3 @@
+
+OBJS += backends/rtlil/rtlil_backend.o
+
diff --git a/backends/ilang/ilang_backend.cc b/backends/rtlil/rtlil_backend.cc
index aa5a175ca..1b11de5ec 100644
--- a/backends/ilang/ilang_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
@@ -18,19 +18,19 @@
* ---
*
* A very simple and straightforward backend for the RTLIL text
- * representation (as understood by the 'ilang' frontend).
+ * representation.
*
*/
-#include "ilang_backend.h"
+#include "rtlil_backend.h"
#include "kernel/yosys.h"
#include <errno.h>
USING_YOSYS_NAMESPACE
-using namespace ILANG_BACKEND;
+using namespace RTLIL_BACKEND;
YOSYS_NAMESPACE_BEGIN
-void ILANG_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int width, int offset, bool autoint)
+void RTLIL_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int width, int offset, bool autoint)
{
if (width < 0)
width = data.bits.size() - offset;
@@ -51,15 +51,19 @@ void ILANG_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 {
@@ -83,7 +87,7 @@ void ILANG_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int wi
}
}
-void ILANG_BACKEND::dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool autoint)
+void RTLIL_BACKEND::dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool autoint)
{
if (chunk.wire == NULL) {
dump_const(f, chunk.data, chunk.width, chunk.offset, autoint);
@@ -97,7 +101,7 @@ void ILANG_BACKEND::dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk,
}
}
-void ILANG_BACKEND::dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, bool autoint)
+void RTLIL_BACKEND::dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, bool autoint)
{
if (sig.is_chunk()) {
dump_sigchunk(f, sig.as_chunk(), autoint);
@@ -111,7 +115,7 @@ void ILANG_BACKEND::dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, boo
}
}
-void ILANG_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire)
+void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire)
{
for (auto &it : wire->attributes) {
f << stringf("%s" "attribute %s ", indent.c_str(), it.first.c_str());
@@ -136,7 +140,7 @@ void ILANG_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::
f << stringf("%s\n", wire->name.c_str());
}
-void ILANG_BACKEND::dump_memory(std::ostream &f, std::string indent, const RTLIL::Memory *memory)
+void RTLIL_BACKEND::dump_memory(std::ostream &f, std::string indent, const RTLIL::Memory *memory)
{
for (auto &it : memory->attributes) {
f << stringf("%s" "attribute %s ", indent.c_str(), it.first.c_str());
@@ -153,7 +157,7 @@ void ILANG_BACKEND::dump_memory(std::ostream &f, std::string indent, const RTLIL
f << stringf("%s\n", memory->name.c_str());
}
-void ILANG_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL::Cell *cell)
+void RTLIL_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL::Cell *cell)
{
for (auto &it : cell->attributes) {
f << stringf("%s" "attribute %s ", indent.c_str(), it.first.c_str());
@@ -177,7 +181,7 @@ void ILANG_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL::
f << stringf("%s" "end\n", indent.c_str());
}
-void ILANG_BACKEND::dump_proc_case_body(std::ostream &f, std::string indent, const RTLIL::CaseRule *cs)
+void RTLIL_BACKEND::dump_proc_case_body(std::ostream &f, std::string indent, const RTLIL::CaseRule *cs)
{
for (auto it = cs->actions.begin(); it != cs->actions.end(); ++it)
{
@@ -192,7 +196,7 @@ void ILANG_BACKEND::dump_proc_case_body(std::ostream &f, std::string indent, con
dump_proc_switch(f, indent, *it);
}
-void ILANG_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const RTLIL::SwitchRule *sw)
+void RTLIL_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const RTLIL::SwitchRule *sw)
{
for (auto it = sw->attributes.begin(); it != sw->attributes.end(); ++it) {
f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str());
@@ -225,7 +229,7 @@ void ILANG_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const
f << stringf("%s" "end\n", indent.c_str());
}
-void ILANG_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RTLIL::SyncRule *sy)
+void RTLIL_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RTLIL::SyncRule *sy)
{
f << stringf("%s" "sync ", indent.c_str());
switch (sy->type) {
@@ -242,16 +246,33 @@ void ILANG_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");
}
}
-void ILANG_BACKEND::dump_proc(std::ostream &f, std::string indent, const RTLIL::Process *proc)
+void RTLIL_BACKEND::dump_proc(std::ostream &f, std::string indent, const RTLIL::Process *proc)
{
for (auto it = proc->attributes.begin(); it != proc->attributes.end(); ++it) {
f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str());
@@ -265,7 +286,7 @@ void ILANG_BACKEND::dump_proc(std::ostream &f, std::string indent, const RTLIL::
f << stringf("%s" "end\n", indent.c_str());
}
-void ILANG_BACKEND::dump_conn(std::ostream &f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
+void RTLIL_BACKEND::dump_conn(std::ostream &f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
{
f << stringf("%s" "connect ", indent.c_str());
dump_sigspec(f, left);
@@ -274,7 +295,7 @@ void ILANG_BACKEND::dump_conn(std::ostream &f, std::string indent, const RTLIL::
f << stringf("\n");
}
-void ILANG_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Module *module, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n)
+void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Module *module, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n)
{
bool print_header = flag_m || design->selected_whole_module(module->name);
bool print_body = !flag_n || !design->selected_whole_module(module->name);
@@ -337,8 +358,8 @@ void ILANG_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()) {
@@ -360,7 +381,7 @@ void ILANG_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu
f << stringf("%s" "end\n", indent.c_str());
}
-void ILANG_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n)
+void RTLIL_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n)
{
int init_autoidx = autoidx;
@@ -396,15 +417,15 @@ void ILANG_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool onl
YOSYS_NAMESPACE_END
PRIVATE_NAMESPACE_BEGIN
-struct IlangBackend : public Backend {
- IlangBackend() : Backend("ilang", "write design to ilang file") { }
+struct RTLILBackend : public Backend {
+ RTLILBackend() : Backend("rtlil", "write design to RTLIL file") { }
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
- log(" write_ilang [filename]\n");
+ log(" write_rtlil [filename]\n");
log("\n");
- log("Write the current design to an 'ilang' file. (ilang is a text representation\n");
+ log("Write the current design to an RTLIL file. (RTLIL is a text representation\n");
log("of a design in yosys's internal format.)\n");
log("\n");
log(" -selected\n");
@@ -415,7 +436,7 @@ struct IlangBackend : public Backend {
{
bool selected = false;
- log_header(design, "Executing ILANG backend.\n");
+ log_header(design, "Executing RTLIL backend.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
@@ -432,12 +453,27 @@ struct IlangBackend : public Backend {
log("Output filename: %s\n", filename.c_str());
*f << stringf("# Generated by %s\n", yosys_version_str);
- ILANG_BACKEND::dump_design(*f, design, selected, true, false);
+ RTLIL_BACKEND::dump_design(*f, design, selected, true, false);
+ }
+} RTLILBackend;
+
+struct IlangBackend : public Backend {
+ IlangBackend() : Backend("ilang", "(deprecated) alias of write_rtlil") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log("See `help write_rtlil`.\n");
+ log("\n");
+ }
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ RTLILBackend.execute(f, filename, args, design);
}
} IlangBackend;
struct DumpPass : public Pass {
- DumpPass() : Pass("dump", "print parts of the design in ilang format") { }
+ DumpPass() : Pass("dump", "print parts of the design in RTLIL format") { }
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
@@ -445,7 +481,7 @@ struct DumpPass : public Pass {
log(" dump [options] [selection]\n");
log("\n");
log("Write the selected parts of the design to the console or specified file in\n");
- log("ilang format.\n");
+ log("RTLIL format.\n");
log("\n");
log(" -m\n");
log(" also dump the module headers, even if only parts of a single\n");
@@ -508,7 +544,7 @@ struct DumpPass : public Pass {
f = &buf;
}
- ILANG_BACKEND::dump_design(*f, design, true, flag_m, flag_n);
+ RTLIL_BACKEND::dump_design(*f, design, true, flag_m, flag_n);
if (!filename.empty()) {
delete f;
diff --git a/backends/ilang/ilang_backend.h b/backends/rtlil/rtlil_backend.h
index 97dcbb628..35829729c 100644
--- a/backends/ilang/ilang_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
@@ -18,19 +18,19 @@
* ---
*
* A very simple and straightforward backend for the RTLIL text
- * representation (as understood by the 'ilang' frontend).
+ * representation.
*
*/
-#ifndef ILANG_BACKEND_H
-#define ILANG_BACKEND_H
+#ifndef RTLIL_BACKEND_H
+#define RTLIL_BACKEND_H
#include "kernel/yosys.h"
#include <stdio.h>
YOSYS_NAMESPACE_BEGIN
-namespace ILANG_BACKEND {
+namespace RTLIL_BACKEND {
void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int offset = 0, bool autoint = true);
void dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool autoint = true);
void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, bool autoint = true);
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 526b36352..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
@@ -22,6 +22,7 @@
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/log.h"
+#include "kernel/mem.h"
#include <string>
USING_YOSYS_NAMESPACE
@@ -40,12 +41,15 @@ struct Smt2Worker
std::map<RTLIL::SigBit, RTLIL::Cell*> bit_driver;
std::set<RTLIL::Cell*> exported_cells, hiercells, hiercells_queue;
pool<Cell*> recursive_cells, registers;
+ std::vector<Mem> memories;
+ dict<Cell*, Mem*> mem_cells;
+ std::set<Mem*> memory_queue;
pool<SigBit> clock_posedge, clock_negedge;
vector<string> ex_state_eq, ex_input_eq;
std::map<RTLIL::SigBit, std::pair<int, int>> fcache;
- std::map<Cell*, int> memarrays;
+ std::map<Mem*, int> memarrays;
std::map<int, int> bvsizes;
dict<IdString, char*> ids;
@@ -116,12 +120,74 @@ struct Smt2Worker
makebits(stringf("%s_is", get_id(module)));
+ dict<IdString, Mem*> mem_dict;
+ memories = Mem::get_all_memories(module);
+ for (auto &mem : memories)
+ {
+ mem.narrow();
+ mem_dict[mem.memid] = &mem;
+ for (auto &port : mem.wr_ports)
+ {
+ if (port.clk_enable) {
+ SigSpec clk = sigmap(port.clk);
+ for (int i = 0; i < GetSize(clk); i++)
+ {
+ if (clk[i].wire == nullptr)
+ continue;
+ if (port.clk_polarity)
+ clock_posedge.insert(clk[i]);
+ else
+ clock_negedge.insert(clk[i]);
+ }
+ }
+ for (auto bit : sigmap(port.en))
+ noclock.insert(bit);
+ for (auto bit : sigmap(port.addr))
+ noclock.insert(bit);
+ for (auto bit : sigmap(port.data))
+ noclock.insert(bit);
+ }
+ for (auto &port : mem.rd_ports)
+ {
+ if (port.clk_enable) {
+ SigSpec clk = sigmap(port.clk);
+ for (int i = 0; i < GetSize(clk); i++)
+ {
+ if (clk[i].wire == nullptr)
+ continue;
+ if (port.clk_polarity)
+ clock_posedge.insert(clk[i]);
+ else
+ clock_negedge.insert(clk[i]);
+ }
+ }
+ for (auto bit : sigmap(port.en))
+ noclock.insert(bit);
+ for (auto bit : sigmap(port.addr))
+ noclock.insert(bit);
+ for (auto bit : sigmap(port.data))
+ noclock.insert(bit);
+ Cell *driver = port.cell ? port.cell : mem.cell;
+ for (auto bit : sigmap(port.data)) {
+ if (bit_driver.count(bit))
+ log_error("Found multiple drivers for %s.\n", log_signal(bit));
+ bit_driver[bit] = driver;
+ }
+ }
+ }
+
for (auto cell : module->cells())
for (auto &conn : cell->connections())
{
if (GetSize(conn.second) == 0)
continue;
+ // Handled above.
+ if (cell->is_mem_cell()) {
+ mem_cells[cell] = mem_dict[cell->parameters.at(ID::MEMID).decode_string()];
+ continue;
+ }
+
bool is_input = ct.cell_input(cell->type, conn.first);
bool is_output = ct.cell_output(cell->type, conn.first);
@@ -135,24 +201,6 @@ struct Smt2Worker
log_error("Unsupported or unknown directionality on port %s of cell %s.%s (%s).\n",
log_id(conn.first), log_id(module), log_id(cell), log_id(cell->type));
- if (cell->type.in(ID($mem)) && conn.first.in(ID::RD_CLK, ID::WR_CLK))
- {
- SigSpec clk = sigmap(conn.second);
- for (int i = 0; i < GetSize(clk); i++)
- {
- if (clk[i].wire == nullptr)
- continue;
-
- if (cell->getParam(conn.first == ID::RD_CLK ? ID::RD_CLK_ENABLE : ID::WR_CLK_ENABLE)[i] != State::S1)
- continue;
-
- if (cell->getParam(conn.first == ID::RD_CLK ? ID::RD_CLK_POLARITY : ID::WR_CLK_POLARITY)[i] == State::S1)
- clock_posedge.insert(clk[i]);
- else
- clock_negedge.insert(clk[i]);
- }
- }
- else
if (cell->type.in(ID($dff), ID($_DFF_P_), ID($_DFF_N_)) && conn.first.in(ID::CLK, ID::C))
{
bool posedge = (cell->type == ID($_DFF_N_)) || (cell->type == ID($dff) && cell->getParam(ID::CLK_POLARITY).as_bool());
@@ -647,27 +695,35 @@ struct Smt2Worker
// FIXME: $slice $concat
}
- if (memmode && cell->type == ID($mem))
+ if (memmode && cell->is_mem_cell())
{
+ Mem *mem = mem_cells[cell];
+
+ if (memarrays.count(mem)) {
+ recursive_cells.erase(cell);
+ return;
+ }
+
int arrayid = idcounter++;
- memarrays[cell] = arrayid;
-
- int abits = cell->getParam(ID::ABITS).as_int();
- int width = cell->getParam(ID::WIDTH).as_int();
- int rd_ports = cell->getParam(ID::RD_PORTS).as_int();
- int wr_ports = cell->getParam(ID::WR_PORTS).as_int();
-
- bool async_read = false;
- if (!cell->getParam(ID::WR_CLK_ENABLE).is_fully_ones()) {
- if (!cell->getParam(ID::WR_CLK_ENABLE).is_fully_zero())
- log_error("Memory %s.%s has mixed clocked/nonclocked write ports. This is not supported by \"write_smt2\".\n", log_id(cell), log_id(module));
- async_read = true;
+ memarrays[mem] = arrayid;
+
+ int abits = ceil_log2(mem->size);
+
+ bool has_sync_wr = false;
+ bool has_async_wr = false;
+ for (auto &port : mem->wr_ports) {
+ if (port.clk_enable)
+ has_sync_wr = true;
+ else
+ has_async_wr = true;
}
+ if (has_async_wr && has_sync_wr)
+ log_error("Memory %s.%s has mixed clocked/nonclocked write ports. This is not supported by \"write_smt2\".\n", log_id(cell), log_id(module));
- decls.push_back(stringf("; yosys-smt2-memory %s %d %d %d %d %s\n", get_id(cell), abits, width, rd_ports, wr_ports, async_read ? "async" : "sync"));
+ decls.push_back(stringf("; yosys-smt2-memory %s %d %d %d %d %s\n", get_id(mem->memid), abits, mem->width, GetSize(mem->rd_ports), GetSize(mem->wr_ports), has_async_wr ? "async" : "sync"));
string memstate;
- if (async_read) {
+ if (has_async_wr) {
memstate = stringf("%s#%d#final", get_id(module), arrayid);
} else {
memstate = stringf("%s#%d#0", get_id(module), arrayid);
@@ -675,80 +731,79 @@ struct Smt2Worker
if (statebv)
{
- int mem_size = cell->getParam(ID::SIZE).as_int();
- int mem_offset = cell->getParam(ID::OFFSET).as_int();
-
- makebits(memstate, width*mem_size, get_id(cell));
+ makebits(memstate, mem->width*mem->size, get_id(mem->memid));
decls.push_back(stringf("(define-fun |%s_m %s| ((state |%s_s|)) (_ BitVec %d) (|%s| state))\n",
- get_id(module), get_id(cell), get_id(module), width*mem_size, memstate.c_str()));
+ get_id(module), get_id(mem->memid), get_id(module), mem->width*mem->size, memstate.c_str()));
- for (int i = 0; i < rd_ports; i++)
+ for (int i = 0; i < GetSize(mem->rd_ports); i++)
{
- SigSpec addr_sig = cell->getPort(ID::RD_ADDR).extract(abits*i, abits);
- SigSpec data_sig = cell->getPort(ID::RD_DATA).extract(width*i, width);
+ auto &port = mem->rd_ports[i];
+ SigSpec addr_sig = port.addr;
+ addr_sig.extend_u0(abits);
std::string addr = get_bv(addr_sig);
- if (cell->getParam(ID::RD_CLK_ENABLE).extract(i).as_bool())
+ if (port.clk_enable)
log_error("Read port %d (%s) of memory %s.%s is clocked. This is not supported by \"write_smt2\"! "
- "Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(data_sig), log_id(cell), log_id(module));
+ "Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(port.data), log_id(mem->memid), log_id(module));
decls.push_back(stringf("(define-fun |%s_m:R%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
- get_id(module), i, get_id(cell), get_id(module), abits, addr.c_str(), log_signal(addr_sig)));
+ get_id(module), i, get_id(mem->memid), get_id(module), abits, addr.c_str(), log_signal(addr_sig)));
std::string read_expr = "#b";
- for (int k = 0; k < width; k++)
+ for (int k = 0; k < mem->width; k++)
read_expr += "0";
- for (int k = 0; k < mem_size; k++)
+ for (int k = 0; k < mem->size; k++)
read_expr = stringf("(ite (= (|%s_m:R%dA %s| state) #b%s) ((_ extract %d %d) (|%s| state))\n %s)",
- get_id(module), i, get_id(cell), Const(k+mem_offset, abits).as_string().c_str(),
- width*(k+1)-1, width*k, memstate.c_str(), read_expr.c_str());
+ get_id(module), i, get_id(mem->memid), Const(k+mem->start_offset, abits).as_string().c_str(),
+ mem->width*(k+1)-1, mem->width*k, memstate.c_str(), read_expr.c_str());
decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) (_ BitVec %d)\n %s) ; %s\n",
- get_id(module), idcounter, get_id(module), width, read_expr.c_str(), log_signal(data_sig)));
+ get_id(module), idcounter, get_id(module), mem->width, read_expr.c_str(), log_signal(port.data)));
decls.push_back(stringf("(define-fun |%s_m:R%dD %s| ((state |%s_s|)) (_ BitVec %d) (|%s#%d| state))\n",
- get_id(module), i, get_id(cell), get_id(module), width, get_id(module), idcounter));
+ get_id(module), i, get_id(mem->memid), get_id(module), mem->width, get_id(module), idcounter));
- register_bv(data_sig, idcounter++);
+ register_bv(port.data, idcounter++);
}
}
else
{
if (statedt)
dtmembers.push_back(stringf(" (|%s| (Array (_ BitVec %d) (_ BitVec %d))) ; %s\n",
- memstate.c_str(), abits, width, get_id(cell)));
+ memstate.c_str(), abits, mem->width, get_id(mem->memid)));
else
decls.push_back(stringf("(declare-fun |%s| (|%s_s|) (Array (_ BitVec %d) (_ BitVec %d))) ; %s\n",
- memstate.c_str(), get_id(module), abits, width, get_id(cell)));
+ memstate.c_str(), get_id(module), abits, mem->width, get_id(mem->memid)));
decls.push_back(stringf("(define-fun |%s_m %s| ((state |%s_s|)) (Array (_ BitVec %d) (_ BitVec %d)) (|%s| state))\n",
- get_id(module), get_id(cell), get_id(module), abits, width, memstate.c_str()));
+ get_id(module), get_id(mem->memid), get_id(module), abits, mem->width, memstate.c_str()));
- for (int i = 0; i < rd_ports; i++)
+ for (int i = 0; i < GetSize(mem->rd_ports); i++)
{
- SigSpec addr_sig = cell->getPort(ID::RD_ADDR).extract(abits*i, abits);
- SigSpec data_sig = cell->getPort(ID::RD_DATA).extract(width*i, width);
+ auto &port = mem->rd_ports[i];
+ SigSpec addr_sig = port.addr;
+ addr_sig.extend_u0(abits);
std::string addr = get_bv(addr_sig);
- if (cell->getParam(ID::RD_CLK_ENABLE).extract(i).as_bool())
+ if (port.clk_enable)
log_error("Read port %d (%s) of memory %s.%s is clocked. This is not supported by \"write_smt2\"! "
- "Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(data_sig), log_id(cell), log_id(module));
+ "Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(port.data), log_id(mem->memid), log_id(module));
decls.push_back(stringf("(define-fun |%s_m:R%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
- get_id(module), i, get_id(cell), get_id(module), abits, addr.c_str(), log_signal(addr_sig)));
+ get_id(module), i, get_id(mem->memid), get_id(module), abits, addr.c_str(), log_signal(addr_sig)));
decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) (_ BitVec %d) (select (|%s| state) (|%s_m:R%dA %s| state))) ; %s\n",
- get_id(module), idcounter, get_id(module), width, memstate.c_str(), get_id(module), i, get_id(cell), log_signal(data_sig)));
+ get_id(module), idcounter, get_id(module), mem->width, memstate.c_str(), get_id(module), i, get_id(mem->memid), log_signal(port.data)));
decls.push_back(stringf("(define-fun |%s_m:R%dD %s| ((state |%s_s|)) (_ BitVec %d) (|%s#%d| state))\n",
- get_id(module), i, get_id(cell), get_id(module), width, get_id(module), idcounter));
+ get_id(module), i, get_id(mem->memid), get_id(module), mem->width, get_id(module), idcounter));
- register_bv(data_sig, idcounter++);
+ register_bv(port.data, idcounter++);
}
}
- registers.insert(cell);
+ memory_queue.insert(mem);
recursive_cells.erase(cell);
return;
}
@@ -801,6 +856,18 @@ struct Smt2Worker
return;
}
+ if (cell->type.in(ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)) || cell->type.str().substr(0, 6) == "$_SDFF" || (cell->type.str().substr(0, 6) == "$_DFFE" && cell->type.str().size() == 10)) {
+ 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($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));
+ }
+ if (cell->type.in(ID($sr), ID($dlatch), ID($adlatch), ID($dlatchsr)) || cell->type.str().substr(0, 8) == "$_DLATCH" || cell->type.str().substr(0, 5) == "$_SR_") {
+ log_error("Unsupported cell type %s for cell %s.%s -- please run `clk2fflogic` before `write_smt2`.\n",
+ log_id(cell->type), log_id(module), log_id(cell));
+ }
log_error("Unsupported cell type %s for cell %s.%s.\n",
log_id(cell->type), log_id(module), log_id(cell));
}
@@ -822,40 +889,51 @@ struct Smt2Worker
for (auto bit : SigSpec(wire))
if (reg_bits.count(bit))
is_register = true;
- if (wire->port_id || is_register || wire->get_bool_attribute(ID::keep) || (wiresmode && wire->name[0] == '\\')) {
+ if (wire->port_id || is_register || wire->get_bool_attribute(ID::keep) || (wiresmode && wire->name.isPublic())) {
RTLIL::SigSpec sig = sigmap(wire);
+ std::vector<std::string> comments;
if (wire->port_input)
- decls.push_back(stringf("; yosys-smt2-input %s %d\n", get_id(wire), wire->width));
+ comments.push_back(stringf("; yosys-smt2-input %s %d\n", get_id(wire), wire->width));
if (wire->port_output)
- decls.push_back(stringf("; yosys-smt2-output %s %d\n", get_id(wire), wire->width));
+ comments.push_back(stringf("; yosys-smt2-output %s %d\n", get_id(wire), wire->width));
if (is_register)
- decls.push_back(stringf("; yosys-smt2-register %s %d\n", get_id(wire), wire->width));
- if (wire->get_bool_attribute(ID::keep) || (wiresmode && wire->name[0] == '\\'))
- decls.push_back(stringf("; yosys-smt2-wire %s %d\n", get_id(wire), wire->width));
+ comments.push_back(stringf("; yosys-smt2-register %s %d\n", get_id(wire), wire->width));
+ if (wire->get_bool_attribute(ID::keep) || (wiresmode && wire->name.isPublic()))
+ comments.push_back(stringf("; yosys-smt2-wire %s %d\n", get_id(wire), wire->width));
if (GetSize(wire) == 1 && (clock_posedge.count(sig) || clock_negedge.count(sig)))
- decls.push_back(stringf("; yosys-smt2-clock %s%s%s\n", get_id(wire),
+ comments.push_back(stringf("; yosys-smt2-clock %s%s%s\n", get_id(wire),
clock_posedge.count(sig) ? " posedge" : "", clock_negedge.count(sig) ? " negedge" : ""));
if (bvmode && GetSize(sig) > 1) {
+ std::string sig_bv = get_bv(sig);
+ if (!comments.empty())
+ decls.insert(decls.end(), comments.begin(), comments.end());
decls.push_back(stringf("(define-fun |%s_n %s| ((state |%s_s|)) (_ BitVec %d) %s)\n",
- get_id(module), get_id(wire), get_id(module), GetSize(sig), get_bv(sig).c_str()));
+ get_id(module), get_id(wire), get_id(module), GetSize(sig), sig_bv.c_str()));
if (wire->port_input)
ex_input_eq.push_back(stringf(" (= (|%s_n %s| state) (|%s_n %s| other_state))",
get_id(module), get_id(wire), get_id(module), get_id(wire)));
} else {
- for (int i = 0; i < GetSize(sig); i++)
+ std::vector<std::string> sig_bool;
+ for (int i = 0; i < GetSize(sig); i++) {
+ sig_bool.push_back(get_bool(sig[i]));
+ }
+ if (!comments.empty())
+ decls.insert(decls.end(), comments.begin(), comments.end());
+ for (int i = 0; i < GetSize(sig); i++) {
if (GetSize(sig) > 1) {
decls.push_back(stringf("(define-fun |%s_n %s %d| ((state |%s_s|)) Bool %s)\n",
- get_id(module), get_id(wire), i, get_id(module), get_bool(sig[i]).c_str()));
+ get_id(module), get_id(wire), i, get_id(module), sig_bool[i].c_str()));
if (wire->port_input)
ex_input_eq.push_back(stringf(" (= (|%s_n %s %d| state) (|%s_n %s %d| other_state))",
get_id(module), get_id(wire), i, get_id(module), get_id(wire), i));
} else {
decls.push_back(stringf("(define-fun |%s_n %s| ((state |%s_s|)) Bool %s)\n",
- get_id(module), get_id(wire), get_id(module), get_bool(sig[i]).c_str()));
+ get_id(module), get_id(wire), get_id(module), sig_bool[i].c_str()));
if (wire->port_input)
ex_input_eq.push_back(stringf(" (= (|%s_n %s| state) (|%s_n %s| other_state))",
get_id(module), get_id(wire), get_id(module), get_id(wire)));
}
+ }
}
}
}
@@ -966,7 +1044,7 @@ struct Smt2Worker
}
}
- for (int iter = 1; !registers.empty(); iter++)
+ for (int iter = 1; !registers.empty() || !memory_queue.empty(); iter++)
{
pool<Cell*> this_regs;
this_regs.swap(registers);
@@ -999,152 +1077,156 @@ struct Smt2Worker
if (cell->type == ID($anyconst))
ex_state_eq.push_back(stringf("(= %s %s)", get_bv(cell->getPort(ID::Y)).c_str(), get_bv(cell->getPort(ID::Y), "other_state").c_str()));
}
+ }
- if (cell->type == ID($mem))
- {
- int arrayid = memarrays.at(cell);
+ std::set<Mem*> this_mems;
+ this_mems.swap(memory_queue);
+
+ for (auto mem : this_mems)
+ {
+ int arrayid = memarrays.at(mem);
- int abits = cell->getParam(ID::ABITS).as_int();
- int width = cell->getParam(ID::WIDTH).as_int();
- int wr_ports = cell->getParam(ID::WR_PORTS).as_int();
+ int abits = ceil_log2(mem->size);;
- bool async_read = false;
- string initial_memstate, final_memstate;
+ bool has_sync_wr = false;
+ bool has_async_wr = false;
+ for (auto &port : mem->wr_ports) {
+ if (port.clk_enable)
+ has_sync_wr = true;
+ else
+ has_async_wr = true;
+ }
- if (!cell->getParam(ID::WR_CLK_ENABLE).is_fully_ones()) {
- log_assert(cell->getParam(ID::WR_CLK_ENABLE).is_fully_zero());
- async_read = true;
- initial_memstate = stringf("%s#%d#0", get_id(module), arrayid);
- final_memstate = stringf("%s#%d#final", get_id(module), arrayid);
+ string initial_memstate, final_memstate;
+
+ if (has_async_wr) {
+ log_assert(!has_sync_wr);
+ initial_memstate = stringf("%s#%d#0", get_id(module), arrayid);
+ final_memstate = stringf("%s#%d#final", get_id(module), arrayid);
+ }
+
+ if (statebv)
+ {
+ if (has_async_wr) {
+ makebits(final_memstate, mem->width*mem->size, get_id(mem->memid));
}
- if (statebv)
+ for (int i = 0; i < GetSize(mem->wr_ports); i++)
{
- int mem_size = cell->getParam(ID::SIZE).as_int();
- int mem_offset = cell->getParam(ID::OFFSET).as_int();
-
- if (async_read) {
- makebits(final_memstate, width*mem_size, get_id(cell));
+ auto &port = mem->wr_ports[i];
+ SigSpec addr_sig = port.addr;
+ addr_sig.extend_u0(abits);
+
+ std::string addr = get_bv(addr_sig);
+ std::string data = get_bv(port.data);
+ std::string mask = get_bv(port.en);
+
+ decls.push_back(stringf("(define-fun |%s_m:W%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
+ get_id(module), i, get_id(mem->memid), get_id(module), abits, addr.c_str(), log_signal(addr_sig)));
+ addr = stringf("(|%s_m:W%dA %s| state)", get_id(module), i, get_id(mem->memid));
+
+ decls.push_back(stringf("(define-fun |%s_m:W%dD %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
+ get_id(module), i, get_id(mem->memid), get_id(module), mem->width, data.c_str(), log_signal(port.data)));
+ data = stringf("(|%s_m:W%dD %s| state)", get_id(module), i, get_id(mem->memid));
+
+ decls.push_back(stringf("(define-fun |%s_m:W%dM %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
+ get_id(module), i, get_id(mem->memid), get_id(module), mem->width, mask.c_str(), log_signal(port.en)));
+ mask = stringf("(|%s_m:W%dM %s| state)", get_id(module), i, get_id(mem->memid));
+
+ std::string data_expr;
+
+ for (int k = mem->size-1; k >= 0; k--) {
+ std::string new_data = stringf("(bvor (bvand %s %s) (bvand ((_ extract %d %d) (|%s#%d#%d| state)) (bvnot %s)))",
+ data.c_str(), mask.c_str(), mem->width*(k+1)-1, mem->width*k, get_id(module), arrayid, i, mask.c_str());
+ data_expr += stringf("\n (ite (= %s #b%s) %s ((_ extract %d %d) (|%s#%d#%d| state)))",
+ addr.c_str(), Const(k+mem->start_offset, abits).as_string().c_str(), new_data.c_str(),
+ mem->width*(k+1)-1, mem->width*k, get_id(module), arrayid, i);
}
- for (int i = 0; i < wr_ports; i++)
- {
- SigSpec addr_sig = cell->getPort(ID::WR_ADDR).extract(abits*i, abits);
- SigSpec data_sig = cell->getPort(ID::WR_DATA).extract(width*i, width);
- SigSpec mask_sig = cell->getPort(ID::WR_EN).extract(width*i, width);
+ decls.push_back(stringf("(define-fun |%s#%d#%d| ((state |%s_s|)) (_ BitVec %d) (concat%s)) ; %s\n",
+ get_id(module), arrayid, i+1, get_id(module), mem->width*mem->size, data_expr.c_str(), get_id(mem->memid)));
+ }
+ }
+ else
+ {
+ if (has_async_wr) {
+ if (statedt)
+ dtmembers.push_back(stringf(" (|%s| (Array (_ BitVec %d) (_ BitVec %d))) ; %s\n",
+ initial_memstate.c_str(), abits, mem->width, get_id(mem->memid)));
+ else
+ decls.push_back(stringf("(declare-fun |%s| (|%s_s|) (Array (_ BitVec %d) (_ BitVec %d))) ; %s\n",
+ initial_memstate.c_str(), get_id(module), abits, mem->width, get_id(mem->memid)));
+ }
- std::string addr = get_bv(addr_sig);
- std::string data = get_bv(data_sig);
- std::string mask = get_bv(mask_sig);
+ for (int i = 0; i < GetSize(mem->wr_ports); i++)
+ {
+ auto &port = mem->wr_ports[i];
+ SigSpec addr_sig = port.addr;
+ addr_sig.extend_u0(abits);
- decls.push_back(stringf("(define-fun |%s_m:W%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
- get_id(module), i, get_id(cell), get_id(module), abits, addr.c_str(), log_signal(addr_sig)));
- addr = stringf("(|%s_m:W%dA %s| state)", get_id(module), i, get_id(cell));
+ std::string addr = get_bv(addr_sig);
+ std::string data = get_bv(port.data);
+ std::string mask = get_bv(port.en);
- decls.push_back(stringf("(define-fun |%s_m:W%dD %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
- get_id(module), i, get_id(cell), get_id(module), width, data.c_str(), log_signal(data_sig)));
- data = stringf("(|%s_m:W%dD %s| state)", get_id(module), i, get_id(cell));
+ decls.push_back(stringf("(define-fun |%s_m:W%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
+ get_id(module), i, get_id(mem->memid), get_id(module), abits, addr.c_str(), log_signal(addr_sig)));
+ addr = stringf("(|%s_m:W%dA %s| state)", get_id(module), i, get_id(mem->memid));
- decls.push_back(stringf("(define-fun |%s_m:W%dM %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
- get_id(module), i, get_id(cell), get_id(module), width, mask.c_str(), log_signal(mask_sig)));
- mask = stringf("(|%s_m:W%dM %s| state)", get_id(module), i, get_id(cell));
+ decls.push_back(stringf("(define-fun |%s_m:W%dD %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
+ get_id(module), i, get_id(mem->memid), get_id(module), mem->width, data.c_str(), log_signal(port.data)));
+ data = stringf("(|%s_m:W%dD %s| state)", get_id(module), i, get_id(mem->memid));
- std::string data_expr;
+ decls.push_back(stringf("(define-fun |%s_m:W%dM %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
+ get_id(module), i, get_id(mem->memid), get_id(module), mem->width, mask.c_str(), log_signal(port.en)));
+ mask = stringf("(|%s_m:W%dM %s| state)", get_id(module), i, get_id(mem->memid));
- for (int k = mem_size-1; k >= 0; k--) {
- std::string new_data = stringf("(bvor (bvand %s %s) (bvand ((_ extract %d %d) (|%s#%d#%d| state)) (bvnot %s)))",
- data.c_str(), mask.c_str(), width*(k+1)-1, width*k, get_id(module), arrayid, i, mask.c_str());
- data_expr += stringf("\n (ite (= %s #b%s) %s ((_ extract %d %d) (|%s#%d#%d| state)))",
- addr.c_str(), Const(k+mem_offset, abits).as_string().c_str(), new_data.c_str(),
- width*(k+1)-1, width*k, get_id(module), arrayid, i);
- }
+ data = stringf("(bvor (bvand %s %s) (bvand (select (|%s#%d#%d| state) %s) (bvnot %s)))",
+ data.c_str(), mask.c_str(), get_id(module), arrayid, i, addr.c_str(), mask.c_str());
- decls.push_back(stringf("(define-fun |%s#%d#%d| ((state |%s_s|)) (_ BitVec %d) (concat%s)) ; %s\n",
- get_id(module), arrayid, i+1, get_id(module), width*mem_size, data_expr.c_str(), get_id(cell)));
- }
+ decls.push_back(stringf("(define-fun |%s#%d#%d| ((state |%s_s|)) (Array (_ BitVec %d) (_ BitVec %d)) "
+ "(store (|%s#%d#%d| state) %s %s)) ; %s\n",
+ get_id(module), arrayid, i+1, get_id(module), abits, mem->width,
+ get_id(module), arrayid, i, addr.c_str(), data.c_str(), get_id(mem->memid)));
}
- else
- {
- if (async_read) {
- if (statedt)
- dtmembers.push_back(stringf(" (|%s| (Array (_ BitVec %d) (_ BitVec %d))) ; %s\n",
- initial_memstate.c_str(), abits, width, get_id(cell)));
- else
- decls.push_back(stringf("(declare-fun |%s| (|%s_s|) (Array (_ BitVec %d) (_ BitVec %d))) ; %s\n",
- initial_memstate.c_str(), get_id(module), abits, width, get_id(cell)));
- }
-
- for (int i = 0; i < wr_ports; i++)
- {
- SigSpec addr_sig = cell->getPort(ID::WR_ADDR).extract(abits*i, abits);
- SigSpec data_sig = cell->getPort(ID::WR_DATA).extract(width*i, width);
- SigSpec mask_sig = cell->getPort(ID::WR_EN).extract(width*i, width);
+ }
- std::string addr = get_bv(addr_sig);
- std::string data = get_bv(data_sig);
- std::string mask = get_bv(mask_sig);
+ std::string expr_d = stringf("(|%s#%d#%d| state)", get_id(module), arrayid, GetSize(mem->wr_ports));
+ std::string expr_q = stringf("(|%s#%d#0| next_state)", get_id(module), arrayid);
+ trans.push_back(stringf(" (= %s %s) ; %s\n", expr_d.c_str(), expr_q.c_str(), get_id(mem->memid)));
+ ex_state_eq.push_back(stringf("(= (|%s#%d#0| state) (|%s#%d#0| other_state))", get_id(module), arrayid, get_id(module), arrayid));
- decls.push_back(stringf("(define-fun |%s_m:W%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
- get_id(module), i, get_id(cell), get_id(module), abits, addr.c_str(), log_signal(addr_sig)));
- addr = stringf("(|%s_m:W%dA %s| state)", get_id(module), i, get_id(cell));
+ if (has_async_wr)
+ hier.push_back(stringf(" (= %s (|%s| state)) ; %s\n", expr_d.c_str(), final_memstate.c_str(), get_id(mem->memid)));
- decls.push_back(stringf("(define-fun |%s_m:W%dD %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
- get_id(module), i, get_id(cell), get_id(module), width, data.c_str(), log_signal(data_sig)));
- data = stringf("(|%s_m:W%dD %s| state)", get_id(module), i, get_id(cell));
+ Const init_data = mem->get_init_data();
- decls.push_back(stringf("(define-fun |%s_m:W%dM %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
- get_id(module), i, get_id(cell), get_id(module), width, mask.c_str(), log_signal(mask_sig)));
- mask = stringf("(|%s_m:W%dM %s| state)", get_id(module), i, get_id(cell));
+ for (int i = 0; i < mem->size; i++)
+ {
+ if (i*mem->width >= GetSize(init_data))
+ break;
- data = stringf("(bvor (bvand %s %s) (bvand (select (|%s#%d#%d| state) %s) (bvnot %s)))",
- data.c_str(), mask.c_str(), get_id(module), arrayid, i, addr.c_str(), mask.c_str());
+ Const initword = init_data.extract(i*mem->width, mem->width, State::Sx);
+ Const initmask = initword;
+ bool gen_init_constr = false;
- decls.push_back(stringf("(define-fun |%s#%d#%d| ((state |%s_s|)) (Array (_ BitVec %d) (_ BitVec %d)) "
- "(store (|%s#%d#%d| state) %s %s)) ; %s\n",
- get_id(module), arrayid, i+1, get_id(module), abits, width,
- get_id(module), arrayid, i, addr.c_str(), data.c_str(), get_id(cell)));
+ for (int k = 0; k < GetSize(initword); k++) {
+ if (initword[k] == State::S0 || initword[k] == State::S1) {
+ gen_init_constr = true;
+ initmask[k] = State::S1;
+ } else {
+ initmask[k] = State::S0;
+ initword[k] = State::S0;
}
}
- std::string expr_d = stringf("(|%s#%d#%d| state)", get_id(module), arrayid, wr_ports);
- std::string expr_q = stringf("(|%s#%d#0| next_state)", get_id(module), arrayid);
- trans.push_back(stringf(" (= %s %s) ; %s\n", expr_d.c_str(), expr_q.c_str(), get_id(cell)));
- ex_state_eq.push_back(stringf("(= (|%s#%d#0| state) (|%s#%d#0| other_state))", get_id(module), arrayid, get_id(module), arrayid));
-
- if (async_read)
- hier.push_back(stringf(" (= %s (|%s| state)) ; %s\n", expr_d.c_str(), final_memstate.c_str(), get_id(cell)));
-
- Const init_data = cell->getParam(ID::INIT);
- int memsize = cell->getParam(ID::SIZE).as_int();
-
- for (int i = 0; i < memsize; i++)
+ if (gen_init_constr)
{
- if (i*width >= GetSize(init_data))
- break;
-
- Const initword = init_data.extract(i*width, width, State::Sx);
- Const initmask = initword;
- bool gen_init_constr = false;
-
- for (int k = 0; k < GetSize(initword); k++) {
- if (initword[k] == State::S0 || initword[k] == State::S1) {
- gen_init_constr = true;
- initmask[k] = State::S1;
- } else {
- initmask[k] = State::S0;
- initword[k] = State::S0;
- }
- }
-
- if (gen_init_constr)
- {
- if (statebv)
- /* FIXME */;
- else
- init_list.push_back(stringf("(= (bvand (select (|%s#%d#0| state) #b%s) #b%s) #b%s) ; %s[%d]",
- get_id(module), arrayid, Const(i, abits).as_string().c_str(),
- initmask.as_string().c_str(), initword.as_string().c_str(), get_id(cell), i));
- }
+ if (statebv)
+ /* FIXME */;
+ else
+ init_list.push_back(stringf("(= (bvand (select (|%s#%d#0| state) #b%s) #b%s) #b%s) ; %s[%d]",
+ get_id(module), arrayid, Const(i, abits).as_string().c_str(),
+ initmask.as_string().c_str(), initword.as_string().c_str(), get_id(mem->memid), i));
}
}
}
@@ -1387,8 +1469,12 @@ struct Smt2Backend : public Backend {
log(" use the given template file. the line containing only the token '%%%%'\n");
log(" is replaced with the regular output of this command.\n");
log("\n");
+ log(" -solver-option <option> <value>\n");
+ log(" emit a `; yosys-smt2-solver-option` directive for yosys-smtbmc to write\n");
+ log(" the given option as a `(set-option ...)` command in the SMT-LIBv2.\n");
+ log("\n");
log("[1] For more information on SMT-LIBv2 visit http://smt-lib.org/ or read David\n");
- log("R. Cok's tutorial: http://www.grammatech.com/resources/smt/SMTLIBTutorial.pdf\n");
+ log("R. Cok's tutorial: https://smtlib.github.io/jSMTLIB/SMTLIBTutorial.pdf\n");
log("\n");
log("---------------------------------------------------------------------------\n");
log("\n");
@@ -1441,9 +1527,15 @@ struct Smt2Backend : public Backend {
std::ifstream template_f;
bool bvmode = true, memmode = true, wiresmode = false, verbose = false, statebv = false, statedt = false;
bool forallmode = false;
+ dict<std::string, std::string> solver_options;
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++)
{
@@ -1484,6 +1576,11 @@ struct Smt2Backend : public Backend {
verbose = true;
continue;
}
+ if (args[argidx] == "-solver-option" && argidx+2 < args.size()) {
+ solver_options.emplace(args[argidx+1], args[argidx+2]);
+ argidx += 2;
+ continue;
+ }
break;
}
extra_args(f, filename, args, argidx);
@@ -1514,6 +1611,9 @@ struct Smt2Backend : public Backend {
if (statedt)
*f << stringf("; yosys-smt2-stdt\n");
+ for (auto &it : solver_options)
+ *f << stringf("; yosys-smt2-solver-option %s %s\n", it.first.c_str(), it.second.c_str());
+
std::vector<RTLIL::Module*> sorted_modules;
// extract module dependencies
@@ -1562,7 +1662,7 @@ struct Smt2Backend : public Backend {
for (auto module : sorted_modules)
{
- if (module->get_blackbox_attribute() || module->has_memories_warn() || module->has_processes_warn())
+ if (module->get_blackbox_attribute() || module->has_processes_warn())
continue;
log("Creating SMT-LIBv2 representation of module %s.\n", log_id(module));
diff --git a/backends/smt2/smtbmc.py b/backends/smt2/smtbmc.py
index 03f001bfd..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[:])
@@ -817,6 +817,24 @@ def write_vcd_trace(steps_start, steps_stop, index):
vcd.set_time(steps_stop)
+def char_ok_in_verilog(c,i):
+ if ('A' <= c <= 'Z'): return True
+ if ('a' <= c <= 'z'): return True
+ if ('0' <= c <= '9' and i>0): return True
+ if (c == '_'): return True
+ if (c == '$'): return True
+ return False
+
+def escape_identifier(identifier):
+ if type(identifier) is list:
+ return map(escape_identifier, identifier)
+ if "." in identifier:
+ return ".".join(escape_identifier(identifier.split(".")))
+ if (all(char_ok_in_verilog(identifier[i],i) for i in range(0, len(identifier)))):
+ return identifier
+ return "\\"+identifier+" "
+
+
def write_vlogtb_trace(steps_start, steps_stop, index):
filename = vlogtbfile.replace("%", index)
@@ -858,12 +876,12 @@ def write_vlogtb_trace(steps_start, steps_stop, index):
for name, width in primary_inputs:
if name in clock_inputs:
- print(" wire [%d:0] PI_%s = clock;" % (width-1, name), file=f)
+ print(" wire [%d:0] %s = clock;" % (width-1, escape_identifier("PI_"+name)), file=f)
else:
- print(" reg [%d:0] PI_%s;" % (width-1, name), file=f)
+ print(" reg [%d:0] %s;" % (width-1, escape_identifier("PI_"+name)), file=f)
- print(" %s UUT (" % vlogtb_topmod, file=f)
- print(",\n".join(" .{name}(PI_{name})".format(name=name) for name, _ in primary_inputs), file=f)
+ print(" %s UUT (" % escape_identifier(vlogtb_topmod), file=f)
+ print(",\n".join(" .%s(%s)" % (escape_identifier(name), escape_identifier("PI_"+name)) for name, _ in primary_inputs), file=f)
print(" );", file=f)
print("`ifndef VERILATOR", file=f)
@@ -893,14 +911,14 @@ def write_vlogtb_trace(steps_start, steps_stop, index):
for n in reg:
if n.startswith("$"):
hidden_net = True
- print(" %sUUT.%s = %d'b%s;" % ("// " if hidden_net else "", ".".join(reg), len(val), val), file=f)
+ print(" %sUUT.%s = %d'b%s;" % ("// " if hidden_net else "", ".".join(escape_identifier(reg)), len(val), val), file=f)
anyconsts = sorted(smt.hieranyconsts(vlogtb_topmod))
for info in anyconsts:
if info[3] is not None:
modstate = smt.net_expr(vlogtb_topmod, vlogtb_state.replace("@@step_idx@@", str(steps_start)), info[0])
value = smt.bv2bin(smt.get("(|%s| %s)" % (info[1], modstate)))
- print(" UUT.%s = %d'b%s;" % (".".join(info[0] + [info[3]]), len(value), value), file=f);
+ print(" UUT.%s = %d'b%s;" % (".".join(escape_identifier(info[0] + [info[3]])), len(value), value), file=f);
mems = sorted(smt.hiermems(vlogtb_topmod))
for mempath in mems:
@@ -924,7 +942,7 @@ def write_vlogtb_trace(steps_start, steps_stop, index):
addr_data[addr] = data
for addr, data in addr_data.items():
- print(" UUT.%s[%d'b%s] = %d'b%s;" % (".".join(mempath), len(addr), addr, len(data), data), file=f)
+ print(" UUT.%s[%d'b%s] = %d'b%s;" % (".".join(escape_identifier(mempath)), len(addr), addr, len(data), data), file=f)
print("", file=f)
anyseqs = sorted(smt.hieranyseqs(vlogtb_topmod))
@@ -940,18 +958,18 @@ def write_vlogtb_trace(steps_start, steps_stop, index):
for name, val in zip(pi_names, pi_values):
if i > 0:
- print(" PI_%s <= %d'b%s;" % (".".join(name), len(val), val), file=f)
+ print(" %s <= %d'b%s;" % (escape_identifier("PI_"+".".join(name)), len(val), val), file=f)
else:
- print(" PI_%s = %d'b%s;" % (".".join(name), len(val), val), file=f)
+ print(" %s = %d'b%s;" % (escape_identifier("PI_"+".".join(name)), len(val), val), file=f)
for info in anyseqs:
if info[3] is not None:
modstate = smt.net_expr(vlogtb_topmod, vlogtb_state.replace("@@step_idx@@", str(i)), info[0])
value = smt.bv2bin(smt.get("(|%s| %s)" % (info[1], modstate)))
if i > 0:
- print(" UUT.%s <= %d'b%s;" % (".".join(info[0] + [info[3]]), len(value), value), file=f);
+ print(" UUT.%s <= %d'b%s;" % (".".join(escape_identifier(info[0] + [info[3]])), len(value), value), file=f);
else:
- print(" UUT.%s = %d'b%s;" % (".".join(info[0] + [info[3]]), len(value), value), file=f);
+ print(" UUT.%s = %d'b%s;" % (".".join(escape_identifier(info[0] + [info[3]])), len(value), value), file=f);
if i > 0:
print(" end", file=f)
@@ -1275,10 +1293,10 @@ def smt_pop():
asserts_consequent_cache.pop()
smt.write("(pop 1)")
-def smt_check_sat():
+def smt_check_sat(expected=["sat", "unsat"]):
if asserts_cache_dirty:
smt_forall_assert()
- return smt.check_sat()
+ return smt.check_sat(expected=expected)
if tempind:
retstatus = "FAILED"
diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py
index 72ab39d39..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
@@ -124,6 +124,7 @@ class SmtIo:
self.timeout = 0
self.produce_models = True
self.smt2cache = [list()]
+ self.smt2_options = dict()
self.p = None
self.p_index = solvers_index
solvers_index += 1
@@ -202,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":
@@ -258,14 +259,24 @@ class SmtIo:
for stmt in self.info_stmts:
self.write(stmt)
- if self.forall and self.solver == "yices":
- self.write("(set-option :yices-ef-max-iters 1000000000)")
-
if self.produce_models:
self.write("(set-option :produce-models true)")
+ #See the SMT-LIB Standard, Section 4.1.7
+ modestart_options = [":global-declarations", ":interactive-mode", ":produce-assertions", ":produce-assignments", ":produce-models", ":produce-proofs", ":produce-unsat-assumptions", ":produce-unsat-cores", ":random-seed"]
+ for key, val in self.smt2_options.items():
+ if key in modestart_options:
+ self.write("(set-option {} {})".format(key, val))
+
self.write("(set-logic %s)" % self.logic)
+ if self.forall and self.solver == "yices":
+ self.write("(set-option :yices-ef-max-iters 1000000000)")
+
+ for key, val in self.smt2_options.items():
+ if key not in modestart_options:
+ self.write("(set-option {} {})".format(key, val))
+
def timestamp(self):
secs = int(time() - self.start_time)
return "## %3d:%02d:%02d " % (secs // (60*60), (secs // 60) % 60, secs % 60)
@@ -468,6 +479,9 @@ class SmtIo:
fields = stmt.split()
+ if fields[1] == "yosys-smt2-solver-option":
+ self.smt2_options[fields[2]] = fields[3]
+
if fields[1] == "yosys-smt2-nomem":
if self.logic is None:
self.logic_ax = False
@@ -653,7 +667,7 @@ class SmtIo:
return stmt
- def check_sat(self):
+ def check_sat(self, expected=["sat", "unsat", "unknown", "timeout", "interrupted"]):
if self.debug_print:
print("> (check-sat)")
if self.debug_file and not self.nocomments:
@@ -740,7 +754,7 @@ class SmtIo:
print("(check-sat)", file=self.debug_file)
self.debug_file.flush()
- if result not in ["sat", "unsat", "unknown", "timeout", "interrupted"]:
+ if result not in expected:
if result == "":
print("%s Unexpected EOF response from solver." % (self.timestamp()), flush=True)
else:
@@ -996,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/.gitignore b/backends/smv/.gitignore
new file mode 100644
index 000000000..d23d492d7
--- /dev/null
+++ b/backends/smv/.gitignore
@@ -0,0 +1 @@
+/test_cells.tmp/
diff --git a/backends/smv/smv.cc b/backends/smv/smv.cc
index 4e5c6050d..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
@@ -573,8 +573,22 @@ struct SmvWorker
continue;
}
- if (cell->type[0] == '$')
- log_error("Found currently unsupported cell type %s (%s.%s).\n", log_id(cell->type), log_id(module), log_id(cell));
+ if (cell->type[0] == '$') {
+ if (cell->type.in(ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)) || cell->type.str().substr(0, 6) == "$_SDFF" || (cell->type.str().substr(0, 6) == "$_DFFE" && cell->type.str().size() == 10)) {
+ 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($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));
+ }
+ if (cell->type.in(ID($sr), ID($dlatch), ID($adlatch), ID($dlatchsr)) || cell->type.str().substr(0, 8) == "$_DLATCH" || cell->type.str().substr(0, 5) == "$_SR_") {
+ log_error("Unsupported cell type %s for cell %s.%s -- please run `clk2fflogic` before `write_smv`.\n",
+ log_id(cell->type), log_id(module), log_id(cell));
+ }
+ log_error("Unsupported cell type %s for cell %s.%s.\n",
+ log_id(cell->type), log_id(module), log_id(cell));
+ }
// f << stringf(" %s : %s;\n", cid(cell->name), cid(cell->type));
@@ -727,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 aa20f106a..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
@@ -64,7 +64,7 @@ static void print_spice_net(std::ostream &f, RTLIL::SigBit s, std::string &neg,
}
}
-static void print_spice_module(std::ostream &f, RTLIL::Module *module, RTLIL::Design *design, std::string &neg, std::string &pos, std::string &ncpf, bool big_endian, bool use_inames)
+static void print_spice_module(std::ostream &f, RTLIL::Module *module, RTLIL::Design *design, std::string &neg, std::string &pos, std::string &buf, std::string &ncpf, bool big_endian, bool use_inames)
{
SigMap sigmap(module);
idict<IdString, 1> inums;
@@ -121,10 +121,10 @@ static void print_spice_module(std::ostream &f, RTLIL::Module *module, RTLIL::De
for (auto &conn : module->connections())
for (int i = 0; i < conn.first.size(); i++) {
- f << stringf("V%d", conn_counter++);
- print_spice_net(f, conn.first.extract(i, 1), neg, pos, ncpf, nc_counter, use_inames, inums);
+ f << (buf == "DC" ? stringf("V%d", conn_counter++) : stringf("X%d", cell_counter++));
print_spice_net(f, conn.second.extract(i, 1), neg, pos, ncpf, nc_counter, use_inames, inums);
- f << stringf(" DC 0\n");
+ print_spice_net(f, conn.first.extract(i, 1), neg, pos, ncpf, nc_counter, use_inames, inums);
+ f << (buf == "DC" ? " DC 0\n" : stringf(" %s\n", buf.c_str()));
}
}
@@ -148,6 +148,10 @@ struct SpiceBackend : public Backend {
log(" -pos net_name\n");
log(" set the net name for constant 1 (default: Vdd)\n");
log("\n");
+ log(" -buf DC|subckt_name\n");
+ log(" set the name for jumper element (default: DC)\n");
+ log(" (used to connect different nets)\n");
+ log("\n");
log(" -nc_prefix\n");
log(" prefix for not-connected nets (default: _NC)\n");
log("\n");
@@ -164,7 +168,7 @@ struct SpiceBackend : public Backend {
std::string top_module_name;
RTLIL::Module *top_module = NULL;
bool big_endian = false, use_inames = false;
- std::string neg = "Vss", pos = "Vdd", ncpf = "_NC";
+ std::string neg = "Vss", pos = "Vdd", ncpf = "_NC", buf = "DC";
log_header(design, "Executing SPICE backend.\n");
@@ -187,6 +191,10 @@ struct SpiceBackend : public Backend {
pos = args[++argidx];
continue;
}
+ if (args[argidx] == "-buf" && argidx+1 < args.size()) {
+ buf = args[++argidx];
+ continue;
+ }
if (args[argidx] == "-nc_prefix" && argidx+1 < args.size()) {
ncpf = args[++argidx];
continue;
@@ -241,14 +249,14 @@ struct SpiceBackend : public Backend {
*f << stringf(" %s", spice_id2str(wire->name).c_str());
}
*f << stringf("\n");
- print_spice_module(*f, module, design, neg, pos, ncpf, big_endian, use_inames);
+ print_spice_module(*f, module, design, neg, pos, buf, ncpf, big_endian, use_inames);
*f << stringf(".ENDS %s\n\n", spice_id2str(module->name).c_str());
}
if (!top_module_name.empty()) {
if (top_module == NULL)
log_error("Can't find top module `%s'!\n", top_module_name.c_str());
- print_spice_module(*f, top_module, design, neg, pos, ncpf, big_endian, use_inames);
+ print_spice_module(*f, top_module, design, neg, pos, buf, ncpf, big_endian, use_inames);
*f << stringf("\n");
}
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 cef1dd9df..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
@@ -25,6 +25,8 @@
#include "kernel/celltypes.h"
#include "kernel/log.h"
#include "kernel/sigtools.h"
+#include "kernel/ff.h"
+#include "kernel/mem.h"
#include <string>
#include <sstream>
#include <set>
@@ -33,15 +35,16 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, extmem, defparam, decimal, siminit;
+bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, extmem, defparam, decimal, siminit, systemverilog, simple_lhs;
int auto_name_counter, auto_name_offset, auto_name_digits, extmem_counter;
std::map<RTLIL::IdString, int> auto_name_map;
-std::set<RTLIL::IdString> reg_wires, reg_ct;
+std::set<RTLIL::IdString> reg_wires;
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)
{
@@ -355,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()) {
@@ -428,15 +432,509 @@ 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
}
-void dump_memory(std::ostream &f, std::string indent, RTLIL::Memory *memory)
+void dump_memory(std::ostream &f, std::string indent, Mem &mem)
{
- dump_attributes(f, indent, memory->attributes);
- f << stringf("%s" "reg [%d:0] %s [%d:%d];\n", indent.c_str(), memory->width-1, id(memory->name).c_str(), memory->size+memory->start_offset-1, memory->start_offset);
+ std::string mem_id = id(mem.memid);
+
+ dump_attributes(f, indent, mem.attributes);
+ f << stringf("%s" "reg [%d:0] %s [%d:%d];\n", indent.c_str(), mem.width-1, mem_id.c_str(), mem.size+mem.start_offset-1, mem.start_offset);
+
+ // for memory block make something like:
+ // reg [7:0] memid [3:0];
+ // initial begin
+ // memid[0] = ...
+ // end
+ if (!mem.inits.empty())
+ {
+ if (extmem)
+ {
+ std::string extmem_filename = stringf("%s-%d.mem", extmem_prefix.c_str(), extmem_counter++);
+
+ std::string extmem_filename_esc;
+ for (auto c : extmem_filename)
+ {
+ if (c == '\n')
+ extmem_filename_esc += "\\n";
+ else if (c == '\t')
+ extmem_filename_esc += "\\t";
+ else if (c < 32)
+ extmem_filename_esc += stringf("\\%03o", c);
+ else if (c == '"')
+ extmem_filename_esc += "\\\"";
+ else if (c == '\\')
+ extmem_filename_esc += "\\\\";
+ else
+ extmem_filename_esc += c;
+ }
+ f << stringf("%s" "initial $readmemb(\"%s\", %s);\n", indent.c_str(), extmem_filename_esc.c_str(), mem_id.c_str());
+
+ std::ofstream extmem_f(extmem_filename, std::ofstream::trunc);
+ if (extmem_f.fail())
+ log_error("Can't open file `%s' for writing: %s\n", extmem_filename.c_str(), strerror(errno));
+ else
+ {
+ Const data = mem.get_init_data();
+ for (int i=0; i<mem.size; i++)
+ {
+ RTLIL::Const element = data.extract(i*mem.width, mem.width);
+ for (int j=0; j<element.size(); j++)
+ {
+ switch (element[element.size()-j-1])
+ {
+ case State::S0: extmem_f << '0'; break;
+ case State::S1: extmem_f << '1'; break;
+ case State::Sx: extmem_f << 'x'; break;
+ case State::Sz: extmem_f << 'z'; break;
+ case State::Sa: extmem_f << '_'; break;
+ case State::Sm: log_error("Found marker state in final netlist.");
+ }
+ }
+ extmem_f << '\n';
+ }
+ }
+ }
+ else
+ {
+ f << stringf("%s" "initial begin\n", indent.c_str());
+ for (auto &init : mem.inits) {
+ int words = GetSize(init.data) / mem.width;
+ int start = init.addr.as_int();
+ for (int i=0; i<words; i++)
+ {
+ 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());
+ }
+ }
+
+ // 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
+ std::vector<std::string> lof_reg_declarations;
+
+ // read ports
+ for (auto &port : mem.rd_ports)
+ {
+ if (port.clk_enable)
+ {
+ {
+ std::ostringstream os;
+ dump_sigspec(os, port.clk);
+ clk_domain_str = stringf("%sedge %s", port.clk_polarity ? "pos" : "neg", os.str().c_str());
+ 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();
+ }
+ }
+
+ // 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;
+ // always @(posedge clk)
+ // if (rd_en) temp_id <= array_reg[r_addr];
+ // 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;
+ 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";
+ }
+ 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);
+ std::string line = stringf("assign %s = %s;\n", os.str().c_str(), temp_id.c_str());
+ clk_to_lof_body[""].push_back(line);
+ }
+ }
+ else
+ {
+ // for rd-transparent read-ports make something like:
+ // reg [..] temp_id;
+ // always @(posedge clk)
+ // 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 - port.wide_log2, temp_id.c_str()) );
+ {
+ std::ostringstream os;
+ 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;
+ 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];
+ 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. 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)
+ {
+ 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;
+ }
+
+ 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" : " @*");
+ }
+
+ for (int pidx = 0; pidx < GetSize(mem.wr_ports); pidx++)
+ {
+ if (!wr_ports_now.count(pidx))
+ continue;
+ wr_ports_done.insert(pidx);
+
+ 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++)
+ {
+ 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");
+ }
+ }
+ }
+
+ f << stringf("%s" "end\n", indent.c_str());
+ }
+ // Output Verilog that looks something like this:
+ // reg [..] _3_;
+ // always @(posedge CLK2) begin
+ // _3_ <= memory[D1ADDR];
+ // if (A1EN)
+ // memory[A1ADDR] <= A1DATA;
+ // if (A2EN)
+ // memory[A2ADDR] <= A2DATA;
+ // ...
+ // end
+ // always @(negedge CLK1) begin
+ // if (C1EN)
+ // memory[C1ADDR] <= C1DATA;
+ // end
+ // ...
+ // assign D1DATA = _3_;
+ // assign D2DATA <= memory[D2ADDR];
+
+ // the reg ... definitions
+ for(auto &reg : lof_reg_declarations)
+ {
+ f << stringf("%s" "%s", indent.c_str(), reg.c_str());
+ }
+ // the block of expressions by clock domain
+ for(auto &pair : clk_to_lof_body)
+ {
+ std::string clk_domain = pair.first;
+ std::vector<std::string> lof_lines = pair.second;
+ if( clk_domain != "")
+ {
+ f << stringf("%s" "always%s @(%s) begin\n", indent.c_str(), systemverilog ? "_ff" : "", clk_domain.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
+ {
+ // the non-clocked assignments
+ for(auto &line : lof_lines)
+ f << stringf("%s" "%s", indent.c_str(), line.c_str());
+ }
+ }
}
void dump_cell_expr_port(std::ostream &f, RTLIL::Cell *cell, std::string port, bool gen_signed = true)
@@ -451,7 +949,7 @@ void dump_cell_expr_port(std::ostream &f, RTLIL::Cell *cell, std::string port, b
std::string cellname(RTLIL::Cell *cell)
{
- if (!norename && cell->name[0] == '$' && reg_ct.count(cell->type) && cell->hasPort(ID::Q))
+ if (!norename && cell->name[0] == '$' && RTLIL::builtin_ff_cell_types().count(cell->type) && cell->hasPort(ID::Q) && !cell->type.in(ID($ff), ID($_FF_)))
{
RTLIL::SigSpec sig = cell->getPort(ID::Q);
if (GetSize(sig) != 1 || sig.is_fully_const())
@@ -605,93 +1103,6 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
return true;
}
- if (cell->type.begins_with("$_DFF_"))
- {
- std::string reg_name = cellname(cell);
- bool out_is_reg_wire = is_reg_wire(cell->getPort(ID::Q), reg_name);
-
- if (!out_is_reg_wire) {
- f << stringf("%s" "reg %s", indent.c_str(), reg_name.c_str());
- dump_reg_init(f, cell->getPort(ID::Q));
- f << ";\n";
- }
-
- dump_attributes(f, indent, cell->attributes);
- f << stringf("%s" "always @(%sedge ", indent.c_str(), cell->type[6] == 'P' ? "pos" : "neg");
- dump_sigspec(f, cell->getPort(ID::C));
- if (cell->type[7] != '_') {
- f << stringf(" or %sedge ", cell->type[7] == 'P' ? "pos" : "neg");
- dump_sigspec(f, cell->getPort(ID::R));
- }
- f << stringf(")\n");
-
- if (cell->type[7] != '_') {
- f << stringf("%s" " if (%s", indent.c_str(), cell->type[7] == 'P' ? "" : "!");
- dump_sigspec(f, cell->getPort(ID::R));
- f << stringf(")\n");
- f << stringf("%s" " %s <= %c;\n", indent.c_str(), reg_name.c_str(), cell->type[8]);
- f << stringf("%s" " else\n", indent.c_str());
- }
-
- f << stringf("%s" " %s <= ", indent.c_str(), reg_name.c_str());
- dump_cell_expr_port(f, cell, "D", false);
- f << stringf(";\n");
-
- if (!out_is_reg_wire) {
- f << stringf("%s" "assign ", indent.c_str());
- dump_sigspec(f, cell->getPort(ID::Q));
- f << stringf(" = %s;\n", reg_name.c_str());
- }
-
- return true;
- }
-
- if (cell->type.begins_with("$_DFFSR_"))
- {
- char pol_c = cell->type[8], pol_s = cell->type[9], pol_r = cell->type[10];
-
- std::string reg_name = cellname(cell);
- bool out_is_reg_wire = is_reg_wire(cell->getPort(ID::Q), reg_name);
-
- if (!out_is_reg_wire) {
- f << stringf("%s" "reg %s", indent.c_str(), reg_name.c_str());
- dump_reg_init(f, cell->getPort(ID::Q));
- f << ";\n";
- }
-
- dump_attributes(f, indent, cell->attributes);
- f << stringf("%s" "always @(%sedge ", indent.c_str(), pol_c == 'P' ? "pos" : "neg");
- dump_sigspec(f, cell->getPort(ID::C));
- f << stringf(" or %sedge ", pol_s == 'P' ? "pos" : "neg");
- dump_sigspec(f, cell->getPort(ID::S));
- f << stringf(" or %sedge ", pol_r == 'P' ? "pos" : "neg");
- dump_sigspec(f, cell->getPort(ID::R));
- f << stringf(")\n");
-
- f << stringf("%s" " if (%s", indent.c_str(), pol_r == 'P' ? "" : "!");
- dump_sigspec(f, cell->getPort(ID::R));
- f << stringf(")\n");
- f << stringf("%s" " %s <= 0;\n", indent.c_str(), reg_name.c_str());
-
- f << stringf("%s" " else if (%s", indent.c_str(), pol_s == 'P' ? "" : "!");
- dump_sigspec(f, cell->getPort(ID::S));
- f << stringf(")\n");
- f << stringf("%s" " %s <= 1;\n", indent.c_str(), reg_name.c_str());
-
- f << stringf("%s" " else\n", indent.c_str());
- f << stringf("%s" " %s <= ", indent.c_str(), reg_name.c_str());
- dump_cell_expr_port(f, cell, "D", false);
- f << stringf(";\n");
-
- if (!out_is_reg_wire) {
- f << stringf("%s" "assign ", indent.c_str());
- dump_sigspec(f, cell->getPort(ID::Q));
- f << stringf(" = %s;\n", reg_name.c_str());
- }
-
- return true;
- }
-
#define HANDLE_UNIOP(_type, _operator) \
if (cell->type ==_type) { dump_cell_expr_uniop(f, indent, cell, _operator); return true; }
#define HANDLE_BINOP(_type, _operator) \
@@ -836,21 +1247,19 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
f << stringf(" = ");
if (cell->getParam(ID::B_SIGNED).as_bool())
{
- f << stringf("$signed(");
- dump_sigspec(f, cell->getPort(ID::B));
- f << stringf(")");
+ dump_cell_expr_port(f, cell, "B", true);
f << stringf(" < 0 ? ");
- dump_sigspec(f, cell->getPort(ID::A));
+ dump_cell_expr_port(f, cell, "A", true);
f << stringf(" << - ");
dump_sigspec(f, cell->getPort(ID::B));
f << stringf(" : ");
- dump_sigspec(f, cell->getPort(ID::A));
+ dump_cell_expr_port(f, cell, "A", true);
f << stringf(" >> ");
dump_sigspec(f, cell->getPort(ID::B));
}
else
{
- dump_sigspec(f, cell->getPort(ID::A));
+ dump_cell_expr_port(f, cell, "A", true);
f << stringf(" >> ");
dump_sigspec(f, cell->getPort(ID::B));
}
@@ -986,431 +1395,233 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
return true;
}
- if (cell->type == ID($dffsr))
+ if (RTLIL::builtin_ff_cell_types().count(cell->type))
{
- SigSpec sig_clk = cell->getPort(ID::CLK);
- SigSpec sig_set = cell->getPort(ID::SET);
- SigSpec sig_clr = cell->getPort(ID::CLR);
- SigSpec sig_d = cell->getPort(ID::D);
- SigSpec sig_q = cell->getPort(ID::Q);
+ FfData ff(nullptr, cell);
- int width = cell->parameters[ID::WIDTH].as_int();
- bool pol_clk = cell->parameters[ID::CLK_POLARITY].as_bool();
- bool pol_set = cell->parameters[ID::SET_POLARITY].as_bool();
- bool pol_clr = cell->parameters[ID::CLR_POLARITY].as_bool();
+ // $ff / $_FF_ cell: not supported.
+ if (ff.has_gclk)
+ return false;
std::string reg_name = cellname(cell);
- bool out_is_reg_wire = is_reg_wire(sig_q, reg_name);
-
- if (!out_is_reg_wire) {
- f << stringf("%s" "reg [%d:0] %s", indent.c_str(), width-1, reg_name.c_str());
- dump_reg_init(f, sig_q);
- f << ";\n";
- }
-
- for (int i = 0; i < width; i++) {
- f << stringf("%s" "always @(%sedge ", indent.c_str(), pol_clk ? "pos" : "neg");
- dump_sigspec(f, sig_clk);
- f << stringf(", %sedge ", pol_set ? "pos" : "neg");
- dump_sigspec(f, sig_set);
- f << stringf(", %sedge ", pol_clr ? "pos" : "neg");
- dump_sigspec(f, sig_clr);
- f << stringf(")\n");
-
- f << stringf("%s" " if (%s", indent.c_str(), pol_clr ? "" : "!");
- dump_sigspec(f, sig_clr);
- f << stringf(") %s[%d] <= 1'b0;\n", reg_name.c_str(), i);
-
- f << stringf("%s" " else if (%s", indent.c_str(), pol_set ? "" : "!");
- dump_sigspec(f, sig_set);
- f << stringf(") %s[%d] <= 1'b1;\n", reg_name.c_str(), i);
-
- f << stringf("%s" " else %s[%d] <= ", indent.c_str(), reg_name.c_str(), i);
- dump_sigspec(f, sig_d[i]);
- f << stringf(";\n");
- }
+ bool out_is_reg_wire = is_reg_wire(ff.sig_q, reg_name);
if (!out_is_reg_wire) {
- f << stringf("%s" "assign ", indent.c_str());
- dump_sigspec(f, sig_q);
- f << stringf(" = %s;\n", reg_name.c_str());
- }
-
- return true;
- }
-
- if (cell->type.in(ID($dff), ID($adff), ID($dffe)))
- {
- RTLIL::SigSpec sig_clk, sig_arst, sig_en, val_arst;
- bool pol_clk, pol_arst = false, pol_en = false;
-
- sig_clk = cell->getPort(ID::CLK);
- pol_clk = cell->parameters[ID::CLK_POLARITY].as_bool();
-
- if (cell->type == ID($adff)) {
- sig_arst = cell->getPort(ID::ARST);
- pol_arst = cell->parameters[ID::ARST_POLARITY].as_bool();
- val_arst = RTLIL::SigSpec(cell->parameters[ID::ARST_VALUE]);
- }
-
- if (cell->type == ID($dffe)) {
- sig_en = cell->getPort(ID::EN);
- pol_en = cell->parameters[ID::EN_POLARITY].as_bool();
- }
-
- std::string reg_name = cellname(cell);
- bool out_is_reg_wire = is_reg_wire(cell->getPort(ID::Q), reg_name);
-
- if (!out_is_reg_wire) {
- f << stringf("%s" "reg [%d:0] %s", indent.c_str(), cell->parameters[ID::WIDTH].as_int()-1, reg_name.c_str());
- dump_reg_init(f, cell->getPort(ID::Q));
- f << ";\n";
- }
-
- f << stringf("%s" "always @(%sedge ", indent.c_str(), pol_clk ? "pos" : "neg");
- dump_sigspec(f, sig_clk);
- if (cell->type == ID($adff)) {
- f << stringf(" or %sedge ", pol_arst ? "pos" : "neg");
- dump_sigspec(f, sig_arst);
- }
- f << stringf(")\n");
-
- if (cell->type == ID($adff)) {
- f << stringf("%s" " if (%s", indent.c_str(), pol_arst ? "" : "!");
- dump_sigspec(f, sig_arst);
- f << stringf(")\n");
- f << stringf("%s" " %s <= ", indent.c_str(), reg_name.c_str());
- dump_sigspec(f, val_arst);
- f << stringf(";\n");
- f << stringf("%s" " else\n", indent.c_str());
- }
-
- if (cell->type == ID($dffe)) {
- f << stringf("%s" " if (%s", indent.c_str(), pol_en ? "" : "!");
- dump_sigspec(f, sig_en);
- f << stringf(")\n");
- }
-
- f << stringf("%s" " %s <= ", indent.c_str(), reg_name.c_str());
- dump_cell_expr_port(f, cell, "D", false);
- f << stringf(";\n");
-
- if (!out_is_reg_wire) {
- f << stringf("%s" "assign ", indent.c_str());
- dump_sigspec(f, cell->getPort(ID::Q));
- f << stringf(" = %s;\n", reg_name.c_str());
- }
-
- return true;
- }
-
- if (cell->type == ID($dlatch))
- {
- RTLIL::SigSpec sig_en;
- bool pol_en = false;
-
- sig_en = cell->getPort(ID::EN);
- pol_en = cell->parameters[ID::EN_POLARITY].as_bool();
-
- std::string reg_name = cellname(cell);
- bool out_is_reg_wire = is_reg_wire(cell->getPort(ID::Q), reg_name);
-
- if (!out_is_reg_wire) {
- f << stringf("%s" "reg [%d:0] %s", indent.c_str(), cell->parameters[ID::WIDTH].as_int()-1, reg_name.c_str());
- dump_reg_init(f, cell->getPort(ID::Q));
+ if (ff.width == 1)
+ f << stringf("%s" "reg %s", indent.c_str(), reg_name.c_str());
+ else
+ f << stringf("%s" "reg [%d:0] %s", indent.c_str(), ff.width-1, reg_name.c_str());
+ dump_reg_init(f, ff.sig_q);
f << ";\n";
}
- f << stringf("%s" "always @*\n", indent.c_str());
-
- f << stringf("%s" " if (%s", indent.c_str(), pol_en ? "" : "!");
- dump_sigspec(f, sig_en);
- f << stringf(")\n");
-
- f << stringf("%s" " %s = ", indent.c_str(), reg_name.c_str());
- dump_cell_expr_port(f, cell, "D", false);
- f << stringf(";\n");
-
- if (!out_is_reg_wire) {
- f << stringf("%s" "assign ", indent.c_str());
- dump_sigspec(f, cell->getPort(ID::Q));
- f << stringf(" = %s;\n", reg_name.c_str());
- }
-
- return true;
- }
+ // If the FF has CLR/SET inputs, emit every bit slice separately.
+ int chunks = ff.has_sr ? ff.width : 1;
+ bool chunky = ff.has_sr && ff.width != 1;
- if (cell->type == ID($mem))
- {
- RTLIL::IdString memid = cell->parameters[ID::MEMID].decode_string();
- std::string mem_id = id(cell->parameters[ID::MEMID].decode_string());
- int abits = cell->parameters[ID::ABITS].as_int();
- int size = cell->parameters[ID::SIZE].as_int();
- int offset = cell->parameters[ID::OFFSET].as_int();
- int width = cell->parameters[ID::WIDTH].as_int();
- bool use_init = !(RTLIL::SigSpec(cell->parameters[ID::INIT]).is_fully_undef());
-
- // for memory block make something like:
- // reg [7:0] memid [3:0];
- // initial begin
- // memid[0] = ...
- // end
- dump_attributes(f, indent.c_str(), cell->attributes);
- f << stringf("%s" "reg [%d:%d] %s [%d:%d];\n", indent.c_str(), width-1, 0, mem_id.c_str(), size+offset-1, offset);
- if (use_init)
+ for (int i = 0; i < chunks; i++)
{
- if (extmem)
- {
- std::string extmem_filename = stringf("%s-%d.mem", extmem_prefix.c_str(), extmem_counter++);
-
- std::string extmem_filename_esc;
- for (auto c : extmem_filename)
- {
- if (c == '\n')
- extmem_filename_esc += "\\n";
- else if (c == '\t')
- extmem_filename_esc += "\\t";
- else if (c < 32)
- extmem_filename_esc += stringf("\\%03o", c);
- else if (c == '"')
- extmem_filename_esc += "\\\"";
- else if (c == '\\')
- extmem_filename_esc += "\\\\";
- else
- extmem_filename_esc += c;
- }
- f << stringf("%s" "initial $readmemb(\"%s\", %s);\n", indent.c_str(), extmem_filename_esc.c_str(), mem_id.c_str());
-
- std::ofstream extmem_f(extmem_filename, std::ofstream::trunc);
- if (extmem_f.fail())
- log_error("Can't open file `%s' for writing: %s\n", extmem_filename.c_str(), strerror(errno));
- else
- {
- for (int i=0; i<size; i++)
- {
- RTLIL::Const element = cell->parameters[ID::INIT].extract(i*width, width);
- for (int j=0; j<element.size(); j++)
- {
- switch (element[element.size()-j-1])
- {
- case State::S0: extmem_f << '0'; break;
- case State::S1: extmem_f << '1'; break;
- case State::Sx: extmem_f << 'x'; break;
- case State::Sz: extmem_f << 'z'; break;
- case State::Sa: extmem_f << '_'; break;
- case State::Sm: log_error("Found marker state in final netlist.");
- }
- }
- extmem_f << '\n';
- }
- }
-
- }
- else
- {
- f << stringf("%s" "initial begin\n", indent.c_str());
- for (int i=0; i<size; i++)
- {
- f << stringf("%s" " %s[%d] = ", indent.c_str(), mem_id.c_str(), i);
- dump_const(f, cell->parameters[ID::INIT].extract(i*width, width));
- f << stringf(";\n");
- }
- f << stringf("%s" "end\n", indent.c_str());
+ SigSpec sig_d, sig_ad;
+ Const val_arst, val_srst;
+ 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_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;
+ sig_d = ff.sig_d;
+ sig_ad = ff.sig_ad;
}
- }
-
- // create a map : "edge clk" -> expressions within that clock domain
- dict<std::string, std::vector<std::string>> clk_to_lof_body;
- clk_to_lof_body[""] = std::vector<std::string>();
- std::string clk_domain_str;
- // create a list of reg declarations
- std::vector<std::string> lof_reg_declarations;
-
- int nread_ports = cell->parameters[ID::RD_PORTS].as_int();
- RTLIL::SigSpec sig_rd_clk, sig_rd_en, sig_rd_data, sig_rd_addr;
- bool use_rd_clk, rd_clk_posedge, rd_transparent;
- // read ports
- for (int i=0; i < nread_ports; i++)
- {
- sig_rd_clk = cell->getPort(ID::RD_CLK).extract(i);
- sig_rd_en = cell->getPort(ID::RD_EN).extract(i);
- sig_rd_data = cell->getPort(ID::RD_DATA).extract(i*width, width);
- sig_rd_addr = cell->getPort(ID::RD_ADDR).extract(i*abits, abits);
- use_rd_clk = cell->parameters[ID::RD_CLK_ENABLE].extract(i).as_bool();
- rd_clk_posedge = cell->parameters[ID::RD_CLK_POLARITY].extract(i).as_bool();
- rd_transparent = cell->parameters[ID::RD_TRANSPARENT].extract(i).as_bool();
- if (use_rd_clk)
- {
- {
- std::ostringstream os;
- dump_sigspec(os, sig_rd_clk);
- clk_domain_str = stringf("%sedge %s", rd_clk_posedge ? "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 (!rd_transparent)
- {
- // for clocked read ports make something like:
- // reg [..] temp_id;
- // always @(posedge clk)
- // if (rd_en) temp_id <= array_reg[r_addr];
- // assign r_data = temp_id;
- std::string temp_id = next_auto_id();
- lof_reg_declarations.push_back( stringf("reg [%d:0] %s;\n", sig_rd_data.size() - 1, temp_id.c_str()) );
+ if (ff.has_arst)
+ val_arst = chunky ? ff.val_arst[i] : ff.val_arst;
+ if (ff.has_srst)
+ 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_clk) {
+ if (ff.has_sr) {
+ if (ff.sig_set[i].wire == NULL)
{
- std::ostringstream os;
- if (sig_rd_en != RTLIL::SigBit(true))
- {
- os << stringf("if (");
- dump_sigspec(os, sig_rd_en);
- os << stringf(") ");
- }
- os << stringf("%s <= %s[", temp_id.c_str(), mem_id.c_str());
- dump_sigspec(os, sig_rd_addr);
- os << stringf("];\n");
- clk_to_lof_body[clk_domain_str].push_back(os.str());
+ 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)
{
- std::ostringstream os;
- dump_sigspec(os, sig_rd_data);
- std::string line = stringf("assign %s = %s;\n", os.str().c_str(), temp_id.c_str());
- clk_to_lof_body[""].push_back(line);
+ 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
- {
- // for rd-transparent read-ports make something like:
- // reg [..] temp_id;
- // always @(posedge clk)
- // 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", sig_rd_addr.size() - 1, temp_id.c_str()) );
+ } else if (ff.has_arst) {
+ if (ff.sig_arst[0].wire == NULL)
{
- std::ostringstream os;
- dump_sigspec(os, sig_rd_addr);
- 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);
+ 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)
{
- std::ostringstream os;
- dump_sigspec(os, sig_rd_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);
+ 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");
}
}
- } else {
- // for non-clocked read-ports make something like:
- // assign r_data = array_reg[r_addr];
- std::ostringstream os, os2;
- dump_sigspec(os, sig_rd_data);
- dump_sigspec(os2, sig_rd_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);
}
- }
-
- int nwrite_ports = cell->parameters[ID::WR_PORTS].as_int();
- RTLIL::SigSpec sig_wr_clk, sig_wr_data, sig_wr_addr, sig_wr_en;
- bool wr_clk_posedge;
- // write ports
- for (int i=0; i < nwrite_ports; i++)
- {
- sig_wr_clk = cell->getPort(ID::WR_CLK).extract(i);
- sig_wr_data = cell->getPort(ID::WR_DATA).extract(i*width, width);
- sig_wr_addr = cell->getPort(ID::WR_ADDR).extract(i*abits, abits);
- sig_wr_en = cell->getPort(ID::WR_EN).extract(i*width, width);
- wr_clk_posedge = cell->parameters[ID::WR_CLK_POLARITY].extract(i).as_bool();
- {
- std::ostringstream os;
- dump_sigspec(os, sig_wr_clk);
- clk_domain_str = stringf("%sedge %s", wr_clk_posedge ? "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>();
- }
- // make something like:
- // always @(posedge clk)
- // if (wr_en_bit) memid[w_addr][??] <= w_data[??];
- // ...
- for (int i = 0; i < GetSize(sig_wr_en); i++)
+ dump_attributes(f, indent, cell->attributes);
+ if (ff.has_clk)
{
- int start_i = i, width = 1;
- SigBit wen_bit = sig_wr_en[i];
+ // FFs.
+ f << stringf("%s" "always%s @(%sedge ", indent.c_str(), systemverilog ? "_ff" : "", ff.pol_clk ? "pos" : "neg");
+ dump_sigspec(f, ff.sig_clk);
+ if (ff.has_sr) {
+ f << stringf(", %sedge ", ff.pol_set ? "pos" : "neg");
+ if (ff.sig_set[i].wire == NULL)
+ f << stringf("%s", sig_set_name.c_str());
+ else
+ dump_sigspec(f, ff.sig_set[i]);
- while (i+1 < GetSize(sig_wr_en) && active_sigmap(sig_wr_en[i+1]) == active_sigmap(wen_bit))
- i++, width++;
+ f << stringf(", %sedge ", ff.pol_clr ? "pos" : "neg");
+ if (ff.sig_clr[i].wire == NULL)
+ 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[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");
- if (wen_bit == State::S0)
- continue;
+ f << stringf("%s" " ", indent.c_str());
+ if (ff.has_sr) {
+ f << stringf("if (%s", ff.pol_clr ? "" : "!");
+ if (ff.sig_clr[i].wire == NULL)
+ f << stringf("%s", sig_clr_name.c_str());
+ else
+ dump_sigspec(f, ff.sig_clr[i]);
+ f << stringf(") %s <= 1'b0;\n", reg_bit_name.c_str());
+ f << stringf("%s" " else if (%s", indent.c_str(), ff.pol_set ? "" : "!");
+ if (ff.sig_set[i].wire == NULL)
+ f << stringf("%s", sig_set_name.c_str());
+ else
+ dump_sigspec(f, ff.sig_set[i]);
+ f << stringf(") %s <= 1'b1;\n", reg_bit_name.c_str());
+ f << stringf("%s" " else ", indent.c_str());
+ } else if (ff.has_arst) {
+ f << stringf("if (%s", ff.pol_arst ? "" : "!");
+ if (ff.sig_arst[0].wire == NULL)
+ f << stringf("%s", sig_arst_name.c_str());
+ else
+ dump_sigspec(f, ff.sig_arst);
+ f << stringf(") %s <= ", reg_bit_name.c_str());
+ 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());
+ }
- std::ostringstream os;
- if (wen_bit != State::S1)
- {
- os << stringf("if (");
- dump_sigspec(os, wen_bit);
- os << stringf(") ");
+ 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);
+ f << stringf(") %s <= ", reg_bit_name.c_str());
+ dump_sigspec(f, val_srst);
+ f << stringf(";\n");
+ f << stringf("%s" " else ", indent.c_str());
+ } else {
+ if (ff.has_srst) {
+ f << stringf("if (%s", ff.pol_srst ? "" : "!");
+ dump_sigspec(f, ff.sig_srst);
+ f << stringf(") %s <= ", reg_bit_name.c_str());
+ dump_sigspec(f, val_srst);
+ f << stringf(";\n");
+ f << stringf("%s" " else ", indent.c_str());
+ }
+ if (ff.has_ce) {
+ f << stringf("if (%s", ff.pol_ce ? "" : "!");
+ dump_sigspec(f, ff.sig_ce);
+ f << stringf(") ");
+ }
}
- os << stringf("%s[", mem_id.c_str());
- dump_sigspec(os, sig_wr_addr);
- if (width == GetSize(sig_wr_en))
- os << stringf("] <= ");
- else
- os << stringf("][%d:%d] <= ", i, start_i);
- dump_sigspec(os, sig_wr_data.extract(start_i, width));
- os << stringf(";\n");
- clk_to_lof_body[clk_domain_str].push_back(os.str());
- }
- }
- // Output Verilog that looks something like this:
- // reg [..] _3_;
- // always @(posedge CLK2) begin
- // _3_ <= memory[D1ADDR];
- // if (A1EN)
- // memory[A1ADDR] <= A1DATA;
- // if (A2EN)
- // memory[A2ADDR] <= A2DATA;
- // ...
- // end
- // always @(negedge CLK1) begin
- // if (C1EN)
- // memory[C1ADDR] <= C1DATA;
- // end
- // ...
- // assign D1DATA = _3_;
- // assign D2DATA <= memory[D2ADDR];
-
- // the reg ... definitions
- for(auto &reg : lof_reg_declarations)
- {
- f << stringf("%s" "%s", indent.c_str(), reg.c_str());
- }
- // the block of expressions by clock domain
- for(auto &pair : clk_to_lof_body)
- {
- std::string clk_domain = pair.first;
- std::vector<std::string> lof_lines = pair.second;
- if( clk_domain != "")
- {
- f << stringf("%s" "always @(%s) begin\n", indent.c_str(), clk_domain.c_str());
- 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());
+
+ f << stringf("%s <= ", reg_bit_name.c_str());
+ dump_sigspec(f, sig_d);
+ f << stringf(";\n");
}
else
{
- // the non-clocked assignments
- for(auto &line : lof_lines)
- f << stringf("%s" "%s", indent.c_str(), line.c_str());
+ // Latches.
+ f << stringf("%s" "always%s\n", indent.c_str(), systemverilog ? "_latch" : " @*");
+
+ f << stringf("%s" " ", indent.c_str());
+ if (ff.has_sr) {
+ f << stringf("if (%s", ff.pol_clr ? "" : "!");
+ dump_sigspec(f, ff.sig_clr[i]);
+ f << stringf(") %s = 1'b0;\n", reg_bit_name.c_str());
+ 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_aload)
+ f << stringf("%s" " else ", indent.c_str());
+ } else if (ff.has_arst) {
+ f << stringf("if (%s", ff.pol_arst ? "" : "!");
+ dump_sigspec(f, ff.sig_arst);
+ f << stringf(") %s = ", reg_bit_name.c_str());
+ dump_sigspec(f, val_arst);
+ f << stringf(";\n");
+ if (ff.has_aload)
+ f << stringf("%s" " else ", indent.c_str());
+ }
+ 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_ad);
+ f << stringf(";\n");
+ }
}
}
+ if (!out_is_reg_wire) {
+ f << stringf("%s" "assign ", indent.c_str());
+ dump_sigspec(f, ff.sig_q);
+ f << stringf(" = %s;\n", reg_name.c_str());
+ }
+
return true;
}
if (cell->type.in(ID($assert), ID($assume), ID($cover)))
{
- f << stringf("%s" "always @* if (", indent.c_str());
+ f << stringf("%s" "always%s if (", indent.c_str(), systemverilog ? "_comb" : " @*");
dump_sigspec(f, cell->getPort(ID::EN));
f << stringf(") %s(", cell->type.c_str()+1);
dump_sigspec(f, cell->getPort(ID::A));
@@ -1528,14 +1739,17 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
return true;
}
- // FIXME: $_SR_[PN][PN]_, $_DLATCH_[PN]_, $_DLATCHSR_[PN][PN][PN]_
- // FIXME: $sr, $dlatch, $memrd, $memwr, $fsm
+ // FIXME: $fsm
return false;
}
void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell)
{
+ // Handled by dump_memory
+ if (cell->is_mem_cell())
+ return;
+
if (cell->type[0] == '$' && !noexpr) {
if (dump_cell_expr(f, indent, cell))
return;
@@ -1602,7 +1816,7 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell)
}
}
- if (siminit && reg_ct.count(cell->type) && cell->hasPort(ID::Q)) {
+ if (siminit && RTLIL::builtin_ff_cell_types().count(cell->type) && cell->hasPort(ID::Q) && !cell->type.in(ID($ff), ID($_FF_))) {
std::stringstream ss;
dump_reg_init(ss, cell->getPort(ID::Q));
if (!ss.str().empty()) {
@@ -1615,11 +1829,23 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell)
void dump_conn(std::ostream &f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
{
- f << stringf("%s" "assign ", indent.c_str());
- dump_sigspec(f, left);
- f << stringf(" = ");
- dump_sigspec(f, right);
- f << stringf(";\n");
+ if (simple_lhs) {
+ int offset = 0;
+ for (auto &chunk : left.chunks()) {
+ f << stringf("%s" "assign ", indent.c_str());
+ dump_sigspec(f, chunk);
+ f << stringf(" = ");
+ dump_sigspec(f, right.extract(offset, GetSize(chunk)));
+ f << stringf(";\n");
+ offset += GetSize(chunk);
+ }
+ } else {
+ f << stringf("%s" "assign ", indent.c_str());
+ dump_sigspec(f, left);
+ f << stringf(" = ");
+ dump_sigspec(f, right);
+ f << stringf(";\n");
+ }
}
void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw);
@@ -1717,7 +1943,9 @@ void dump_process(std::ostream &f, std::string indent, RTLIL::Process *proc, boo
return;
}
- f << stringf("%s" "always @* begin\n", indent.c_str());
+ f << stringf("%s" "always%s begin\n", indent.c_str(), systemverilog ? "_comb" : " @*");
+ if (!systemverilog)
+ f << indent + " " << "if (" << id(initial_id) << ") begin end\n";
dump_case_body(f, indent, &proc->root_case, true);
std::string backup_indent = indent;
@@ -1728,11 +1956,11 @@ void dump_process(std::ostream &f, std::string indent, RTLIL::Process *proc, boo
indent = backup_indent;
if (sync->type == RTLIL::STa) {
- f << stringf("%s" "always @* begin\n", indent.c_str());
+ f << stringf("%s" "always%s begin\n", indent.c_str(), systemverilog ? "_comb" : " @*");
} else if (sync->type == RTLIL::STi) {
f << stringf("%s" "initial begin\n", indent.c_str());
} else {
- f << stringf("%s" "always @(", indent.c_str());
+ f << stringf("%s" "always%s @(", indent.c_str(), systemverilog ? "_ff" : "");
if (sync->type == RTLIL::STp || sync->type == RTLIL::ST1)
f << stringf("posedge ");
if (sync->type == RTLIL::STn || sync->type == RTLIL::ST0)
@@ -1810,7 +2038,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
std::set<std::pair<RTLIL::Wire*,int>> reg_bits;
for (auto cell : module->cells())
{
- if (!reg_ct.count(cell->type) || !cell->hasPort(ID::Q))
+ if (!RTLIL::builtin_ff_cell_types().count(cell->type) || !cell->hasPort(ID::Q) || cell->type.in(ID($ff), ID($_FF_)))
continue;
RTLIL::SigSpec sig = cell->getPort(ID::Q);
@@ -1836,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()) {
@@ -1844,17 +2073,22 @@ 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()) {
+ initial_id = NEW_ID;
+ f << indent + " " << "reg " << id(initial_id) << " = 0;\n";
+ }
for (auto w : module->wires())
dump_wire(f, indent + " ", w);
- for (auto it = module->memories.begin(); it != module->memories.end(); ++it)
- dump_memory(f, indent + " ", it->second);
+ for (auto &mem : Mem::get_all_memories(module))
+ dump_memory(f, indent + " ", mem);
for (auto cell : module->cells())
dump_cell(f, indent + " ", cell);
@@ -1881,6 +2115,9 @@ struct VerilogBackend : public Backend {
log("\n");
log("Write the current design to a Verilog file.\n");
log("\n");
+ log(" -sv\n");
+ log(" with this option, SystemVerilog constructs like always_comb are used\n");
+ log("\n");
log(" -norename\n");
log(" without this option all internal object names (the ones with a dollar\n");
log(" instead of a backslash prefix) are changed to short names in the\n");
@@ -1922,6 +2159,9 @@ struct VerilogBackend : public Backend {
log(" deactivates this feature and instead will write string constants\n");
log(" as binary numbers.\n");
log("\n");
+ log(" -simple-lhs\n");
+ log(" Connection assignments with simple left hand side without concatenations.\n");
+ log("\n");
log(" -extmem\n");
log(" instead of initializing memories using assignments to individual\n");
log(" elements, use the '$readmemh' function to read initialization data\n");
@@ -1969,6 +2209,7 @@ struct VerilogBackend : public Backend {
defparam = false;
decimal = false;
siminit = false;
+ simple_lhs = false;
auto_prefix = "";
bool blackboxes = false;
@@ -1976,37 +2217,14 @@ struct VerilogBackend : public Backend {
auto_name_map.clear();
reg_wires.clear();
- reg_ct.clear();
-
- reg_ct.insert(ID($dff));
- reg_ct.insert(ID($adff));
- reg_ct.insert(ID($dffe));
- reg_ct.insert(ID($dlatch));
-
- reg_ct.insert(ID($_DFF_N_));
- reg_ct.insert(ID($_DFF_P_));
-
- reg_ct.insert(ID($_DFF_NN0_));
- reg_ct.insert(ID($_DFF_NN1_));
- reg_ct.insert(ID($_DFF_NP0_));
- reg_ct.insert(ID($_DFF_NP1_));
- reg_ct.insert(ID($_DFF_PN0_));
- reg_ct.insert(ID($_DFF_PN1_));
- reg_ct.insert(ID($_DFF_PP0_));
- reg_ct.insert(ID($_DFF_PP1_));
-
- reg_ct.insert(ID($_DFFSR_NNN_));
- reg_ct.insert(ID($_DFFSR_NNP_));
- reg_ct.insert(ID($_DFFSR_NPN_));
- reg_ct.insert(ID($_DFFSR_NPP_));
- reg_ct.insert(ID($_DFFSR_PNN_));
- reg_ct.insert(ID($_DFFSR_PNP_));
- reg_ct.insert(ID($_DFFSR_PPN_));
- reg_ct.insert(ID($_DFFSR_PPP_));
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
std::string arg = args[argidx];
+ if (arg == "-sv") {
+ systemverilog = true;
+ continue;
+ }
if (arg == "-norename") {
norename = true;
continue;
@@ -2064,6 +2282,10 @@ struct VerilogBackend : public Backend {
selected = true;
continue;
}
+ if (arg == "-simple-lhs") {
+ simple_lhs = true;
+ continue;
+ }
if (arg == "-v") {
verbose = true;
continue;
@@ -2078,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);
@@ -2095,7 +2323,6 @@ struct VerilogBackend : public Backend {
auto_name_map.clear();
reg_wires.clear();
- reg_ct.clear();
}
} VerilogBackend;
diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc
index 07e3cd6e0..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
@@ -55,6 +55,17 @@ inline int32_t from_big_endian(int32_t i32) {
#define log_debug2(...) ;
//#define log_debug2(...) log_debug(__VA_ARGS__)
+static int decimal_digits(uint32_t n) {
+ static uint32_t digit_cutoff[9] = {
+ 10, 100, 1000, 10000, 100000,
+ 1000000, 10000000, 100000000, 1000000000
+ };
+ for (int i = 0; i < 9; ++i) {
+ if (n < digit_cutoff[i]) return i + 1;
+ }
+ return 10;
+}
+
struct ConstEvalAig
{
RTLIL::Module *module;
@@ -515,7 +526,7 @@ void AigerReader::parse_aiger_ascii()
unsigned l1, l2, l3;
// Parse inputs
- int digits = ceil(log10(I));
+ int digits = decimal_digits(I);
for (unsigned i = 1; i <= I; ++i, ++line_count) {
if (!(f >> l1))
log_error("Line %u cannot be interpreted as an input!\n", line_count);
@@ -537,7 +548,7 @@ void AigerReader::parse_aiger_ascii()
clk_wire->port_input = true;
clk_wire->port_output = false;
}
- digits = ceil(log10(L));
+ digits = decimal_digits(L);
for (unsigned i = 0; i < L; ++i, ++line_count) {
if (!(f >> l1 >> l2))
log_error("Line %u cannot be interpreted as a latch!\n", line_count);
@@ -575,7 +586,7 @@ void AigerReader::parse_aiger_ascii()
}
// Parse outputs
- digits = ceil(log10(O));
+ digits = decimal_digits(O);
for (unsigned i = 0; i < O; ++i, ++line_count) {
if (!(f >> l1))
log_error("Line %u cannot be interpreted as an output!\n", line_count);
@@ -643,7 +654,7 @@ void AigerReader::parse_aiger_binary()
std::string line;
// Parse inputs
- int digits = ceil(log10(I));
+ int digits = decimal_digits(I);
for (unsigned i = 1; i <= I; ++i) {
log_debug2("%d is an input\n", i);
RTLIL::Wire *wire = module->addWire(stringf("$i%0*d", digits, i));
@@ -662,7 +673,7 @@ void AigerReader::parse_aiger_binary()
clk_wire->port_input = true;
clk_wire->port_output = false;
}
- digits = ceil(log10(L));
+ digits = decimal_digits(L);
l1 = (I+1) * 2;
for (unsigned i = 0; i < L; ++i, ++line_count, l1 += 2) {
if (!(f >> l2))
@@ -700,7 +711,7 @@ void AigerReader::parse_aiger_binary()
}
// Parse outputs
- digits = ceil(log10(O));
+ digits = decimal_digits(O);
for (unsigned i = 0; i < O; ++i, ++line_count) {
if (!(f >> l1))
log_error("Line %u cannot be interpreted as an output!\n", line_count);
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 9520ae32c..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
@@ -287,8 +292,7 @@ void AstNode::dumpAst(FILE *f, std::string indent) const
}
std::string type_name = type2str(type);
- fprintf(f, "%s%s <%s:%d.%d-%d.%d>", indent.c_str(), type_name.c_str(), filename.c_str(), location.first_line,
- location.first_column, location.last_line, location.last_column);
+ fprintf(f, "%s%s <%s>", indent.c_str(), type_name.c_str(), loc_string().c_str());
if (!flag_no_dump_ptr) {
if (id2ast)
@@ -318,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)
@@ -336,6 +342,12 @@ void AstNode::dumpAst(FILE *f, std::string indent) const
fprintf(f, " %d", v);
fprintf(f, " ]");
}
+ if (!multirange_swapped.empty()) {
+ fprintf(f, " multirange_swapped=[");
+ for (auto v : multirange_swapped)
+ fprintf(f, " %d", v);
+ fprintf(f, " ]");
+ }
if (is_enum) {
fprintf(f, " type=enum");
}
@@ -542,9 +554,9 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
break;
case AST_CASE:
- if (!children.empty() && children[0]->type == AST_CONDX)
+ if (children.size() > 1 && children[1]->type == AST_CONDX)
fprintf(f, "%s" "casex (", indent.c_str());
- else if (!children.empty() && children[0]->type == AST_CONDZ)
+ else if (children.size() > 1 && children[1]->type == AST_CONDZ)
fprintf(f, "%s" "casez (", indent.c_str());
else
fprintf(f, "%s" "case (", indent.c_str());
@@ -842,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);
@@ -857,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;
@@ -953,8 +974,25 @@ RTLIL::Const AstNode::realAsConst(int width)
return result;
}
-// 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)
+std::string AstNode::loc_string() const
+{
+ return stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+}
+
+void AST::set_src_attr(RTLIL::AttrObject *obj, const AstNode *ast)
+{
+ obj->attributes[ID::src] = ast->loc_string();
+}
+
+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);
@@ -965,12 +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;
- current_module->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", ast->filename.c_str(), ast->location.first_line,
- ast->location.first_column, ast->location.last_line, ast->location.last_column);
- 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;
@@ -992,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) {
@@ -1009,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");
@@ -1106,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];
@@ -1134,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)
@@ -1188,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) {
@@ -1208,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);
+
+ 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 (defer)
- (*it)->str = "$abstract" + (*it)->str;
+ if (defer_local)
+ child->str = "$abstract" + child->str;
- if (design->has((*it)->str)) {
- RTLIL::Module *existing_mod = design->module((*it)->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:%d.%d-%d.%d.\n",
- (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->location.first_line, (*it)->location.first_column, (*it)->location.last_line, (*it)->location.last_column);
+ log("Ignoring re-definition of module `%s' at %s.\n",
+ child->str.c_str(), child->loc_string().c_str());
continue;
} else {
- log("Replacing existing%s module `%s' at %s:%d.%d-%d.%d.\n",
+ log("Replacing existing%s module `%s' at %s.\n",
existing_mod->get_bool_attribute(ID::blackbox) ? " blackbox" : "",
- (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->location.first_line, (*it)->location.first_column, (*it)->location.last_line, (*it)->location.last_column);
+ 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();
}
}
@@ -1337,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();
@@ -1400,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);
-
- // 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,
+ // 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);
- // 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
@@ -1472,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);
@@ -1505,6 +1633,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdStr
}
} else {
+ modname = new_modname;
log("Found cached RTLIL representation for module `%s'.\n", modname.c_str());
}
@@ -1522,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());
@@ -1532,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)
{
@@ -1540,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;
@@ -1551,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;
@@ -1604,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 9a5aa15f9..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 {
@@ -202,6 +203,7 @@ namespace AST
// if this is a multirange memory then this vector contains offset and length of each dimension
std::vector<int> multirange_dimensions;
+ std::vector<bool> multirange_swapped; // true if range is swapped, not used for structs
// this is set by simplify and used during RTLIL generation
AstNode *id2ast;
@@ -219,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();
@@ -249,9 +251,10 @@ namespace AST
// simplify() creates a simpler AST by unrolling for-loops, expanding generate blocks, etc.
// it also sets the id2ast pointers so that identifier lookups are fast in genRTLIL()
bool simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param);
+ void replace_result_wire_name_in_function(const std::string &from, const std::string &to);
AstNode *readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr, bool unconditional_init);
- void expand_genblock(std::string index_var, std::string prefix, std::map<std::string, std::string> &name_map);
- void replace_ids(const std::string &prefix, const std::map<std::string, std::string> &rules);
+ void expand_genblock(const std::string &prefix);
+ void label_genblks(std::set<std::string>& existing, int &counter);
void mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg_places,
dict<AstNode*, uint32_t> &mem2reg_flags, dict<AstNode*, uint32_t> &proc_flags, uint32_t &status_flags);
bool mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, AstNode *block, AstNode *&async_block);
@@ -259,19 +262,32 @@ 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 { RTLIL::Const val; int offset; bool is_signed; };
- bool has_const_only_constructs(bool &recommend_const_eval);
- void replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall);
- AstNode *eval_const_function(AstNode *fcall);
+ struct varinfo_t {
+ RTLIL::Const val;
+ int offset;
+ bool is_signed;
+ AstNode *arg = nullptr;
+ bool explicitly_sized;
+ };
+ bool has_const_only_constructs();
+ bool replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall, bool must_succeed);
+ AstNode *eval_const_function(AstNode *fcall, bool must_succeed);
bool is_simple_const_expr();
std::string process_format_str(const std::string &sformat, int next_arg, int stage, int width_hint, bool sign_hint);
+ bool is_recursive_function() const;
+ std::pair<AstNode*, AstNode*> get_tern_choice();
+
// create a human-readable text representation of the AST (for debugging)
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);
@@ -280,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;
@@ -298,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;
@@ -312,6 +328,12 @@ namespace AST
// helpers for enum
void allocateDefaultEnumValues();
void annotateTypedEnums(AstNode *template_node);
+
+ // 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
@@ -327,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;
};
@@ -350,6 +373,20 @@ namespace AST
std::pair<std::string,std::string> split_modport_from_type(std::string name_type);
AstNode * find_modport(AstNode *intf, std::string name);
void explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule, std::string intfname, AstNode *modport);
+
+ // 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
@@ -362,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 e241142d3..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
@@ -67,7 +67,7 @@ static ffi_fptr resolve_fn (std::string symbol_name)
AST::AstNode *AST::dpi_call(const std::string &rtype, const std::string &fname, const std::vector<std::string> &argtypes, const std::vector<AstNode*> &args)
{
AST::AstNode *newNode = nullptr;
- union { double f64; float f32; int32_t i32; } value_store [args.size() + 1];
+ union { double f64; float f32; int32_t i32; void *ptr; } value_store [args.size() + 1];
ffi_type *types [args.size() + 1];
void *values [args.size() + 1];
ffi_cif cif;
@@ -92,6 +92,11 @@ AST::AstNode *AST::dpi_call(const std::string &rtype, const std::string &fname,
value_store[i].i32 = args[i]->asInt(args[i]->is_signed);
values[i] = &value_store[i].i32;
types[i] = &ffi_type_sint32;
+ } else if (argtypes[i] == "chandle") {
+ log(" arg %d (%s): %llx\n", i, argtypes[i].c_str(), (unsigned long long)args[i]->asInt(false));
+ value_store[i].ptr = (void *)args[i]->asInt(args[i]->is_signed);
+ values[i] = &value_store[i].ptr;
+ types[i] = &ffi_type_pointer;
} else {
log_error("invalid argtype '%s' for argument %d.\n", argtypes[i].c_str(), i);
}
@@ -106,6 +111,9 @@ AST::AstNode *AST::dpi_call(const std::string &rtype, const std::string &fname,
} else if (rtype == "real") {
types[args.size()] = &ffi_type_double;
values[args.size()] = &value_store[args.size()].f64;
+ } else if (rtype == "chandle") {
+ types[args.size()] = &ffi_type_pointer;
+ values[args.size()] = &value_store[args.size()].ptr;
} else {
log_error("invalid rtype '%s'.\n", rtype.c_str());
}
@@ -123,6 +131,13 @@ AST::AstNode *AST::dpi_call(const std::string &rtype, const std::string &fname,
newNode = new AstNode(AST_REALVALUE);
newNode->realvalue = value_store[args.size()].f32;
log(" return realvalue: %g\n", newNode->asReal(true));
+ } else if (rtype == "chandle") {
+ uint64_t rawval = (uint64_t)value_store[args.size()].ptr;
+ std::vector<RTLIL::State> bits(64);
+ for (int i = 0; i < 64; i++)
+ bits.at(i) = (rawval & (1ULL << i)) ? RTLIL::State::S1 : RTLIL::State::S0;
+ newNode = AstNode::mkconst_bits(bits, false);
+ log(" return chandle: %llx\n", (unsigned long long)newNode->asInt(false));
} else {
newNode = AstNode::mkconst_int(value_store[args.size()].i32, false);
log(" return integer: %lld\n", (long long)newNode->asInt(true));
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc
index e878d0dd2..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>
@@ -45,10 +47,11 @@ static RTLIL::SigSpec uniop2rtlil(AstNode *that, IdString type, int result_width
{
IdString name = stringf("%s$%s:%d$%d", type.c_str(), that->filename.c_str(), that->location.first_line, autoidx++);
RTLIL::Cell *cell = current_module->addCell(name, type);
- cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column);
+ set_src_attr(cell, that);
RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", result_width);
- wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column);
+ set_src_attr(wire, that);
+ wire->is_signed = that->is_signed;
if (gen_attributes)
for (auto &attr : that->attributes) {
@@ -76,10 +79,11 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s
IdString name = stringf("$extend$%s:%d$%d", that->filename.c_str(), that->location.first_line, autoidx++);
RTLIL::Cell *cell = current_module->addCell(name, ID($pos));
- cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column);
+ set_src_attr(cell, that);
RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", width);
- wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column);
+ set_src_attr(wire, that);
+ wire->is_signed = that->is_signed;
if (that != NULL)
for (auto &attr : that->attributes) {
@@ -102,10 +106,11 @@ static RTLIL::SigSpec binop2rtlil(AstNode *that, IdString type, int result_width
{
IdString name = stringf("%s$%s:%d$%d", type.c_str(), that->filename.c_str(), that->location.first_line, autoidx++);
RTLIL::Cell *cell = current_module->addCell(name, type);
- cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column);
+ set_src_attr(cell, that);
RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", result_width);
- wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column);
+ set_src_attr(wire, that);
+ wire->is_signed = that->is_signed;
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
@@ -136,10 +141,11 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const
sstr << "$ternary$" << that->filename << ":" << that->location.first_line << "$" << (autoidx++);
RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($mux));
- cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column);
+ set_src_attr(cell, that);
RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", left.size());
- wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", that->filename.c_str(), that->location.first_line, that->location.first_column, that->location.last_line, that->location.last_column);
+ set_src_attr(wire, that);
+ wire->is_signed = that->is_signed;
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
@@ -315,16 +321,14 @@ struct AST_INTERNAL::ProcessGenerator
LookaheadRewriter la_rewriter(always);
// generate process and simple root case
- proc = new RTLIL::Process;
- proc->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", always->filename.c_str(), always->location.first_line, always->location.first_column, always->location.last_line, always->location.last_column);
- proc->name = stringf("$proc$%s:%d$%d", always->filename.c_str(), always->location.first_line, autoidx++);
+ proc = current_module->addProcess(stringf("$proc$%s:%d$%d", always->filename.c_str(), always->location.first_line, autoidx++));
+ set_src_attr(proc, always);
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
@@ -352,7 +356,7 @@ struct AST_INTERNAL::ProcessGenerator
if (found_anyedge_syncs) {
if (found_global_syncs)
log_file_error(always->filename, always->location.first_line, "Found non-synthesizable event list!\n");
- log("Note: Assuming pure combinatorial block at %s:%d.%d-%d.%d in\n", always->filename.c_str(), always->location.first_line, always->location.first_column, always->location.last_line, always->location.last_column);
+ log("Note: Assuming pure combinatorial block at %s in\n", always->loc_string().c_str());
log("compliance with IEC 62142(E):2005 / IEEE Std. 1364.1(E):2002. Recommending\n");
log("use of @* instead of @(...) for better match of synthesis and simulation.\n");
}
@@ -395,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;
@@ -452,7 +459,7 @@ struct AST_INTERNAL::ProcessGenerator
} while (current_module->wires_.count(wire_name) > 0);
RTLIL::Wire *wire = current_module->addWire(wire_name, chunk.width);
- wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", always->filename.c_str(), always->location.first_line, always->location.first_column, always->location.last_line, always->location.last_column);
+ set_src_attr(wire, always);
chunk.wire = wire;
chunk.offset = 0;
@@ -559,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++) {
@@ -586,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;
- sw->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", ast->filename.c_str(), ast->location.first_line, ast->location.first_column, ast->location.last_line, ast->location.last_column);
- sw->signal = ast->children[0]->genWidthRTLIL(-1, &subst_rvalue_map.stdmap());
+ set_src_attr(sw, ast);
+ 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) {
@@ -621,7 +632,7 @@ struct AST_INTERNAL::ProcessGenerator
RTLIL::CaseRule *backup_case = current_case;
current_case = new RTLIL::CaseRule;
- current_case->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", child->filename.c_str(), child->location.first_line, child->location.first_column, child->location.last_line, child->location.last_column);
+ set_src_attr(current_case, child);
last_generated_case = current_case;
addChunkActions(current_case->actions, this_case_eq_ltemp, this_case_eq_rvalue);
for (auto node : child->children) {
@@ -630,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);
@@ -694,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)
{
@@ -728,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) {
@@ -768,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) {
@@ -819,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;
@@ -919,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) {
@@ -940,12 +1088,53 @@ 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
+ // unelaborated, which currently only applies to calls to recursive
+ // functions reached by unevaluated ternary branches.
+ const AstNode *func = current_scope.at(str);
+ if (func->type != AST_FUNCTION)
+ log_file_error(filename, location.first_line, "Function call to %s resolved to something that isn't a function!\n", RTLIL::unescape_id(str).c_str());
+ const AstNode *wire = nullptr;
+ for (const AstNode *child : func->children)
+ if (child->str == func->str) {
+ wire = child;
+ break;
+ }
+ log_assert(wire && wire->type == AST_WIRE);
+ sign_hint = wire->is_signed;
+ width_hint = 1;
+ if (!wire->children.empty())
+ {
+ log_assert(wire->children.size() == 1);
+ const AstNode *range = wire->children.at(0);
+ log_assert(range->type == AST_RANGE && range->children.size() == 2);
+ AstNode *left = range->children.at(0)->clone();
+ AstNode *right = range->children.at(1)->clone();
+ while (left->simplify(true, false, false, 1, -1, false, true)) { }
+ while (right->simplify(true, false, false, 1, -1, false, true)) { }
+ if (left->type != AST_CONSTANT || right->type != AST_CONSTANT)
+ log_file_error(filename, location.first_line, "Function %s has non-constant width!",
+ RTLIL::unescape_id(str).c_str());
+ width_hint = abs(int(left->asInt(true) - right->asInt(true)));
+ delete left;
+ delete right;
+ }
+ break;
+ }
YS_FALLTHROUGH
// 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());
}
@@ -961,6 +1150,35 @@ 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,
+ const AstNode *node, const char *to_add_kind)
+{
+ auto already_exists = [&](const RTLIL::AttrObject *existing, const char *existing_kind) {
+ std::string src = existing->get_string_attribute(ID::src);
+ std::string location_str = "earlier";
+ if (!src.empty())
+ location_str = "at " + src;
+ log_file_error(node->filename, node->location.first_line,
+ "Cannot add %s `%s' because a %s with the same name was already created %s!\n",
+ to_add_kind, id.c_str(), existing_kind, location_str.c_str());
+ };
+
+ if (const RTLIL::Wire *wire = module->wire(id))
+ already_exists(wire, "signal");
+ if (const RTLIL::Cell *cell = module->cell(id))
+ already_exists(cell, "cell");
+ if (module->processes.count(id))
+ already_exists(module->processes.at(id), "process");
+ if (module->memories.count(id))
+ already_exists(module->memories.at(id), "memory");
}
// create RTLIL from an AST node
@@ -1008,8 +1226,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// If a port in a module with unknown type is found, mark it with the attribute 'is_interface'
// This is used by the hierarchy pass to know when it can replace interface connection with the individual
// signals.
- RTLIL::Wire *wire = current_module->addWire(str, 1);
- wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+ RTLIL::IdString id = str;
+ check_unique_id(current_module, id, this, "interface port");
+ RTLIL::Wire *wire = current_module->addWire(id, 1);
+ set_src_attr(wire, this);
wire->start_offset = 0;
wire->port_id = port_id;
wire->port_input = true;
@@ -1046,10 +1266,13 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
log_file_error(filename, location.first_line, "Parameter `%s' with non-constant value!\n", str.c_str());
RTLIL::Const val = children[0]->bitsAsConst();
- RTLIL::Wire *wire = current_module->addWire(str, GetSize(val));
+ RTLIL::IdString id = str;
+ check_unique_id(current_module, id, this, "pwire");
+ RTLIL::Wire *wire = current_module->addWire(id, GetSize(val));
current_module->connect(wire, val);
+ wire->is_signed = children[0]->is_signed;
- wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+ set_src_attr(wire, this);
wire->attributes[type == AST_PARAMETER ? ID::parameter : ID::localparam] = 1;
for (auto &attr : attributes) {
@@ -1062,16 +1285,16 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// create an RTLIL::Wire for an AST_WIRE node
case AST_WIRE: {
- if (current_module->wires_.count(str) != 0)
- log_file_error(filename, location.first_line, "Re-definition of signal `%s'!\n", str.c_str());
if (!range_valid)
log_file_error(filename, location.first_line, "Signal `%s' with non-constant width!\n", str.c_str());
if (!(range_left + 1 >= range_right))
log_file_error(filename, location.first_line, "Signal `%s' with invalid width range %d!\n", str.c_str(), range_left - range_right + 1);
- RTLIL::Wire *wire = current_module->addWire(str, range_left - range_right + 1);
- wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+ RTLIL::IdString id = str;
+ check_unique_id(current_module, id, this, "signal");
+ RTLIL::Wire *wire = current_module->addWire(id, range_left - range_right + 1);
+ set_src_attr(wire, this);
wire->start_offset = range_right;
wire->port_id = port_id;
wire->port_input = is_input;
@@ -1092,9 +1315,6 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// create an RTLIL::Memory for an AST_MEMORY node
case AST_MEMORY: {
- if (current_module->memories.count(str) != 0)
- log_file_error(filename, location.first_line, "Re-definition of memory `%s'!\n", str.c_str());
-
log_assert(children.size() >= 2);
log_assert(children[0]->type == AST_RANGE);
log_assert(children[1]->type == AST_RANGE);
@@ -1103,7 +1323,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
log_file_error(filename, location.first_line, "Memory `%s' with non-constant width or size!\n", str.c_str());
RTLIL::Memory *memory = new RTLIL::Memory;
- memory->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+ set_src_attr(memory, this);
memory->name = str;
memory->width = children[0]->range_left - children[0]->range_right + 1;
if (children[1]->range_right < children[1]->range_left) {
@@ -1113,6 +1333,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
memory->start_offset = children[1]->range_left;
memory->size = children[1]->range_right - children[1]->range_left + 1;
}
+ check_unique_id(current_module, memory->name, this, "memory");
current_module->memories[memory->name] = memory;
for (auto &attr : attributes) {
@@ -1160,9 +1381,17 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (id2ast->type == AST_AUTOWIRE && current_module->wires_.count(str) == 0) {
RTLIL::Wire *wire = current_module->addWire(str);
- wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+ 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());
@@ -1302,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;
}
@@ -1542,13 +1778,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
sstr << "$memrd$" << str << "$" << filename << ":" << location.first_line << "$" << (autoidx++);
RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($memrd));
- cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+ set_src_attr(cell, this);
RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_DATA", current_module->memories[str]->width);
- wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+ set_src_attr(wire, this);
int mem_width, mem_size, addr_bits;
is_signed = id2ast->is_signed;
+ wire->is_signed = is_signed;
id2ast->meminfo(mem_width, mem_size, addr_bits);
RTLIL::SigSpec addr_sig = children[0]->genRTLIL();
@@ -1572,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));
- cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+ 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;
@@ -1643,8 +1872,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
else
cellname = str;
+ check_unique_id(current_module, cellname, this, "procedural assertion");
RTLIL::Cell *cell = current_module->addCell(cellname, celltype);
- cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+ set_src_attr(cell, this);
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
@@ -1661,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++)
@@ -1685,11 +1915,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
{
int port_counter = 0, para_counter = 0;
- if (current_module->count_id(str) != 0)
- log_file_error(filename, location.first_line, "Re-definition of cell `%s'!\n", str.c_str());
-
- RTLIL::Cell *cell = current_module->addCell(str, "");
- cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+ RTLIL::IdString id = str;
+ check_unique_id(current_module, id, this, "cell");
+ RTLIL::Cell *cell = current_module->addCell(id, "");
+ set_src_attr(cell, this);
// Set attribute 'module_not_derived' which will be cleared again after the hierarchy pass
cell->set_bool_attribute(ID::module_not_derived);
@@ -1702,27 +1931,47 @@ 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) {
RTLIL::SigSpec sig;
- if (child->children.size() > 0)
- sig = child->children[0]->genRTLIL();
+ if (child->children.size() > 0) {
+ AstNode *arg = child->children[0];
+ int local_width_hint = -1;
+ bool local_sign_hint = false;
+ // don't inadvertently attempt to detect the width of interfaces
+ if (arg->type != AST_IDENTIFIER || !arg->id2ast || arg->id2ast->type != AST_CELL)
+ arg->detectSignWidth(local_width_hint, local_sign_hint);
+ sig = arg->genRTLIL(local_width_hint, local_sign_hint);
+ log_assert(local_sign_hint == arg->is_signed);
+ if (sig.is_wire()) {
+ // if the resulting SigSpec is a wire, its
+ // signedness should match that of the AstNode
+ 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
+ RTLIL::IdString wire_name = NEW_ID;
+ RTLIL::Wire *wire = current_module->addWire(wire_name, GetSize(sig));
+ wire->is_signed = true;
+ current_module->connect(wire, sig);
+ sig = wire;
+ }
+ }
if (child->str.size() == 0) {
char buf[100];
snprintf(buf, 100, "$%d", ++port_counter);
@@ -1811,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")
{
@@ -1832,7 +2088,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
log_file_error(filename, location.first_line, "Failed to detect width of %s!\n", RTLIL::unescape_id(str).c_str());
Cell *cell = current_module->addCell(myid, str.substr(1));
- cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+ set_src_attr(cell, this);
cell->parameters[ID::WIDTH] = width;
if (attributes.count(ID::reg)) {
@@ -1843,7 +2099,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
}
Wire *wire = current_module->addWire(myid + "_wire", width);
- wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+ set_src_attr(wire, this);
cell->setPort(ID::Y, wire);
is_signed = sign_hint;
@@ -1856,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();
@@ -1866,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 c4df5c0a0..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
@@ -89,7 +89,7 @@ std::string AstNode::process_format_str(const std::string &sformat, int next_arg
case 'S':
case 'd':
case 'D':
- if (got_len)
+ if (got_len && len_value != 0)
goto unsupported_format;
YS_FALLTHROUGH
case 'x':
@@ -110,6 +110,12 @@ std::string AstNode::process_format_str(const std::string &sformat, int next_arg
goto unsupported_format;
break;
+ case 'l':
+ case 'L':
+ if (got_len)
+ goto unsupported_format;
+ break;
+
default:
unsupported_format:
log_file_error(filename, location.first_line, "System task `%s' called with invalid/unsupported format specifier.\n", str.c_str());
@@ -155,6 +161,11 @@ std::string AstNode::process_format_str(const std::string &sformat, int next_arg
sout += log_id(current_module->name);
break;
+ case 'l':
+ case 'L':
+ sout += log_id(current_module->name);
+ break;
+
default:
log_abort();
}
@@ -181,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];
@@ -319,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) {
@@ -333,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) {
@@ -380,32 +396,67 @@ static int size_packed_struct(AstNode *snode, int base_offset)
static AstNode *node_int(int ival)
{
- // maybe mkconst_int should have default values for the common integer case
- return AstNode::mkconst_int(ival, true, 32);
+ return AstNode::mkconst_int(ival, true);
}
-static AstNode *offset_indexed_range(int offset_right, int stride, AstNode *left_expr, AstNode *right_expr)
+static AstNode *multiply_by_const(AstNode *expr_node, int stride)
+{
+ return new AstNode(AST_MUL, expr_node, node_int(stride));
+}
+
+static AstNode *offset_indexed_range(int offset, int stride, AstNode *left_expr, AstNode *right_expr)
{
// adjust the range expressions to add an offset into the struct
// and maybe index using an array stride
auto left = left_expr->clone();
auto right = right_expr->clone();
- if (stride == 1) {
- // just add the offset
- left = new AstNode(AST_ADD, node_int(offset_right), left);
- right = new AstNode(AST_ADD, node_int(offset_right), right);
+ if (stride > 1) {
+ // newleft = (left + 1) * stride - 1
+ left = new AstNode(AST_SUB, multiply_by_const(new AstNode(AST_ADD, left, node_int(1)), stride), node_int(1));
+ // newright = right * stride
+ right = multiply_by_const(right, stride);
+ }
+ // add the offset
+ if (offset) {
+ left = new AstNode(AST_ADD, node_int(offset), left);
+ right = new AstNode(AST_ADD, node_int(offset), right);
+ }
+ return new AstNode(AST_RANGE, left, right);
+}
+
+static AstNode *make_struct_index_range(AstNode *node, AstNode *rnode, int stride, int offset)
+{
+ // generate a range node to perform either bit or array indexing
+ if (rnode->children.size() == 1) {
+ // index e.g. s.a[i]
+ return offset_indexed_range(offset, stride, rnode->children[0], rnode->children[0]);
+ }
+ else if (rnode->children.size() == 2) {
+ // slice e.g. s.a[i:j]
+ return offset_indexed_range(offset, stride, rnode->children[0], rnode->children[1]);
}
else {
- // newleft = offset_right - 1 + (left + 1) * stride
- left = new AstNode(AST_ADD, new AstNode(AST_SUB, node_int(offset_right), node_int(1)),
- new AstNode(AST_MUL, node_int(stride), new AstNode(AST_ADD, left, node_int(1))));
- // newright = offset_right + right * stride
- right = new AstNode(AST_ADD, node_int(offset_right), new AstNode(AST_MUL, right, node_int(stride)));
+ struct_op_error(node);
}
+}
+
+static AstNode *slice_range(AstNode *rnode, AstNode *snode)
+{
+ // apply the bit slice indicated by snode to the range rnode
+ log_assert(rnode->type==AST_RANGE);
+ auto left = rnode->children[0];
+ auto right = rnode->children[1];
+ log_assert(snode->type==AST_RANGE);
+ auto slice_left = snode->children[0];
+ auto slice_right = snode->children[1];
+ auto width = new AstNode(AST_SUB, slice_left->clone(), slice_right->clone());
+ right = new AstNode(AST_ADD, right->clone(), slice_right->clone());
+ left = new AstNode(AST_ADD, right->clone(), width);
return new AstNode(AST_RANGE, left, right);
}
-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
@@ -414,27 +465,26 @@ static AstNode *make_struct_member_range(AstNode *node, AstNode *member_node)
int range_right = member_node->range_right;
if (node->children.empty()) {
// no range operations apply, return the whole width
+ return make_range(range_left, range_right);
}
- else if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) {
- auto rnode = node->children[0];
- int stride = get_struct_array_width(member_node);
- if (rnode->children.size() == 1) {
- // index e.g. s.a[i]
- return offset_indexed_range(range_right, stride, rnode->children[0], rnode->children[0]);
- }
- else if (rnode->children.size() == 2) {
- // slice e.g. s.a[i:j]
- return offset_indexed_range(range_right, stride, rnode->children[0], rnode->children[1]);
- }
- else {
- struct_op_error(node);
- }
+ int stride = get_struct_array_width(member_node);
+ if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) {
+ // bit or array indexing e.g. s.a[2] or s.a[1:0]
+ return make_struct_index_range(node, node->children[0], stride, range_right);
+ }
+ else if (node->children.size() == 1 && node->children[0]->type == AST_MULTIRANGE) {
+ // multirange, i.e. bit slice after array index, e.g. s.a[i][p:q]
+ log_assert(stride > 1);
+ auto mrnode = node->children[0];
+ auto element_range = make_struct_index_range(node, mrnode->children[0], stride, range_right);
+ // then apply bit slice range
+ auto range = slice_range(element_range, mrnode->children[1]);
+ delete element_range;
+ return range;
}
else {
- // TODO multirange, i.e. bit slice after array index s.a[i][p:q]
struct_op_error(node);
}
- return make_range(range_left, range_right);
}
static void add_members_to_scope(AstNode *snode, std::string name)
@@ -483,6 +533,258 @@ static AstNode *make_packed_struct(AstNode *template_node, std::string &name)
return wnode;
}
+// check if a node or its children contains an assignment to the given variable
+static bool node_contains_assignment_to(const AstNode* node, const AstNode* var)
+{
+ if (node->type == AST_ASSIGN_EQ || node->type == AST_ASSIGN_LE) {
+ // current node is iteslf an assignment
+ log_assert(node->children.size() >= 2);
+ const AstNode* lhs = node->children[0];
+ if (lhs->type == AST_IDENTIFIER && lhs->str == var->str)
+ return false;
+ }
+ for (const AstNode* child : node->children) {
+ // if this child shadows the given variable
+ if (child != var && child->str == var->str && child->type == AST_WIRE)
+ break; // skip the remainder of this block/scope
+ // depth-first short circuit
+ if (!node_contains_assignment_to(child, var))
+ return false;
+ }
+ return true;
+}
+
+static std::string prefix_id(const std::string &prefix, const std::string &str)
+{
+ log_assert(!prefix.empty() && (prefix.front() == '$' || prefix.front() == '\\'));
+ log_assert(!str.empty() && (str.front() == '$' || str.front() == '\\'));
+ log_assert(prefix.back() == '.');
+ if (str.front() == '\\')
+ return prefix + str.substr(1);
+ 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().
@@ -495,10 +797,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
static bool deep_recursion_warning = false;
if (recursion_counter++ == 1000 && deep_recursion_warning) {
- log_warning("Deep recursion in AST simplifier.\nDoes this design contain insanely long expressions?\n");
+ log_warning("Deep recursion in AST simplifier.\nDoes this design contain overly long or deeply nested expressions, or excessive recursion?\n");
deep_recursion_warning = false;
}
+ static bool unevaluated_tern_branch = false;
+
AstNode *newNode = NULL;
bool did_something = false;
@@ -682,6 +986,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
// also merge multiple declarations for the same wire (e.g. "output foobar; reg foobar;")
if (type == AST_MODULE) {
current_scope.clear();
+ std::set<std::string> existing;
+ int counter = 0;
+ label_genblks(existing, counter);
std::map<std::string, AstNode*> this_wire_scope;
for (size_t i = 0; i < children.size(); i++) {
AstNode *node = children[i];
@@ -785,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
@@ -793,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) {
@@ -834,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;
@@ -862,7 +1281,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && children[0]->id2ast->is_logic)
children[0]->id2ast->is_reg = true; // if logic type is used in a block asignment
if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && !children[0]->id2ast->is_reg)
- log_warning("wire '%s' is assigned in a block at %s:%d.%d-%d.%d.\n", children[0]->str.c_str(), filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+ log_warning("wire '%s' is assigned in a block at %s.\n", children[0]->str.c_str(), loc_string().c_str());
if (type == AST_ASSIGN && children[0]->id2ast->is_reg) {
bool is_rand_reg = false;
if (children[1]->type == AST_FCALL) {
@@ -876,7 +1295,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
is_rand_reg = true;
}
if (!is_rand_reg)
- log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.%d-%d.%d.\n", children[0]->str.c_str(), filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
+ log_warning("reg '%s' is assigned in a continuous assignment at %s.\n", children[0]->str.c_str(), loc_string().c_str());
}
children[0]->was_checked = true;
}
@@ -1012,7 +1431,6 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
break;
case AST_TERNARY:
- detect_width_simple = true;
child_0_is_self_determined = true;
break;
@@ -1045,6 +1463,24 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
detectSignWidth(width_hint, sign_hint);
if (type == AST_TERNARY) {
+ if (width_hint < 0) {
+ while (!children[0]->basic_prep && children[0]->simplify(true, false, in_lvalue, stage, -1, false, in_param))
+ did_something = true;
+
+ bool backup_unevaluated_tern_branch = unevaluated_tern_branch;
+ AstNode *chosen = get_tern_choice().first;
+
+ unevaluated_tern_branch = backup_unevaluated_tern_branch || chosen == children[2];
+ while (!children[1]->basic_prep && children[1]->simplify(false, false, in_lvalue, stage, -1, false, in_param))
+ did_something = true;
+
+ unevaluated_tern_branch = backup_unevaluated_tern_branch || chosen == children[1];
+ while (!children[2]->basic_prep && children[2]->simplify(false, false, in_lvalue, stage, -1, false, in_param))
+ did_something = true;
+
+ unevaluated_tern_branch = backup_unevaluated_tern_branch;
+ detectSignWidth(width_hint, sign_hint);
+ }
int width_hint_left, width_hint_right;
bool sign_hint_left, sign_hint_right;
bool found_real_left, found_real_right;
@@ -1070,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++) {
@@ -1084,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;
@@ -1103,11 +1544,20 @@ 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++) {
bool did_something_here = true;
bool backup_flag_autowire = flag_autowire;
+ bool backup_unevaluated_tern_branch = unevaluated_tern_branch;
if ((type == AST_GENFOR || type == AST_FOR) && i >= 3)
break;
if ((type == AST_GENIF || type == AST_GENCASE) && i >= 1)
@@ -1120,6 +1570,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
break;
if (type == AST_DEFPARAM && i == 0)
flag_autowire = true;
+ if (type == AST_TERNARY && i > 0 && !unevaluated_tern_branch) {
+ AstNode *chosen = get_tern_choice().first;
+ unevaluated_tern_branch = chosen && chosen != children[i];
+ }
while (did_something_here && i < children.size()) {
bool const_fold_here = const_fold, in_lvalue_here = in_lvalue;
int width_hint_here = width_hint;
@@ -1159,11 +1613,26 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
did_something = true;
}
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;
@@ -1259,6 +1728,10 @@ 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;
current_scope[str] = this;
goto apply_newNode;
}
@@ -1304,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());
@@ -1438,11 +1926,13 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
{
int total_size = 1;
multirange_dimensions.clear();
+ multirange_swapped.clear();
for (auto range : children[1]->children) {
if (!range->range_valid)
log_file_error(filename, location.first_line, "Non-constant range on memory decl.\n");
multirange_dimensions.push_back(min(range->range_left, range->range_right));
multirange_dimensions.push_back(max(range->range_left, range->range_right) - min(range->range_left, range->range_right) + 1);
+ multirange_swapped.push_back(range->range_swapped);
total_size *= multirange_dimensions.back();
}
delete children[1];
@@ -1455,9 +1945,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
{
AstNode *index_expr = nullptr;
+ integer = children[0]->children.size(); // save original number of dimensions for $size() etc.
for (int i = 0; 2*i < GetSize(id2ast->multirange_dimensions); i++)
{
- if (GetSize(children[0]->children) < i)
+ if (GetSize(children[0]->children) <= i)
log_file_error(filename, location.first_line, "Insufficient number of array indices for %s.\n", log_id(str));
AstNode *new_index_expr = children[0]->children[i]->children.at(0)->clone();
@@ -1533,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;
}
}
@@ -1542,6 +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;
+ 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) {
@@ -1595,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");
@@ -1646,6 +2140,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
newNode = new AstNode(AST_IDENTIFIER, children[1]->clone());
newNode->str = wire_id;
+ newNode->integer = integer; // save original number of dimensions for $size() etc.
newNode->id2ast = wire;
goto apply_newNode;
}
@@ -1687,25 +2182,27 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
body_ast->children.size() == 1 && body_ast->children.at(0)->type == AST_GENBLOCK)
body_ast = body_ast->children.at(0);
+ const char* loop_type_str = "procedural";
+ const char* var_type_str = "register";
+ AstNodeType var_type = AST_WIRE;
+ if (type == AST_GENFOR) {
+ loop_type_str = "generate";
+ var_type_str = "genvar";
+ var_type = AST_GENVAR;
+ }
+
if (init_ast->type != AST_ASSIGN_EQ)
- log_file_error(filename, location.first_line, "Unsupported 1st expression of generate for-loop!\n");
+ log_file_error(filename, location.first_line, "Unsupported 1st expression of %s for-loop!\n", loop_type_str);
if (next_ast->type != AST_ASSIGN_EQ)
- log_file_error(filename, location.first_line, "Unsupported 3rd expression of generate for-loop!\n");
+ log_file_error(filename, location.first_line, "Unsupported 3rd expression of %s for-loop!\n", loop_type_str);
- if (type == AST_GENFOR) {
- if (init_ast->children[0]->id2ast == NULL || init_ast->children[0]->id2ast->type != AST_GENVAR)
- log_file_error(filename, location.first_line, "Left hand side of 1st expression of generate for-loop is not a gen var!\n");
- if (next_ast->children[0]->id2ast == NULL || next_ast->children[0]->id2ast->type != AST_GENVAR)
- log_file_error(filename, location.first_line, "Left hand side of 3rd expression of generate for-loop is not a gen var!\n");
- } else {
- if (init_ast->children[0]->id2ast == NULL || init_ast->children[0]->id2ast->type != AST_WIRE)
- log_file_error(filename, location.first_line, "Left hand side of 1st expression of generate for-loop is not a register!\n");
- if (next_ast->children[0]->id2ast == NULL || next_ast->children[0]->id2ast->type != AST_WIRE)
- log_file_error(filename, location.first_line, "Left hand side of 3rd expression of generate for-loop is not a register!\n");
- }
+ if (init_ast->children[0]->id2ast == NULL || init_ast->children[0]->id2ast->type != var_type)
+ log_file_error(filename, location.first_line, "Left hand side of 1st expression of %s for-loop is not a %s!\n", loop_type_str, var_type_str);
+ if (next_ast->children[0]->id2ast == NULL || next_ast->children[0]->id2ast->type != var_type)
+ log_file_error(filename, location.first_line, "Left hand side of 3rd expression of %s for-loop is not a %s!\n", loop_type_str, var_type_str);
if (init_ast->children[0]->id2ast != next_ast->children[0]->id2ast)
- log_file_error(filename, location.first_line, "Incompatible left-hand sides in 1st and 3rd expression of generate for-loop!\n");
+ log_file_error(filename, location.first_line, "Incompatible left-hand sides in 1st and 3rd expression of %s for-loop!\n", loop_type_str);
// eval 1st expression
AstNode *varbuf = init_ast->children[1]->clone();
@@ -1717,7 +2214,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
if (varbuf->type != AST_CONSTANT)
- log_file_error(filename, location.first_line, "Right hand side of 1st expression of generate for-loop is not constant!\n");
+ log_file_error(filename, location.first_line, "Right hand side of 1st expression of %s for-loop is not constant!\n", loop_type_str);
auto resolved = current_scope.at(init_ast->children[0]->str);
if (resolved->range_valid) {
@@ -1758,7 +2255,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
if (buf->type != AST_CONSTANT)
- log_file_error(filename, location.first_line, "2nd expression of generate for-loop is not constant!\n");
+ log_file_error(filename, location.first_line, "2nd expression of %s for-loop is not constant!\n", loop_type_str);
if (buf->integer == 0) {
delete buf;
@@ -1768,23 +2265,28 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
// expand body
int index = varbuf->children[0]->integer;
- if (body_ast->type == AST_GENBLOCK)
- buf = body_ast->clone();
- else
- buf = new AstNode(AST_GENBLOCK, body_ast->clone());
- if (buf->str.empty()) {
- std::stringstream sstr;
- sstr << "$genblock$" << filename << ":" << location.first_line << "$" << (autoidx++);
- buf->str = sstr.str();
- }
- std::map<std::string, std::string> name_map;
+ log_assert(body_ast->type == AST_GENBLOCK || body_ast->type == AST_BLOCK);
+ log_assert(!body_ast->str.empty());
+ buf = body_ast->clone();
+
std::stringstream sstr;
sstr << buf->str << "[" << index << "].";
- buf->expand_genblock(varbuf->str, sstr.str(), name_map);
+ std::string prefix = sstr.str();
+
+ // create a scoped localparam for the current value of the loop variable
+ AstNode *local_index = varbuf->clone();
+ size_t pos = local_index->str.rfind('.');
+ if (pos != std::string::npos) // remove outer prefix
+ local_index->str = "\\" + local_index->str.substr(pos + 1);
+ local_index->str = prefix_id(prefix, local_index->str);
+ current_scope[local_index->str] = local_index;
+ current_ast_mod->children.push_back(local_index);
+
+ buf->expand_genblock(prefix);
if (type == AST_GENFOR) {
for (size_t i = 0; i < buf->children.size(); i++) {
- buf->children[i]->simplify(false, false, false, stage, -1, false, false);
+ buf->children[i]->simplify(const_fold, false, false, stage, -1, false, false);
current_ast_mod->children.push_back(buf->children[i]);
}
} else {
@@ -1804,7 +2306,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
if (buf->type != AST_CONSTANT)
- log_file_error(filename, location.first_line, "Right hand side of 3rd expression of generate for-loop is not constant (%s)!\n", type2str(buf->type).c_str());
+ log_file_error(filename, location.first_line, "Right hand side of 3rd expression of %s for-loop is not constant (%s)!\n", loop_type_str, type2str(buf->type).c_str());
delete varbuf->children[0];
varbuf->children[0] = buf;
@@ -1828,14 +2330,26 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
{
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)
- log_file_error(children[i]->filename, children[i]->location.first_line, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n");
+ {
+ log_assert(!VERILOG_FRONTEND::sv_mode);
+ log_file_error(children[i]->filename, children[i]->location.first_line, "Local declaration in unnamed block is only supported in SystemVerilog mode!\n");
+ }
}
// transform block with name
if (type == AST_BLOCK && !str.empty())
{
- std::map<std::string, std::string> name_map;
- expand_genblock(std::string(), str + ".", name_map);
+ 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++)
@@ -1855,12 +2369,11 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_GENBLOCK && children.size() != 0)
{
if (!str.empty()) {
- std::map<std::string, std::string> name_map;
- expand_genblock(std::string(), str + ".", name_map);
+ expand_genblock(str + ".");
}
for (size_t i = 0; i < children.size(); i++) {
- children[i]->simplify(false, false, false, stage, -1, false, false);
+ children[i]->simplify(const_fold, false, false, stage, -1, false, false);
current_ast_mod->children.push_back(children[i]);
}
@@ -1892,12 +2405,11 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
buf = new AstNode(AST_GENBLOCK, buf);
if (!buf->str.empty()) {
- std::map<std::string, std::string> name_map;
- buf->expand_genblock(std::string(), buf->str + ".", name_map);
+ buf->expand_genblock(buf->str + ".");
}
for (size_t i = 0; i < buf->children.size(); i++) {
- buf->children[i]->simplify(false, false, false, stage, -1, false, false);
+ buf->children[i]->simplify(const_fold, false, false, stage, -1, false, false);
current_ast_mod->children.push_back(buf->children[i]);
}
@@ -1971,12 +2483,11 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
buf = selected_case->clone();
if (!buf->str.empty()) {
- std::map<std::string, std::string> name_map;
- buf->expand_genblock(std::string(), buf->str + ".", name_map);
+ buf->expand_genblock(buf->str + ".");
}
for (size_t i = 0; i < buf->children.size(); i++) {
- buf->children[i]->simplify(false, false, false, stage, -1, false, false);
+ buf->children[i]->simplify(const_fold, false, false, stage, -1, false, false);
current_ast_mod->children.push_back(buf->children[i]);
}
@@ -2056,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;
@@ -2073,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];
@@ -2128,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;
@@ -2430,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);
@@ -2456,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);
@@ -2465,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);
@@ -2502,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
{
@@ -2531,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;
@@ -2553,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;
@@ -2756,26 +3287,28 @@ skip_dynamic_range_lvalue_expansion:;
goto apply_newNode;
}
- if (str == "\\$size" || str == "\\$bits")
+ if (str == "\\$size" || str == "\\$bits" || str == "\\$high" || str == "\\$low" || str == "\\$left" || str == "\\$right")
{
- if (str == "\\$bits" && children.size() != 1)
- log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()));
-
- if (str == "\\$size" && children.size() != 1 && children.size() != 2)
- log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1 or 2.\n",
- RTLIL::unescape_id(str).c_str(), int(children.size()));
-
int dim = 1;
- if (str == "\\$size" && children.size() == 2) {
- AstNode *buf = children[1]->clone();
- // Evaluate constant expression
- while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
- dim = buf->asInt(false);
- delete buf;
+ if (str == "\\$bits") {
+ if (children.size() != 1)
+ log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1.\n",
+ RTLIL::unescape_id(str).c_str(), int(children.size()));
+ } else {
+ if (children.size() != 1 && children.size() != 2)
+ log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1 or 2.\n",
+ RTLIL::unescape_id(str).c_str(), int(children.size()));
+ if (children.size() == 2) {
+ AstNode *buf = children[1]->clone();
+ // Evaluate constant expression
+ while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
+ dim = buf->asInt(false);
+ delete buf;
+ }
}
AstNode *buf = children[0]->clone();
int mem_depth = 1;
+ int result, high = 0, low = 0, left = 0, right = 0, width = 1; // defaults for a simple wire
AstNode *id_ast = NULL;
// Is this needed?
@@ -2788,6 +3321,31 @@ skip_dynamic_range_lvalue_expansion:;
id_ast = current_scope.at(buf->str);
if (!id_ast)
log_file_error(filename, location.first_line, "Failed to resolve identifier %s for width detection!\n", buf->str.c_str());
+ // a slice of our identifier means we advance to the next dimension, e.g. $size(a[3])
+ if (buf->children.size() > 0) {
+ // something is hanging below this identifier
+ if (buf->children[0]->type == AST_RANGE && buf->integer == 0)
+ // if integer == 0, this node was originally created as AST_RANGE so it's dimension is 1
+ dim++;
+ // more than one range, e.g. $size(a[3][2])
+ else // created an AST_MULTIRANGE, converted to AST_RANGE, but original dimension saved in 'integer' field
+ dim += buf->integer; // increment by multirange size
+ }
+ // We have 4 cases:
+ // wire x; ==> AST_WIRE, no AST_RANGE children
+ // wire [1:0]x; ==> AST_WIRE, AST_RANGE children
+ // wire [1:0]x[1:0]; ==> AST_MEMORY, two AST_RANGE children (1st for packed, 2nd for unpacked)
+ // wire [1:0]x[1:0][1:0]; ==> AST_MEMORY, one AST_RANGE child (0) for packed, then AST_MULTIRANGE child (1) for unpacked
+ // (updated: actually by the time we are here, AST_MULTIRANGE is converted into one big AST_RANGE)
+ // case 0 handled by default
+ if ((id_ast->type == AST_WIRE || id_ast->type == AST_MEMORY) && id_ast->children.size() > 0) {
+ // handle packed array left/right for case 1, and cases 2/3 when requesting the last dimension (packed side)
+ AstNode *wire_range = id_ast->children[0];
+ left = wire_range->children[0]->integer;
+ right = wire_range->children[1]->integer;
+ high = max(left, right);
+ low = min(left, right);
+ }
if (id_ast->type == AST_MEMORY) {
// We got here only if the argument is a memory
// Otherwise $size() and $bits() return the expression width
@@ -2800,29 +3358,58 @@ skip_dynamic_range_lvalue_expansion:;
} else
log_file_error(filename, location.first_line, "Unknown memory depth AST type in `%s'!\n", buf->str.c_str());
} else {
- // $size()
+ // $size(), $left(), $right(), $high(), $low()
+ int dims = 1;
if (mem_range->type == AST_RANGE) {
- if (!mem_range->range_valid)
- log_file_error(filename, location.first_line, "Failed to detect width of memory access `%s'!\n", buf->str.c_str());
- int dims;
- if (id_ast->multirange_dimensions.empty())
- dims = 1;
- else
+ if (id_ast->multirange_dimensions.empty()) {
+ if (!mem_range->range_valid)
+ log_file_error(filename, location.first_line, "Failed to detect width of memory access `%s'!\n", buf->str.c_str());
+ if (dim == 1) {
+ left = mem_range->range_right;
+ right = mem_range->range_left;
+ high = max(left, right);
+ low = min(left, right);
+ }
+ } else {
dims = GetSize(id_ast->multirange_dimensions)/2;
- if (dim == 1)
- width_hint = (dims > 1) ? id_ast->multirange_dimensions[1] : (mem_range->range_left - mem_range->range_right + 1);
- else if (dim <= dims) {
- width_hint = id_ast->multirange_dimensions[2*dim-1];
- } else if ((dim > dims+1) || (dim < 0))
- log_file_error(filename, location.first_line, "Dimension %d out of range in `%s', as it only has dimensions 1..%d!\n", dim, buf->str.c_str(), dims+1);
- } else
+ if (dim <= dims) {
+ width_hint = id_ast->multirange_dimensions[2*dim-1];
+ high = id_ast->multirange_dimensions[2*dim-2] + id_ast->multirange_dimensions[2*dim-1] - 1;
+ low = id_ast->multirange_dimensions[2*dim-2];
+ if (id_ast->multirange_swapped[dim-1]) {
+ left = low;
+ right = high;
+ } else {
+ right = low;
+ left = high;
+ }
+ } else if ((dim > dims+1) || (dim < 0))
+ log_file_error(filename, location.first_line, "Dimension %d out of range in `%s', as it only has dimensions 1..%d!\n", dim, buf->str.c_str(), dims+1);
+ }
+ } else {
log_file_error(filename, location.first_line, "Unknown memory depth AST type in `%s'!\n", buf->str.c_str());
+ }
}
}
+ width = high - low + 1;
+ } else {
+ width = width_hint;
}
delete buf;
-
- newNode = mkconst_int(width_hint * mem_depth, false);
+ if (str == "\\$high")
+ result = high;
+ else if (str == "\\$low")
+ result = low;
+ else if (str == "\\$left")
+ result = left;
+ else if (str == "\\$right")
+ result = right;
+ else if (str == "\\$size")
+ result = width;
+ else {
+ result = width * mem_depth;
+ }
+ newNode = mkconst_int(result, false);
goto apply_newNode;
}
@@ -2909,6 +3496,93 @@ skip_dynamic_range_lvalue_expansion:;
goto apply_newNode;
}
+ if (str == "\\$countbits") {
+ if (children.size() < 2)
+ log_file_error(filename, location.first_line, "System function %s got %d arguments, expected at least 2.\n",
+ RTLIL::unescape_id(str).c_str(), int(children.size()));
+
+ std::vector<RTLIL::State> control_bits;
+
+ // Determine which bits to count
+ for (size_t i = 1; i < children.size(); i++) {
+ AstNode *node = children[i];
+ while (node->simplify(true, false, false, stage, -1, false, false)) { }
+ if (node->type != AST_CONSTANT)
+ log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with non-constant control bit argument.\n", str.c_str());
+ if (node->bits.size() != 1)
+ log_file_error(filename, location.first_line, "Failed to evaluate system function `%s' with control bit width != 1.\n", str.c_str());
+ control_bits.push_back(node->bits[0]);
+ }
+
+ // Detect width of exp (first argument of $countbits)
+ int exp_width = -1;
+ bool exp_sign = false;
+ AstNode *exp = children[0];
+ exp->detectSignWidth(exp_width, exp_sign, NULL);
+
+ newNode = mkconst_int(0, false);
+
+ for (int i = 0; i < exp_width; i++) {
+ // Generate nodes for: exp << i >> ($size(exp) - 1)
+ // ^^ ^^
+ AstNode *lsh_node = new AstNode(AST_SHIFT_LEFT, exp->clone(), mkconst_int(i, false));
+ AstNode *rsh_node = new AstNode(AST_SHIFT_RIGHT, lsh_node, mkconst_int(exp_width - 1, false));
+
+ AstNode *or_node = nullptr;
+
+ for (RTLIL::State control_bit : control_bits) {
+ // Generate node for: (exp << i >> ($size(exp) - 1)) === control_bit
+ // ^^^
+ AstNode *eq_node = new AstNode(AST_EQX, rsh_node->clone(), mkconst_bits({control_bit}, false));
+
+ // Or the result for each checked bit value
+ if (or_node)
+ or_node = new AstNode(AST_LOGIC_OR, or_node, eq_node);
+ else
+ or_node = eq_node;
+ }
+
+ // We should have at least one element in control_bits,
+ // because we checked for the number of arguments above
+ log_assert(or_node != nullptr);
+
+ delete rsh_node;
+
+ // Generate node for adding with result of previous bit
+ newNode = new AstNode(AST_ADD, newNode, or_node);
+ }
+
+ goto apply_newNode;
+ }
+
+ if (str == "\\$countones" || str == "\\$isunknown" || str == "\\$onehot" || str == "\\$onehot0") {
+ if (children.size() != 1)
+ log_file_error(filename, location.first_line, "System function %s got %d arguments, expected 1.\n",
+ RTLIL::unescape_id(str).c_str(), int(children.size()));
+
+ AstNode *countbits = clone();
+ countbits->str = "\\$countbits";
+
+ if (str == "\\$countones") {
+ countbits->children.push_back(mkconst_bits({RTLIL::State::S1}, false));
+ newNode = countbits;
+ } else if (str == "\\$isunknown") {
+ countbits->children.push_back(mkconst_bits({RTLIL::Sx}, false));
+ countbits->children.push_back(mkconst_bits({RTLIL::Sz}, false));
+ newNode = new AstNode(AST_GT, countbits, mkconst_int(0, false));
+ } else if (str == "\\$onehot") {
+ countbits->children.push_back(mkconst_bits({RTLIL::State::S1}, false));
+ newNode = new AstNode(AST_EQ, countbits, mkconst_int(1, false));
+ } else if (str == "\\$onehot0") {
+ countbits->children.push_back(mkconst_bits({RTLIL::State::S1}, false));
+ newNode = new AstNode(AST_LE, countbits, mkconst_int(1, false));
+ } else {
+ log_abort();
+ }
+
+ goto apply_newNode;
+ }
+
if (current_scope.count(str) != 0 && current_scope[str]->type == AST_DPI_FUNCTION)
{
AstNode *dpi_decl = current_scope[str];
@@ -3016,28 +3690,37 @@ skip_dynamic_range_lvalue_expansion:;
log_file_error(filename, location.first_line, "Can't resolve task name `%s'.\n", str.c_str());
}
- AstNode *decl = current_scope[str];
std::stringstream sstr;
- sstr << "$func$" << str << "$" << filename << ":" << location.first_line << "$" << (autoidx++) << "$";
+ sstr << str << "$func$" << filename << ":" << location.first_line << "$" << (autoidx++) << '.';
std::string prefix = sstr.str();
- bool recommend_const_eval = false;
- bool require_const_eval = in_param ? false : has_const_only_constructs(recommend_const_eval);
- if ((in_param || recommend_const_eval || require_const_eval) && !decl->attributes.count(ID::via_celltype))
+ AstNode *decl = current_scope[str];
+ if (unevaluated_tern_branch && decl->is_recursive_function())
+ goto replace_fcall_later;
+ decl = decl->clone();
+ decl->replace_result_wire_name_in_function(str, "$result"); // enables recursion
+ decl->expand_genblock(prefix);
+
+ if (decl->type == AST_FUNCTION && !decl->attributes.count(ID::via_celltype))
{
+ bool require_const_eval = decl->has_const_only_constructs();
bool all_args_const = true;
for (auto child : children) {
while (child->simplify(true, false, false, 1, -1, false, true)) { }
- if (child->type != AST_CONSTANT)
+ if (child->type != AST_CONSTANT && child->type != AST_REALVALUE)
all_args_const = false;
}
if (all_args_const) {
- AstNode *func_workspace = current_scope[str]->clone();
- newNode = func_workspace->eval_const_function(this);
+ AstNode *func_workspace = decl->clone();
+ func_workspace->str = prefix_id(prefix, "$result");
+ newNode = func_workspace->eval_const_function(this, in_param || require_const_eval);
delete func_workspace;
- goto apply_newNode;
+ if (newNode) {
+ delete decl;
+ goto apply_newNode;
+ }
}
if (in_param)
@@ -3047,8 +3730,6 @@ skip_dynamic_range_lvalue_expansion:;
}
size_t arg_count = 0;
- std::map<std::string, std::string> replace_rules;
- vector<AstNode*> added_mod_children;
dict<std::string, AstNode*> wire_cache;
vector<AstNode*> new_stmts;
vector<AstNode*> output_assignments;
@@ -3058,16 +3739,17 @@ skip_dynamic_range_lvalue_expansion:;
log_assert(type == AST_FCALL);
AstNode *wire = NULL;
+ std::string res_name = prefix_id(prefix, "$result");
for (auto child : decl->children)
- if (child->type == AST_WIRE && child->str == str)
+ if (child->type == AST_WIRE && child->str == res_name)
wire = child->clone();
log_assert(wire != NULL);
- wire->str = prefix + str;
wire->port_id = 0;
wire->is_input = false;
wire->is_output = false;
+ current_scope[wire->str] = wire;
current_ast_mod->children.push_back(wire);
while (wire->simplify(true, false, false, 1, -1, false, false)) { }
@@ -3111,7 +3793,6 @@ skip_dynamic_range_lvalue_expansion:;
if (child->type == AST_WIRE && (child->is_input || child->is_output || (type == AST_FCALL && child->str == str)))
{
AstNode *wire = child->clone();
- wire->str = prefix + wire->str;
wire->port_id = 0;
wire->is_input = false;
wire->is_output = false;
@@ -3154,14 +3835,15 @@ skip_dynamic_range_lvalue_expansion:;
if (wire_cache.count(child->str))
{
wire = wire_cache.at(child->str);
- if (wire->children.empty()) {
+ bool contains_value = wire->type == AST_LOCALPARAM;
+ if (wire->children.size() == contains_value) {
for (auto c : child->children)
wire->children.push_back(c->clone());
} else if (!child->children.empty()) {
while (child->simplify(true, false, false, stage, -1, false, false)) { }
- if (GetSize(child->children) == GetSize(wire->children)) {
+ if (GetSize(child->children) == GetSize(wire->children) - contains_value) {
for (int i = 0; i < GetSize(child->children); i++)
- if (*child->children.at(i) != *wire->children.at(i))
+ if (*child->children.at(i) != *wire->children.at(i + contains_value))
goto tcall_incompatible_wires;
} else {
tcall_incompatible_wires:
@@ -3172,7 +3854,6 @@ skip_dynamic_range_lvalue_expansion:;
else
{
wire = child->clone();
- wire->str = prefix + wire->str;
wire->port_id = 0;
wire->is_input = false;
wire->is_output = false;
@@ -3183,19 +3864,46 @@ skip_dynamic_range_lvalue_expansion:;
wire_cache[child->str] = wire;
+ current_scope[wire->str] = wire;
current_ast_mod->children.push_back(wire);
- added_mod_children.push_back(wire);
}
- if (child->type == AST_WIRE)
- while (wire->simplify(true, false, false, 1, -1, false, false)) { }
-
- replace_rules[child->str] = wire->str;
- current_scope[wire->str] = wire;
+ while (wire->simplify(true, false, false, 1, -1, false, false)) { }
if ((child->is_input || child->is_output) && arg_count < children.size())
{
AstNode *arg = children[arg_count++]->clone();
+ // 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
+ if (wire->children.back()->type != AST_RANGE) {
+ // check if this wire is redeclared with an explicit size
+ bool uses_explicit_size = false;
+ for (const AstNode *other_child : decl->children)
+ if (other_child->type == AST_WIRE && child->str == other_child->str
+ && !other_child->children.empty()
+ && other_child->children.back()->type == AST_RANGE) {
+ uses_explicit_size = true;
+ break;
+ }
+ if (!uses_explicit_size) {
+ AstNode* range = new AstNode();
+ range->type = AST_RANGE;
+ wire->children.push_back(range);
+ range->children.push_back(mkconst_int(0, true));
+ range->children.push_back(mkconst_int(0, true));
+ }
+ }
+ // updates the sizing
+ while (wire->simplify(true, false, false, 1, -1, false, false)) { }
+ delete arg;
+ continue;
+ }
AstNode *wire_id = new AstNode(AST_IDENTIFIER);
wire_id->str = wire->str;
AstNode *assign = child->is_input ?
@@ -3209,18 +3917,9 @@ skip_dynamic_range_lvalue_expansion:;
}
}
- for (auto child : added_mod_children) {
- child->replace_ids(prefix, replace_rules);
- while (child->simplify(true, false, false, 1, -1, false, false)) { }
- }
-
for (auto child : decl->children)
if (child->type != AST_WIRE && child->type != AST_MEMORY && child->type != AST_PARAMETER && child->type != AST_LOCALPARAM)
- {
- AstNode *stmt = child->clone();
- stmt->replace_ids(prefix, replace_rules);
- new_stmts.push_back(stmt);
- }
+ new_stmts.push_back(child->clone());
new_stmts.insert(new_stmts.end(), output_assignments.begin(), output_assignments.end());
@@ -3233,10 +3932,11 @@ skip_dynamic_range_lvalue_expansion:;
}
replace_fcall_with_id:
+ delete decl;
if (type == AST_FCALL) {
delete_children();
type = AST_IDENTIFIER;
- str = prefix + str;
+ str = prefix_id(prefix, "$result");
}
if (type == AST_TCALL)
str = "";
@@ -3284,7 +3984,14 @@ replace_fcall_later:;
if (current_scope[str]->children[0]->isConst())
newNode = current_scope[str]->children[0]->clone();
}
- else if (at_zero && current_scope.count(str) > 0 && (current_scope[str]->type == AST_WIRE || current_scope[str]->type == AST_AUTOWIRE)) {
+ else if (at_zero && current_scope.count(str) > 0) {
+ AstNode *node = current_scope[str];
+ if (node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_MEMORY)
+ newNode = mkconst_int(0, sign_hint, width_hint);
+ }
+ break;
+ case AST_MEMRD:
+ if (at_zero) {
newNode = mkconst_int(0, sign_hint, width_hint);
}
break;
@@ -3429,24 +4136,9 @@ replace_fcall_later:;
case AST_TERNARY:
if (children[0]->isConst())
{
- bool found_sure_true = false;
- bool found_maybe_true = false;
-
- if (children[0]->type == AST_CONSTANT)
- for (auto &bit : children[0]->bits) {
- if (bit == RTLIL::State::S1)
- found_sure_true = true;
- if (bit > RTLIL::State::S1)
- found_maybe_true = true;
- }
- else
- found_sure_true = children[0]->asReal(sign_hint) != 0;
-
- AstNode *choice = NULL, *not_choice = NULL;
- if (found_sure_true)
- choice = children[1], not_choice = children[2];
- else if (!found_maybe_true)
- choice = children[2], not_choice = children[1];
+ auto pair = get_tern_choice();
+ AstNode *choice = pair.first;
+ AstNode *not_choice = pair.second;
if (choice != NULL) {
if (choice->type == AST_CONSTANT) {
@@ -3491,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;
@@ -3540,12 +4236,12 @@ apply_newNode:
return did_something;
}
-static void replace_result_wire_name_in_function(AstNode *node, std::string &from, std::string &to)
+void AstNode::replace_result_wire_name_in_function(const std::string &from, const std::string &to)
{
- for (auto &it : node->children)
- replace_result_wire_name_in_function(it, from, to);
- if (node->str == from)
- node->str = to;
+ for (AstNode *child : children)
+ child->replace_result_wire_name_in_function(from, to);
+ if (str == from && type != AST_FCALL && type != AST_TCALL)
+ str = to;
}
// replace a readmem[bh] TCALL ast node with a block of memory assignments
@@ -3559,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()) {
@@ -3634,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;
@@ -3674,116 +4375,163 @@ 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;
}
-// annotate the names of all wires and other named objects in a generate block
-void AstNode::expand_genblock(std::string index_var, std::string prefix, std::map<std::string, std::string> &name_map)
+// annotate the names of all wires and other named objects in a named generate
+// or procedural block; nested blocks are themselves annotated such that the
+// prefix is carried forward, but resolution of their children is deferred
+void AstNode::expand_genblock(const std::string &prefix)
{
- if (!index_var.empty() && type == AST_IDENTIFIER && str == index_var) {
- if (children.empty()) {
- current_scope[index_var]->children[0]->cloneInto(this);
- } else {
- AstNode *p = new AstNode(AST_LOCALPARAM, current_scope[index_var]->children[0]->clone());
- p->str = stringf("$genval$%d", autoidx++);
- current_ast_mod->children.push_back(p);
- str = p->str;
- id2ast = p;
+ 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
+ for (size_t ppos = prefix.size() - 1; ppos; --ppos) {
+ if (prefix.at(ppos) != '.') continue;
+
+ std::string new_prefix = prefix.substr(0, ppos + 1);
+ auto attempt_resolve = [&new_prefix](const std::string &ident) -> std::string {
+ std::string new_name = prefix_id(new_prefix, ident);
+ if (current_scope.count(new_name))
+ return new_name;
+ return {};
+ };
+
+ // attempt to resolve the full identifier
+ std::string resolved = attempt_resolve(str);
+ if (!resolved.empty()) {
+ str = resolved;
+ break;
+ }
+
+ // attempt to resolve hierarchical prefixes within the identifier,
+ // as the prefix could refer to a local scope which exists but
+ // hasn't yet been elaborated
+ for (size_t spos = str.size() - 1; spos; --spos) {
+ if (str.at(spos) != '.') continue;
+ resolved = attempt_resolve(str.substr(0, spos));
+ if (!resolved.empty()) {
+ str = resolved + str.substr(spos);
+ ppos = 1; // break outer loop
+ break;
+ }
+ }
+
}
}
- if ((type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL || type == AST_WIRETYPE) && name_map.count(str) > 0)
- str = name_map[str];
-
- std::map<std::string, std::string> backup_name_map;
+ auto prefix_node = [&prefix](AstNode* child) {
+ if (child->str.empty()) return;
+ std::string new_name = prefix_id(prefix, child->str);
+ if (child->type == AST_FUNCTION)
+ child->replace_result_wire_name_in_function(child->str, new_name);
+ else
+ child->str = new_name;
+ current_scope[new_name] = child;
+ };
for (size_t i = 0; i < children.size(); i++) {
AstNode *child = children[i];
- if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM ||
- child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL || child->type == AST_TYPEDEF || child->type == AST_ENUM_ITEM) {
- if (backup_name_map.size() == 0)
- backup_name_map = name_map;
- std::string new_name = prefix[0] == '\\' ? prefix.substr(1) : prefix;
- size_t pos = child->str.rfind('.');
- if (pos == std::string::npos)
- pos = child->str[0] == '\\' && prefix[0] == '\\' ? 1 : 0;
- else
- pos = pos + 1;
- new_name = child->str.substr(0, pos) + new_name + child->str.substr(pos);
- if (new_name[0] != '$' && new_name[0] != '\\')
- new_name = prefix[0] + new_name;
- name_map[child->str] = new_name;
- if (child->type == AST_FUNCTION)
- replace_result_wire_name_in_function(child, child->str, new_name);
- else
- child->str = new_name;
- current_scope[new_name] = child;
- }
- if (child->type == AST_ENUM){
+
+ switch (child->type) {
+ case AST_WIRE:
+ case AST_MEMORY:
+ case AST_PARAMETER:
+ case AST_LOCALPARAM:
+ case AST_FUNCTION:
+ case AST_TASK:
+ case AST_CELL:
+ case AST_TYPEDEF:
+ case AST_ENUM_ITEM:
+ case AST_GENVAR:
+ prefix_node(child);
+ break;
+
+ case AST_BLOCK:
+ case AST_GENBLOCK:
+ if (!child->str.empty())
+ prefix_node(child);
+ break;
+
+ case AST_ENUM:
current_scope[child->str] = child;
for (auto enode : child->children){
log_assert(enode->type == AST_ENUM_ITEM);
- if (backup_name_map.size() == 0)
- backup_name_map = name_map;
- std::string new_name = prefix[0] == '\\' ? prefix.substr(1) : prefix;
- size_t pos = enode->str.rfind('.');
- if (pos == std::string::npos)
- pos = enode->str[0] == '\\' && prefix[0] == '\\' ? 1 : 0;
- else
- pos = pos + 1;
- new_name = enode->str.substr(0, pos) + new_name + enode->str.substr(pos);
- if (new_name[0] != '$' && new_name[0] != '\\')
- new_name = prefix[0] + new_name;
- name_map[enode->str] = new_name;
-
- enode->str = new_name;
- current_scope[new_name] = enode;
+ prefix_node(enode);
}
+ break;
+
+ default:
+ break;
}
}
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;
+ // named blocks pick up the current prefix and will expanded later
+ if ((child->type == AST_GENBLOCK || child->type == AST_BLOCK) && !child->str.empty())
continue;
- if (child->type != AST_FUNCTION && child->type != AST_TASK)
- child->expand_genblock(index_var, prefix, name_map);
- }
-
- if (backup_name_map.size() > 0)
- name_map.swap(backup_name_map);
+ child->expand_genblock(prefix);
+ }
}
-// rename stuff (used when tasks of functions are instantiated)
-void AstNode::replace_ids(const std::string &prefix, const std::map<std::string, std::string> &rules)
+// add implicit AST_GENBLOCK names according to IEEE 1364-2005 Section 12.4.3 or
+// IEEE 1800-2017 Section 27.6
+void AstNode::label_genblks(std::set<std::string>& existing, int &counter)
{
- if (type == AST_BLOCK)
- {
- std::map<std::string, std::string> new_rules = rules;
- std::string new_prefix = prefix + str;
-
- for (auto child : children)
- if (child->type == AST_WIRE) {
- new_rules[child->str] = new_prefix + child->str;
- child->str = new_prefix + child->str;
- }
+ switch (type) {
+ case AST_GENIF:
+ case AST_GENFOR:
+ case AST_GENCASE:
+ // seeing a proper generate control flow construct increments the
+ // counter once
+ ++counter;
+ for (AstNode *child : children)
+ child->label_genblks(existing, counter);
+ break;
- for (auto child : children)
- if (child->type != AST_WIRE)
- child->replace_ids(new_prefix, new_rules);
+ case AST_GENBLOCK: {
+ // if this block is unlabeled, generate its corresponding unique name
+ for (int padding = 0; str.empty(); ++padding) {
+ std::string candidate = "\\genblk";
+ for (int i = 0; i < padding; ++i)
+ candidate += '0';
+ candidate += std::to_string(counter);
+ if (!existing.count(candidate))
+ str = candidate;
+ }
+ // within a genblk, the counter starts fresh
+ std::set<std::string> existing_local = existing;
+ int counter_local = 0;
+ for (AstNode *child : children)
+ child->label_genblks(existing_local, counter_local);
+ break;
}
- else
- {
- if (type == AST_IDENTIFIER && rules.count(str) > 0)
- str = rules.at(str);
- for (auto child : children)
- child->replace_ids(prefix, rules);
+
+ default:
+ // track names which could conflict with implicit genblk names
+ if (str.rfind("\\genblk", 0) == 0)
+ existing.insert(str);
+ for (AstNode *child : children)
+ child->label_genblks(existing, counter);
+ break;
}
}
@@ -3977,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)
{
@@ -3991,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;
+ }
+ }
}
}
@@ -4098,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
{
@@ -4231,6 +5045,8 @@ bool AstNode::detect_latch(const std::string &var)
case AST_POSEDGE:
case AST_NEGEDGE:
return false;
+ case AST_EDGE:
+ break;
case AST_BLOCK:
if (!c->detect_latch(var))
return false;
@@ -4273,17 +5089,12 @@ bool AstNode::detect_latch(const std::string &var)
}
}
-bool AstNode::has_const_only_constructs(bool &recommend_const_eval)
+bool AstNode::has_const_only_constructs()
{
- if (type == AST_FOR)
- recommend_const_eval = true;
if (type == AST_WHILE || type == AST_REPEAT)
return true;
- if (type == AST_FCALL && current_scope.count(str))
- if (current_scope[str]->has_const_only_constructs(recommend_const_eval))
- return true;
for (auto child : children)
- if (child->AstNode::has_const_only_constructs(recommend_const_eval))
+ if (child->has_const_only_constructs())
return true;
return false;
}
@@ -4299,19 +5110,26 @@ bool AstNode::is_simple_const_expr()
}
// helper function for AstNode::eval_const_function()
-void AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &variables, AstNode *fcall)
+bool AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &variables, AstNode *fcall, bool must_succeed)
{
if (type == AST_IDENTIFIER && variables.count(str)) {
int offset = variables.at(str).offset, width = variables.at(str).val.bits.size();
if (!children.empty()) {
- if (children.size() != 1 || children.at(0)->type != AST_RANGE)
- log_file_error(filename, location.first_line, "Memory access in constant function is not supported\n%s:%d.%d-%d.%d: ...called from here.\n",
- fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
- children.at(0)->replace_variables(variables, fcall);
+ if (children.size() != 1 || children.at(0)->type != AST_RANGE) {
+ if (!must_succeed)
+ return false;
+ log_file_error(filename, location.first_line, "Memory access in constant function is not supported\n%s: ...called from here.\n",
+ fcall->loc_string().c_str());
+ }
+ if (!children.at(0)->replace_variables(variables, fcall, must_succeed))
+ return false;
while (simplify(true, false, false, 1, -1, false, true)) { }
- if (!children.at(0)->range_valid)
- log_file_error(filename, location.first_line, "Non-constant range\n%s:%d.%d-%d.%d: ... called from here.\n",
- fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
+ if (!children.at(0)->range_valid) {
+ if (!must_succeed)
+ return false;
+ log_file_error(filename, location.first_line, "Non-constant range\n%s: ... called from here.\n",
+ fcall->loc_string().c_str());
+ }
offset = min(children.at(0)->range_left, children.at(0)->range_right);
width = min(std::abs(children.at(0)->range_left - children.at(0)->range_right) + 1, width);
}
@@ -4321,44 +5139,30 @@ void AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &varia
AstNode *newNode = mkconst_bits(new_bits, variables.at(str).is_signed);
newNode->cloneInto(this);
delete newNode;
- return;
+ return true;
}
for (auto &child : children)
- child->replace_variables(variables, fcall);
+ if (!child->replace_variables(variables, fcall, must_succeed))
+ return false;
+ return true;
}
-// evaluate functions with all-const arguments
-AstNode *AstNode::eval_const_function(AstNode *fcall)
+// attempt to statically evaluate a functions with all-const arguments
+AstNode *AstNode::eval_const_function(AstNode *fcall, bool must_succeed)
{
- std::map<std::string, AstNode*> backup_scope;
+ 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;
size_t argidx = 0;
for (auto child : children)
{
- if (child->type == AST_WIRE)
- {
- while (child->simplify(true, false, false, 1, -1, false, true)) { }
- if (!child->range_valid)
- log_file_error(child->filename, child->location.first_line, "Can't determine size of variable %s\n%s:%d.%d-%d.%d: ... called from here.\n",
- child->str.c_str(), fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
- variables[child->str].val = RTLIL::Const(RTLIL::State::Sx, abs(child->range_left - child->range_right)+1);
- variables[child->str].offset = min(child->range_left, child->range_right);
- variables[child->str].is_signed = child->is_signed;
- if (child->is_input && argidx < fcall->children.size())
- variables[child->str].val = fcall->children.at(argidx++)->bitsAsConst(variables[child->str].val.bits.size());
- backup_scope[child->str] = current_scope[child->str];
- current_scope[child->str] = child;
- continue;
- }
-
block->children.push_back(child->clone());
}
- log_assert(variables.count(str) != 0);
-
while (!block->children.empty())
{
AstNode *stmt = block->children.front();
@@ -4370,36 +5174,104 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
stmt->dumpAst(NULL, "stmt> ");
#endif
+ if (stmt->type == AST_WIRE)
+ {
+ while (stmt->simplify(true, false, false, 1, -1, false, true)) { }
+ if (!stmt->range_valid) {
+ if (!must_succeed)
+ goto finished;
+ log_file_error(stmt->filename, stmt->location.first_line, "Can't determine size of variable %s\n%s: ... called from here.\n",
+ stmt->str.c_str(), fcall->loc_string().c_str());
+ }
+ AstNode::varinfo_t &variable = variables[stmt->str];
+ int width = abs(stmt->range_left - stmt->range_right) + 1;
+ // if this variable has already been declared as an input, check the
+ // sizes match if it already had an explicit size
+ if (variable.arg && variable.explicitly_sized && variable.val.size() != width) {
+ log_file_error(filename, location.first_line, "Incompatible re-declaration of constant function wire %s.\n", stmt->str.c_str());
+ }
+ variable.val = RTLIL::Const(RTLIL::State::Sx, width);
+ variable.offset = min(stmt->range_left, stmt->range_right);
+ variable.is_signed = stmt->is_signed;
+ variable.explicitly_sized = stmt->children.size() &&
+ stmt->children.back()->type == AST_RANGE;
+ // identify the argument corresponding to this wire, if applicable
+ if (stmt->is_input && argidx < fcall->children.size()) {
+ variable.arg = fcall->children.at(argidx++);
+ }
+ // load the constant arg's value into this variable
+ if (variable.arg) {
+ if (variable.arg->type == AST_CONSTANT) {
+ variable.val = variable.arg->bitsAsConst(width);
+ } else {
+ log_assert(variable.arg->type == AST_REALVALUE);
+ variable.val = variable.arg->realAsConst(width);
+ }
+ }
+ current_scope[stmt->str] = stmt;
+
+ block->children.erase(block->children.begin());
+ to_delete.push_back(stmt);
+ continue;
+ }
+
+ log_assert(variables.count(str) != 0);
+
+ if (stmt->type == AST_LOCALPARAM)
+ {
+ while (stmt->simplify(true, false, false, 1, -1, false, true)) { }
+
+ current_scope[stmt->str] = stmt;
+
+ block->children.erase(block->children.begin());
+ to_delete.push_back(stmt);
+ continue;
+ }
+
if (stmt->type == AST_ASSIGN_EQ)
{
if (stmt->children.at(0)->type == AST_IDENTIFIER && stmt->children.at(0)->children.size() != 0 &&
stmt->children.at(0)->children.at(0)->type == AST_RANGE)
- stmt->children.at(0)->children.at(0)->replace_variables(variables, fcall);
- stmt->children.at(1)->replace_variables(variables, fcall);
+ if (!stmt->children.at(0)->children.at(0)->replace_variables(variables, fcall, must_succeed))
+ goto finished;
+ if (!stmt->children.at(1)->replace_variables(variables, fcall, must_succeed))
+ goto finished;
while (stmt->simplify(true, false, false, 1, -1, false, true)) { }
if (stmt->type != AST_ASSIGN_EQ)
continue;
- if (stmt->children.at(1)->type != AST_CONSTANT)
- log_file_error(stmt->filename, stmt->location.first_line, "Non-constant expression in constant function\n%s:%d.%d-%d.%d: ... called from here. X\n",
- fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
+ if (stmt->children.at(1)->type != AST_CONSTANT) {
+ if (!must_succeed)
+ goto finished;
+ log_file_error(stmt->filename, stmt->location.first_line, "Non-constant expression in constant function\n%s: ... called from here. X\n",
+ fcall->loc_string().c_str());
+ }
- if (stmt->children.at(0)->type != AST_IDENTIFIER)
- log_file_error(stmt->filename, stmt->location.first_line, "Unsupported composite left hand side in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
- fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
+ if (stmt->children.at(0)->type != AST_IDENTIFIER) {
+ if (!must_succeed)
+ goto finished;
+ log_file_error(stmt->filename, stmt->location.first_line, "Unsupported composite left hand side in constant function\n%s: ... called from here.\n",
+ fcall->loc_string().c_str());
+ }
- if (!variables.count(stmt->children.at(0)->str))
- log_file_error(stmt->filename, stmt->location.first_line, "Assignment to non-local variable in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
- fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
+ if (!variables.count(stmt->children.at(0)->str)) {
+ if (!must_succeed)
+ goto finished;
+ log_file_error(stmt->filename, stmt->location.first_line, "Assignment to non-local variable in constant function\n%s: ... called from here.\n",
+ fcall->loc_string().c_str());
+ }
if (stmt->children.at(0)->children.empty()) {
variables[stmt->children.at(0)->str].val = stmt->children.at(1)->bitsAsConst(variables[stmt->children.at(0)->str].val.bits.size());
} else {
AstNode *range = stmt->children.at(0)->children.at(0);
- if (!range->range_valid)
- log_file_error(range->filename, range->location.first_line, "Non-constant range\n%s:%d.%d-%d.%d: ... called from here.\n",
- fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
+ if (!range->range_valid) {
+ if (!must_succeed)
+ goto finished;
+ log_file_error(range->filename, range->location.first_line, "Non-constant range\n%s: ... called from here.\n",
+ fcall->loc_string().c_str());
+ }
int offset = min(range->range_left, range->range_right);
int width = std::abs(range->range_left - range->range_right) + 1;
varinfo_t &v = variables[stmt->children.at(0)->str];
@@ -4426,12 +5298,16 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
if (stmt->type == AST_WHILE)
{
AstNode *cond = stmt->children.at(0)->clone();
- cond->replace_variables(variables, fcall);
+ if (!cond->replace_variables(variables, fcall, must_succeed))
+ goto finished;
while (cond->simplify(true, false, false, 1, -1, false, true)) { }
- if (cond->type != AST_CONSTANT)
- log_file_error(stmt->filename, stmt->location.first_line, "Non-constant expression in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
- fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
+ if (cond->type != AST_CONSTANT) {
+ if (!must_succeed)
+ goto finished;
+ log_file_error(stmt->filename, stmt->location.first_line, "Non-constant expression in constant function\n%s: ... called from here.\n",
+ fcall->loc_string().c_str());
+ }
if (cond->asBool()) {
block->children.insert(block->children.begin(), stmt->children.at(1)->clone());
@@ -4447,12 +5323,16 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
if (stmt->type == AST_REPEAT)
{
AstNode *num = stmt->children.at(0)->clone();
- num->replace_variables(variables, fcall);
+ if (!num->replace_variables(variables, fcall, must_succeed))
+ goto finished;
while (num->simplify(true, false, false, 1, -1, false, true)) { }
- if (num->type != AST_CONSTANT)
- log_file_error(stmt->filename, stmt->location.first_line, "Non-constant expression in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
- fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
+ if (num->type != AST_CONSTANT) {
+ if (!must_succeed)
+ goto finished;
+ log_file_error(stmt->filename, stmt->location.first_line, "Non-constant expression in constant function\n%s: ... called from here.\n",
+ fcall->loc_string().c_str());
+ }
block->children.erase(block->children.begin());
for (int i = 0; i < num->bitsAsConst().as_int(); i++)
@@ -4466,7 +5346,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
if (stmt->type == AST_CASE)
{
AstNode *expr = stmt->children.at(0)->clone();
- expr->replace_variables(variables, fcall);
+ if (!expr->replace_variables(variables, fcall, must_succeed))
+ goto finished;
while (expr->simplify(true, false, false, 1, -1, false, true)) { }
AstNode *sel_case = NULL;
@@ -4483,14 +5364,18 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
for (size_t j = 0; j+1 < stmt->children.at(i)->children.size() && !found_match; j++)
{
AstNode *cond = stmt->children.at(i)->children.at(j)->clone();
- cond->replace_variables(variables, fcall);
+ if (!cond->replace_variables(variables, fcall, must_succeed))
+ goto finished;
cond = new AstNode(AST_EQ, expr->clone(), cond);
while (cond->simplify(true, false, false, 1, -1, false, true)) { }
- if (cond->type != AST_CONSTANT)
- log_file_error(stmt->filename, stmt->location.first_line, "Non-constant expression in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
- fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
+ if (cond->type != AST_CONSTANT) {
+ if (!must_succeed)
+ goto finished;
+ log_file_error(stmt->filename, stmt->location.first_line, "Non-constant expression in constant function\n%s: ... called from here.\n",
+ fcall->loc_string().c_str());
+ }
found_match = cond->asBool();
delete cond;
@@ -4512,6 +5397,9 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
if (stmt->type == AST_BLOCK)
{
+ if (!stmt->str.empty())
+ stmt->expand_genblock(stmt->str + ".");
+
block->children.erase(block->children.begin());
block->children.insert(block->children.begin(), stmt->children.begin(), stmt->children.end());
stmt->children.clear();
@@ -4519,25 +5407,33 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
continue;
}
- log_file_error(stmt->filename, stmt->location.first_line, "Unsupported language construct in constant function\n%s:%d.%d-%d.%d: ... called from here.\n",
- fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
+ if (!must_succeed)
+ goto finished;
+ log_file_error(stmt->filename, stmt->location.first_line, "Unsupported language construct in constant function\n%s: ... called from here.\n",
+ fcall->loc_string().c_str());
log_abort();
}
+ result = AstNode::mkconst_bits(variables.at(str).val.bits, variables.at(str).is_signed);
+
+finished:
delete block;
+ current_scope = backup_scope;
- for (auto &it : backup_scope)
- if (it.second == NULL)
- current_scope.erase(it.first);
- else
- current_scope[it.first] = it.second;
+ for (auto it : to_delete) {
+ delete it;
+ }
+ to_delete.clear();
- return AstNode::mkconst_bits(variables.at(str).val.bits, variables.at(str).is_signed);
+ 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);
@@ -4563,4 +5459,71 @@ void AstNode::allocateDefaultEnumValues()
}
}
+bool AstNode::is_recursive_function() const
+{
+ std::set<const AstNode *> visited;
+ std::function<bool(const AstNode *node)> visit = [&](const AstNode *node) {
+ if (visited.count(node))
+ return node == this;
+ visited.insert(node);
+ if (node->type == AST_FCALL) {
+ auto it = current_scope.find(node->str);
+ if (it != current_scope.end() && visit(it->second))
+ return true;
+ }
+ for (const AstNode *child : node->children) {
+ if (visit(child))
+ return true;
+ }
+ return false;
+ };
+
+ log_assert(type == AST_FUNCTION);
+ return visit(this);
+}
+
+std::pair<AstNode*, AstNode*> AstNode::get_tern_choice()
+{
+ if (!children[0]->isConst())
+ return {};
+
+ bool found_sure_true = false;
+ bool found_maybe_true = false;
+
+ if (children[0]->type == AST_CONSTANT)
+ for (auto &bit : children[0]->bits) {
+ if (bit == RTLIL::State::S1)
+ found_sure_true = true;
+ if (bit > RTLIL::State::S1)
+ found_maybe_true = true;
+ }
+ else
+ found_sure_true = children[0]->asReal(true) != 0;
+
+ AstNode *choice = nullptr, *not_choice = nullptr;
+ if (found_sure_true)
+ choice = children[1], not_choice = children[2];
+ else if (!found_maybe_true)
+ choice = children[2], not_choice = children[1];
+
+ 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/ilang/.gitignore b/frontends/ilang/.gitignore
deleted file mode 100644
index f586b33c7..000000000
--- a/frontends/ilang/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-ilang_lexer.cc
-ilang_parser.output
-ilang_parser.tab.cc
-ilang_parser.tab.hh
diff --git a/frontends/ilang/Makefile.inc b/frontends/ilang/Makefile.inc
deleted file mode 100644
index 6f1f0e8fc..000000000
--- a/frontends/ilang/Makefile.inc
+++ /dev/null
@@ -1,19 +0,0 @@
-
-GENFILES += frontends/ilang/ilang_parser.tab.cc
-GENFILES += frontends/ilang/ilang_parser.tab.hh
-GENFILES += frontends/ilang/ilang_parser.output
-GENFILES += frontends/ilang/ilang_lexer.cc
-
-frontends/ilang/ilang_parser.tab.cc: frontends/ilang/ilang_parser.y
- $(Q) mkdir -p $(dir $@)
- $(P) $(BISON) -o $@ -d -r all -b frontends/ilang/ilang_parser $<
-
-frontends/ilang/ilang_parser.tab.hh: frontends/ilang/ilang_parser.tab.cc
-
-frontends/ilang/ilang_lexer.cc: frontends/ilang/ilang_lexer.l
- $(Q) mkdir -p $(dir $@)
- $(P) flex -o frontends/ilang/ilang_lexer.cc $<
-
-OBJS += frontends/ilang/ilang_parser.tab.o frontends/ilang/ilang_lexer.o
-OBJS += frontends/ilang/ilang_frontend.o
-
diff --git a/frontends/json/jsonparse.cc b/frontends/json/jsonparse.cc
index 1b34aaf3a..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
@@ -72,10 +72,17 @@ struct JsonNode
break;
}
- if ('0' <= ch && ch <= '9')
+ if (('0' <= ch && ch <= '9') || ch == '-')
{
+ bool negative = false;
type = 'N';
- data_number = ch - '0';
+ if (ch == '-') {
+ data_number = 0;
+ negative = true;
+ } else {
+ data_number = ch - '0';
+ }
+
data_string += ch;
while (1)
@@ -97,6 +104,7 @@ struct JsonNode
data_string += ch;
}
+ data_number = negative ? -data_number : data_number;
data_string = "";
break;
@@ -531,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/rpc/rpc_frontend.cc b/frontends/rpc/rpc_frontend.cc
index 6d72cbff5..c12640ef0 100644
--- a/frontends/rpc/rpc_frontend.cc
+++ b/frontends/rpc/rpc_frontend.cc
@@ -378,7 +378,7 @@ struct RpcFrontend : public Pass {
log(" -> {\"method\": \"derive\", \"module\": \"<module-name\">, \"parameters\": {\n");
log(" \"<param-name>\": {\"type\": \"[unsigned|signed|string|real]\",\n");
log(" \"value\": \"<param-value>\"}, ...}}\n");
- log(" <- {\"frontend\": \"[ilang|verilog|...]\",\"source\": \"<source>\"}}\n");
+ log(" <- {\"frontend\": \"[rtlil|verilog|...]\",\"source\": \"<source>\"}}\n");
log(" <- {\"error\": \"<error-message>\"}\n");
log(" request for the module <module-name> to be derived for a specific set of\n");
log(" parameters. <param-name> starts with \\ for named parameters, and with $\n");
@@ -401,10 +401,11 @@ struct RpcFrontend : public Pass {
std::string arg = args[argidx];
if (arg == "-exec" && argidx+1 < args.size()) {
command.insert(command.begin(), args.begin() + argidx + 1, args.end());
+ argidx = args.size()-1;
continue;
}
if (arg == "-path" && argidx+1 < args.size()) {
- path = args[argidx+1];
+ path = args[++argidx];
continue;
}
break;
diff --git a/frontends/rtlil/.gitignore b/frontends/rtlil/.gitignore
new file mode 100644
index 000000000..d4a322756
--- /dev/null
+++ b/frontends/rtlil/.gitignore
@@ -0,0 +1,4 @@
+rtlil_lexer.cc
+rtlil_parser.output
+rtlil_parser.tab.cc
+rtlil_parser.tab.hh
diff --git a/frontends/rtlil/Makefile.inc b/frontends/rtlil/Makefile.inc
new file mode 100644
index 000000000..d0c0cfcf8
--- /dev/null
+++ b/frontends/rtlil/Makefile.inc
@@ -0,0 +1,19 @@
+
+GENFILES += frontends/rtlil/rtlil_parser.tab.cc
+GENFILES += frontends/rtlil/rtlil_parser.tab.hh
+GENFILES += frontends/rtlil/rtlil_parser.output
+GENFILES += frontends/rtlil/rtlil_lexer.cc
+
+frontends/rtlil/rtlil_parser.tab.cc: frontends/rtlil/rtlil_parser.y
+ $(Q) mkdir -p $(dir $@)
+ $(P) $(BISON) -o $@ -d -r all -b frontends/rtlil/rtlil_parser $<
+
+frontends/rtlil/rtlil_parser.tab.hh: frontends/rtlil/rtlil_parser.tab.cc
+
+frontends/rtlil/rtlil_lexer.cc: frontends/rtlil/rtlil_lexer.l
+ $(Q) mkdir -p $(dir $@)
+ $(P) flex -o frontends/rtlil/rtlil_lexer.cc $<
+
+OBJS += frontends/rtlil/rtlil_parser.tab.o frontends/rtlil/rtlil_lexer.o
+OBJS += frontends/rtlil/rtlil_frontend.o
+
diff --git a/frontends/ilang/ilang_frontend.cc b/frontends/rtlil/rtlil_frontend.cc
index 973e62f2c..5f85ca2b8 100644
--- a/frontends/ilang/ilang_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
@@ -18,30 +18,30 @@
* ---
*
* A very simple and straightforward frontend for the RTLIL text
- * representation (as generated by the 'ilang' backend).
+ * representation.
*
*/
-#include "ilang_frontend.h"
+#include "rtlil_frontend.h"
#include "kernel/register.h"
#include "kernel/log.h"
-void rtlil_frontend_ilang_yyerror(char const *s)
+void rtlil_frontend_yyerror(char const *s)
{
- YOSYS_NAMESPACE_PREFIX log_error("Parser error in line %d: %s\n", rtlil_frontend_ilang_yyget_lineno(), s);
+ YOSYS_NAMESPACE_PREFIX log_error("Parser error in line %d: %s\n", rtlil_frontend_yyget_lineno(), s);
}
YOSYS_NAMESPACE_BEGIN
-struct IlangFrontend : public Frontend {
- IlangFrontend() : Frontend("ilang", "read modules from ilang file") { }
+struct RTLILFrontend : public Frontend {
+ RTLILFrontend() : Frontend("rtlil", "read modules from RTLIL file") { }
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
- log(" read_ilang [filename]\n");
+ log(" read_rtlil [filename]\n");
log("\n");
- log("Load modules from an ilang file to the current design. (ilang is a text\n");
+ log("Load modules from an RTLIL file to the current design. (RTLIL is a text\n");
log("representation of a design in yosys's internal format.)\n");
log("\n");
log(" -nooverwrite\n");
@@ -58,27 +58,27 @@ struct IlangFrontend : public Frontend {
}
void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
{
- ILANG_FRONTEND::flag_nooverwrite = false;
- ILANG_FRONTEND::flag_overwrite = false;
- ILANG_FRONTEND::flag_lib = false;
+ RTLIL_FRONTEND::flag_nooverwrite = false;
+ RTLIL_FRONTEND::flag_overwrite = false;
+ RTLIL_FRONTEND::flag_lib = false;
- log_header(design, "Executing ILANG frontend.\n");
+ log_header(design, "Executing RTLIL frontend.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
std::string arg = args[argidx];
if (arg == "-nooverwrite") {
- ILANG_FRONTEND::flag_nooverwrite = true;
- ILANG_FRONTEND::flag_overwrite = false;
+ RTLIL_FRONTEND::flag_nooverwrite = true;
+ RTLIL_FRONTEND::flag_overwrite = false;
continue;
}
if (arg == "-overwrite") {
- ILANG_FRONTEND::flag_nooverwrite = false;
- ILANG_FRONTEND::flag_overwrite = true;
+ RTLIL_FRONTEND::flag_nooverwrite = false;
+ RTLIL_FRONTEND::flag_overwrite = true;
continue;
}
if (arg == "-lib") {
- ILANG_FRONTEND::flag_lib = true;
+ RTLIL_FRONTEND::flag_lib = true;
continue;
}
break;
@@ -87,12 +87,27 @@ struct IlangFrontend : public Frontend {
log("Input filename: %s\n", filename.c_str());
- ILANG_FRONTEND::lexin = f;
- ILANG_FRONTEND::current_design = design;
- rtlil_frontend_ilang_yydebug = false;
- rtlil_frontend_ilang_yyrestart(NULL);
- rtlil_frontend_ilang_yyparse();
- rtlil_frontend_ilang_yylex_destroy();
+ RTLIL_FRONTEND::lexin = f;
+ RTLIL_FRONTEND::current_design = design;
+ rtlil_frontend_yydebug = false;
+ rtlil_frontend_yyrestart(NULL);
+ rtlil_frontend_yyparse();
+ rtlil_frontend_yylex_destroy();
+ }
+} RTLILFrontend;
+
+struct IlangFrontend : public Frontend {
+ IlangFrontend() : Frontend("ilang", "(deprecated) alias of read_rtlil") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log("See `help read_rtlil`.\n");
+ log("\n");
+ }
+ void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ RTLILFrontend.execute(f, filename, args, design);
}
} IlangFrontend;
diff --git a/frontends/ilang/ilang_frontend.h b/frontends/rtlil/rtlil_frontend.h
index f8a152841..189260605 100644
--- a/frontends/ilang/ilang_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
@@ -18,18 +18,18 @@
* ---
*
* A very simple and straightforward frontend for the RTLIL text
- * representation (as generated by the 'ilang' backend).
+ * representation.
*
*/
-#ifndef ILANG_FRONTEND_H
-#define ILANG_FRONTEND_H
+#ifndef RTLIL_FRONTEND_H
+#define RTLIL_FRONTEND_H
#include "kernel/yosys.h"
YOSYS_NAMESPACE_BEGIN
-namespace ILANG_FRONTEND {
+namespace RTLIL_FRONTEND {
extern std::istream *lexin;
extern RTLIL::Design *current_design;
extern bool flag_nooverwrite;
@@ -39,13 +39,13 @@ namespace ILANG_FRONTEND {
YOSYS_NAMESPACE_END
-extern int rtlil_frontend_ilang_yydebug;
-int rtlil_frontend_ilang_yylex(void);
-void rtlil_frontend_ilang_yyerror(char const *s);
-void rtlil_frontend_ilang_yyrestart(FILE *f);
-int rtlil_frontend_ilang_yyparse(void);
-int rtlil_frontend_ilang_yylex_destroy(void);
-int rtlil_frontend_ilang_yyget_lineno(void);
+extern int rtlil_frontend_yydebug;
+int rtlil_frontend_yylex(void);
+void rtlil_frontend_yyerror(char const *s);
+void rtlil_frontend_yyrestart(FILE *f);
+int rtlil_frontend_yyparse(void);
+int rtlil_frontend_yylex_destroy(void);
+int rtlil_frontend_yyget_lineno(void);
#endif
diff --git a/frontends/ilang/ilang_lexer.l b/frontends/rtlil/rtlil_lexer.l
index 3362ed641..e16413216 100644
--- a/frontends/ilang/ilang_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
@@ -18,7 +18,7 @@
* ---
*
* A very simple and straightforward frontend for the RTLIL text
- * representation (as generated by the 'ilang' backend).
+ * representation.
*
*/
@@ -30,20 +30,20 @@
#endif
#include <cstdlib>
-#include "frontends/ilang/ilang_frontend.h"
-#include "ilang_parser.tab.hh"
+#include "frontends/rtlil/rtlil_frontend.h"
+#include "rtlil_parser.tab.hh"
USING_YOSYS_NAMESPACE
#define YY_INPUT(buf,result,max_size) \
- result = readsome(*ILANG_FRONTEND::lexin, buf, max_size)
+ result = readsome(*RTLIL_FRONTEND::lexin, buf, max_size)
%}
%option yylineno
%option noyywrap
%option nounput
-%option prefix="rtlil_frontend_ilang_yy"
+%option prefix="rtlil_frontend_yy"
%x STRING
@@ -79,16 +79,16 @@ 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; }
[a-z]+ { return TOK_INVALID; }
-"\\"[^ \t\r\n]+ { rtlil_frontend_ilang_yylval.string = strdup(yytext); return TOK_ID; }
-"$"[^ \t\r\n]+ { rtlil_frontend_ilang_yylval.string = strdup(yytext); return TOK_ID; }
-"."[0-9]+ { rtlil_frontend_ilang_yylval.string = strdup(yytext); return TOK_ID; }
+"\\"[^ \t\r\n]+ { rtlil_frontend_yylval.string = strdup(yytext); return TOK_ID; }
+"$"[^ \t\r\n]+ { rtlil_frontend_yylval.string = strdup(yytext); return TOK_ID; }
-[0-9]+'[01xzm-]* { rtlil_frontend_ilang_yylval.string = strdup(yytext); return TOK_VALUE; }
+[0-9]+'[01xzm-]* { rtlil_frontend_yylval.string = strdup(yytext); return TOK_VALUE; }
-?[0-9]+ {
char *end = nullptr;
errno = 0;
@@ -98,7 +98,7 @@ USING_YOSYS_NAMESPACE
return TOK_INVALID; // literal out of range of long
if (value < INT_MIN || value > INT_MAX)
return TOK_INVALID; // literal out of range of int (relevant mostly for LP64 platforms)
- rtlil_frontend_ilang_yylval.integer = value;
+ rtlil_frontend_yylval.integer = value;
return TOK_INT;
}
@@ -131,7 +131,7 @@ USING_YOSYS_NAMESPACE
yystr[j++] = yystr[i++];
}
yystr[j] = 0;
- rtlil_frontend_ilang_yylval.string = yystr;
+ rtlil_frontend_yylval.string = yystr;
return TOK_STRING;
}
<STRING>. { yymore(); }
@@ -145,6 +145,6 @@ USING_YOSYS_NAMESPACE
%%
// this is a hack to avoid the 'yyinput defined but not used' error msgs
-void *rtlil_frontend_ilang_avoid_input_warnings() {
+void *rtlil_frontend_avoid_input_warnings() {
return (void*)&yyinput;
}
diff --git a/frontends/ilang/ilang_parser.y b/frontends/rtlil/rtlil_parser.y
index 879ef4af9..7d99b2c42 100644
--- a/frontends/ilang/ilang_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
@@ -18,15 +18,17 @@
* ---
*
* A very simple and straightforward frontend for the RTLIL text
- * representation (as generated by the 'ilang' backend).
+ * representation.
*
*/
+%require "3.0"
+
%{
#include <list>
-#include "frontends/ilang/ilang_frontend.h"
+#include "frontends/rtlil/rtlil_frontend.h"
YOSYS_NAMESPACE_BEGIN
-namespace ILANG_FRONTEND {
+namespace RTLIL_FRONTEND {
std::istream *lexin;
RTLIL::Design *current_design;
RTLIL::Module *current_module;
@@ -40,12 +42,12 @@ namespace ILANG_FRONTEND {
bool flag_nooverwrite, flag_overwrite, flag_lib;
bool delete_current_module;
}
-using namespace ILANG_FRONTEND;
+using namespace RTLIL_FRONTEND;
YOSYS_NAMESPACE_END
USING_YOSYS_NAMESPACE
%}
-%define api.prefix {rtlil_frontend_ilang_yy}
+%define api.prefix {rtlil_frontend_yy}
/* The union is defined in the header, so we need to provide all the
* includes it requires
@@ -53,7 +55,7 @@ USING_YOSYS_NAMESPACE
%code requires {
#include <string>
#include <vector>
-#include "frontends/ilang/ilang_frontend.h"
+#include "frontends/rtlil/rtlil_frontend.h"
}
%union {
@@ -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
@@ -87,7 +89,7 @@ input:
attrbuf.clear();
} design {
if (attrbuf.size() != 0)
- rtlil_frontend_ilang_yyerror("dangling attribute");
+ rtlil_frontend_yyerror("dangling attribute");
};
EOL:
@@ -111,7 +113,7 @@ module:
log("Ignoring blackbox re-definition of module %s.\n", $2);
delete_current_module = true;
} else if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute(ID::blackbox)) {
- rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of module %s.", $2).c_str());
+ rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of module %s.", $2).c_str());
} else if (flag_nooverwrite) {
log("Ignoring re-definition of module %s.\n", $2);
delete_current_module = true;
@@ -129,7 +131,7 @@ module:
free($2);
} module_body TOK_END {
if (attrbuf.size() != 0)
- rtlil_frontend_ilang_yyerror("dangling attribute");
+ rtlil_frontend_yyerror("dangling attribute");
current_module->fixup_ports();
if (delete_current_module)
delete current_module;
@@ -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);
};
@@ -172,12 +175,12 @@ autoidx_stmt:
wire_stmt:
TOK_WIRE {
- current_wire = current_module->addWire("$__ilang_frontend_tmp__");
+ current_wire = current_module->addWire("$__rtlil_frontend_tmp__");
current_wire->attributes = attrbuf;
attrbuf.clear();
} wire_options TOK_ID EOL {
if (current_module->wire($4) != nullptr)
- rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of wire %s.", $4).c_str());
+ rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of wire %s.", $4).c_str());
current_module->rename(current_wire, $4);
free($4);
};
@@ -187,7 +190,7 @@ wire_options:
current_wire->width = $3;
} |
wire_options TOK_WIDTH TOK_INVALID {
- rtlil_frontend_ilang_yyerror("ilang error: invalid wire width");
+ rtlil_frontend_yyerror("RTLIL error: invalid wire width");
} |
wire_options TOK_UPTO {
current_wire->upto = true;
@@ -222,7 +225,7 @@ memory_stmt:
attrbuf.clear();
} memory_options TOK_ID EOL {
if (current_module->memories.count($4) != 0)
- rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of memory %s.", $4).c_str());
+ rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of memory %s.", $4).c_str());
current_memory->name = $4;
current_module->memories[$4] = current_memory;
free($4);
@@ -243,7 +246,7 @@ memory_options:
cell_stmt:
TOK_CELL TOK_ID TOK_ID EOL {
if (current_module->cell($3) != nullptr)
- rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of cell %s.", $3).c_str());
+ rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of cell %s.", $3).c_str());
current_cell = current_module->addCell($3, $2);
current_cell->attributes = attrbuf;
attrbuf.clear();
@@ -271,7 +274,7 @@ cell_body:
} |
cell_body TOK_CONNECT TOK_ID sigspec EOL {
if (current_cell->hasPort($3))
- rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of cell port %s.", $3).c_str());
+ rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of cell port %s.", $3).c_str());
current_cell->setPort($3, *$4);
delete $4;
free($3);
@@ -281,11 +284,9 @@ cell_body:
proc_stmt:
TOK_PROCESS TOK_ID EOL {
if (current_module->processes.count($2) != 0)
- rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of process %s.", $2).c_str());
- current_process = new RTLIL::Process;
- current_process->name = $2;
+ rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of process %s.", $2).c_str());
+ 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();
@@ -342,7 +343,7 @@ case_body:
assign_stmt:
TOK_ASSIGN sigspec sigspec EOL {
if (attrbuf.size() != 0)
- rtlil_frontend_ilang_yyerror("dangling attribute");
+ rtlil_frontend_yyerror("dangling attribute");
case_stack.back()->actions.push_back(RTLIL::SigSig(*$2, *$3));
delete $2;
delete $3;
@@ -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:
@@ -438,19 +455,19 @@ sigspec:
} |
TOK_ID {
if (current_module->wire($1) == nullptr)
- rtlil_frontend_ilang_yyerror(stringf("ilang error: wire %s not found", $1).c_str());
+ rtlil_frontend_yyerror(stringf("RTLIL error: wire %s not found", $1).c_str());
$$ = new RTLIL::SigSpec(current_module->wire($1));
free($1);
} |
sigspec '[' TOK_INT ']' {
if ($3 >= $1->size() || $3 < 0)
- rtlil_frontend_ilang_yyerror("bit index out of range");
+ rtlil_frontend_yyerror("bit index out of range");
$$ = new RTLIL::SigSpec($1->extract($3));
delete $1;
} |
sigspec '[' TOK_INT ':' TOK_INT ']' {
if ($3 >= $1->size() || $3 < 0 || $3 < $5)
- rtlil_frontend_ilang_yyerror("invalid slice");
+ rtlil_frontend_yyerror("invalid slice");
$$ = new RTLIL::SigSpec($1->extract($5, $3 - $5 + 1));
delete $1;
} |
@@ -477,7 +494,7 @@ sigspec_list: sigspec_list_reversed {
conn_stmt:
TOK_CONNECT sigspec sigspec EOL {
if (attrbuf.size() != 0)
- rtlil_frontend_ilang_yyerror("dangling attribute");
+ rtlil_frontend_yyerror("dangling attribute");
current_module->connect(*$2, *$3);
delete $2;
delete $3;
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 9785b8eff..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
@@ -21,6 +21,7 @@
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/log.h"
+#include "libs/sha1/sha1.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -42,19 +43,26 @@ 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"
-#ifndef SYMBIOTIC_VERIFIC_API_VERSION
-# error "Only Symbiotic EDA flavored Verific is supported. Please contact office@symbioticeda.com for commercial support for Yosys+Verific."
+#ifdef VERIFIC_VHDL_SUPPORT
+#include "vhdl_file.h"
+#include "VhdlUnits.h"
+#endif
+
+#ifdef YOSYSHQ_VERIFIC_EXTENSIONS
+#include "InitialAssertions.h"
#endif
-#if SYMBIOTIC_VERIFIC_API_VERSION < 202006
-# error "Please update your version of Symbiotic EDA flavored Verific."
+#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 < 20210801
+# error "Please update your version of YosysHQ flavored Verific."
#endif
#ifdef __clang__
@@ -170,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;
@@ -188,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;
}
@@ -197,13 +207,19 @@ 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>"
+ // Expect "<binary>" or plain <binary>
auto p = v;
if (p) {
- if (*p != '"')
- p = nullptr;
- else {
+ if (*p != '"') {
+ auto l = strlen(p);
+ auto q = (char*)malloc(l+1);
+ strncpy(q, p, l);
+ q[l] = '\0';
+ for(char *ptr = q; *ptr; ++ptr )*ptr = tolower(*ptr);
+ attributes.emplace(stringf("\\enum_value_%s", q), RTLIL::escape_id(k));
+ } else {
auto *q = p+1;
for (; *q != '"'; q++)
if (*q != '0' && *q != '1') {
@@ -212,17 +228,22 @@ void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &att
}
if (p && *(q+1) != '\0')
p = nullptr;
+
+ if (p != nullptr)
+ {
+ auto l = strlen(p);
+ auto q = (char*)malloc(l+1-2);
+ strncpy(q, p+1, l-2);
+ q[l-2] = '\0';
+ attributes.emplace(stringf("\\enum_value_%s", q), RTLIL::escape_id(k));
+ free(q);
+ }
}
}
if (p == nullptr)
- log_error("Expected TypeRange value '%s' to be of form \"<binary>\".\n", v);
- auto l = strlen(p);
- auto q = (char*)malloc(l+1-2);
- strncpy(q, p+1, l-2);
- q[l-2] = '\0';
- attributes.emplace(stringf("\\enum_value_%s", q), RTLIL::escape_id(k));
- free(q);
+ log_error("Expected TypeRange value '%s' to be of form \"<binary>\" or <binary>.\n", v);
}
+#endif
}
}
}
@@ -357,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;
}
@@ -396,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;
}
@@ -457,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;
@@ -506,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)
@@ -713,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;
}
@@ -778,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
@@ -854,6 +993,21 @@ void VerificImporter::merge_past_ffs(pool<RTLIL::Cell*> &candidates)
merge_past_ffs_clock(it.second, it.first.first, it.first.second);
}
+static std::string sha1_if_contain_spaces(std::string str)
+{
+ if(str.find_first_of(' ') != std::string::npos) {
+ std::size_t open = str.find_first_of('(');
+ std::size_t closed = str.find_last_of(')');
+ if (open != std::string::npos && closed != std::string::npos) {
+ std::string content = str.substr(open + 1, closed - open - 1);
+ return str.substr(0, open + 1) + sha1(content) + str.substr(closed);
+ } else {
+ return sha1(str);
+ }
+ }
+ return str;
+}
+
void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::set<Netlist*> &nl_todo, bool norename)
{
std::string netlist_name = nl->GetAtt(" \\top") ? nl->CellBaseName() : nl->Owner()->Name();
@@ -867,7 +1021,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
module_name += nl->Name();
module_name += ")";
}
- module_name = "\\" + module_name;
+ module_name = "\\" + sha1_if_contain_spaces(module_name);
}
netlist = nl;
@@ -888,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;
@@ -936,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));
@@ -974,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) {
@@ -1445,6 +1609,18 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
continue;
}
+ 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);
+
+ if (!mode_keep)
+ continue;
+ }
+
if (!mode_keep && verific_sva_prims.count(inst->Type())) {
if (verific_verbose)
log(" skipping SVA cell in non k-mode\n");
@@ -1492,7 +1668,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
inst_type += inst->View()->Name();
inst_type += ")";
}
- inst_type = "\\" + inst_type;
+ inst_type = "\\" + sha1_if_contain_spaces(inst_type);
}
RTLIL::Cell *cell = module->addCell(inst_name, inst_type);
@@ -1716,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);
}
@@ -1748,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);
@@ -1759,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
@@ -1911,17 +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_EXTENSIONS
+ InitialAssertions::Rewrite("work", &verific_params);
+#endif
+
if (top.empty()) {
netlists = hier_tree::ElaborateAll(&veri_libs, &vhdl_libs, &verific_params);
}
@@ -1942,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);
}
@@ -1984,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();
@@ -2027,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");
@@ -2035,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");
@@ -2144,11 +2428,85 @@ struct VerificPass : public Pass {
log(" Dump the Verific netlist as a verilog file.\n");
log("\n");
log("\n");
- log("Use Symbiotic EDA Suite if you need Yosys+Verifc.\n");
- log("https://www.symbioticeda.com/seda-suite\n");
+ log(" verific [-work <libname>] -pp [options] <filename> [<module>]..\n");
+ log("\n");
+ log("Pretty print design (or just module) to the specified file from the\n");
+ log("specified library. (default library when -work is not present: \"work\")\n");
+ log("\n");
+ log("Pretty print options:\n");
+ log("\n");
+ log(" -verilog\n");
+ log(" Save output for Verilog/SystemVerilog design modules (default).\n");
+ log("\n");
+ log(" -vhdl\n");
+ log(" Save output for VHDL design units.\n");
+ log("\n");
+ log("\n");
+ log(" verific -app <application>..\n");
+ log("\n");
+ log("Execute YosysHQ formal application on loaded Verilog files.\n");
+ log("\n");
+ log("Application options:\n");
+ log("\n");
+ log(" -module <module>\n");
+ log(" Run formal application only on specified module.\n");
+ log("\n");
+ log(" -blacklist <filename[:lineno]>\n");
+ log(" Do not run application on modules from files that match the filename\n");
+ log(" or filename and line number if provided in such format.\n");
+ log(" Parameter can also contain comma separated list of file locations.\n");
+ log("\n");
+ log(" -blfile <file>\n");
+ log(" Do not run application on locations specified in file, they can represent filename\n");
+ log(" or filename and location in file.\n");
+ log("\n");
+ log("Applications:\n");
+ log("\n");
+#if defined(YOSYS_ENABLE_VERIFIC) && defined(YOSYSHQ_VERIFIC_FORMALAPPS)
+ VerificFormalApplications vfa;
+ log("%s\n",vfa.GetHelp().c_str());
+#else
+ log(" WARNING: Applications only available in commercial build.\n");
+
+#endif
+ log("\n");
+ log("\n");
+ log(" verific -template <name> <top_module>..\n");
+ log("\n");
+ log("Generate template for specified top module of loaded design.\n");
+ log("\n");
+ log("Template options:\n");
+ log("\n");
+ log(" -out\n");
+ log(" Specifies output file for generated template, by default output is stdout\n");
+ log("\n");
+ log(" -chparam name value \n");
+ log(" Generate template using this parameter value. Otherwise default parameter\n");
+ log(" values will be used for templat generate functionality. This option\n");
+ log(" can be specified multiple times to override multiple parameters.\n");
+ log(" String values must be passed in double quotes (\").\n");
log("\n");
- log("Contact office@symbioticeda.com for free evaluation\n");
- log("binaries of Symbiotic EDA Suite.\n");
+ log("Templates:\n");
+ log("\n");
+#if defined(YOSYS_ENABLE_VERIFIC) && defined(YOSYSHQ_VERIFIC_TEMPLATES)
+ VerificTemplateGenerator vfg;
+ log("%s\n",vfg.GetHelp().c_str());
+#else
+ 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");
+ log("Contact office@yosyshq.com for free evaluation\n");
+ log("binaries of YosysHQ Tabby CAD Suite.\n");
log("\n");
}
#ifdef YOSYS_ENABLE_VERIFIC
@@ -2159,11 +2517,11 @@ struct VerificPass : public Pass {
if (check_noverific_env())
log_cmd_error("This version of Yosys is built without Verific support.\n"
"\n"
- "Use Symbiotic EDA Suite if you need Yosys+Verifc.\n"
- "https://www.symbioticeda.com/seda-suite\n"
+ "Use YosysHQ Tabby CAD Suite if you need Yosys+Verific.\n"
+ "https://www.yosyshq.com/\n"
"\n"
- "Contact office@symbioticeda.com for free evaluation\n"
- "binaries of Symbiotic EDA Suite.\n");
+ "Contact office@yosyshq.com for free evaluation\n"
+ "binaries of YosysHQ Tabby CAD Suite.\n");
log_header(design, "Executing VERIFIC (loading SystemVerilog and VHDL designs using Verific).\n");
@@ -2172,21 +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("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);
@@ -2197,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
@@ -2293,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"))
{
@@ -2312,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");
@@ -2340,13 +2770,16 @@ struct VerificPass : public Pass {
while (argidx < GetSize(args))
file_names.Insert(args[argidx++].c_str());
- if (!veri_file::AnalyzeMultipleFiles(&file_names, verilog_mode, work.c_str(), veri_file::MFCU))
+ 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");
+ }
verific_import_pending = true;
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++)
@@ -2382,7 +2815,236 @@ struct VerificPass : public Pass {
verific_import_pending = true;
goto check_error;
}
+#endif
+
+#ifdef YOSYSHQ_VERIFIC_FORMALAPPS
+ if (argidx < GetSize(args) && args[argidx] == "-app")
+ {
+ if (!(argidx+1 < GetSize(args)))
+ cmd_error(args, argidx, "No formal application specified.\n");
+
+ VerificFormalApplications vfa;
+ auto apps = vfa.GetApps();
+ std::string app = args[++argidx];
+ std::vector<std::string> blacklists;
+ if (apps.find(app) == apps.end())
+ log_cmd_error("Application '%s' does not exist.\n", app.c_str());
+
+ FormalApplication *application = apps[app];
+ application->setLogger([](std::string msg) { log("%s",msg.c_str()); } );
+ VeriModule *selected_module = nullptr;
+
+ for (argidx++; argidx < GetSize(args); argidx++) {
+ std::string error;
+ if (application->checkParams(args, argidx, error)) {
+ if (!error.empty())
+ cmd_error(args, argidx, error);
+ continue;
+ }
+
+ if (args[argidx] == "-module" && argidx < GetSize(args)) {
+ if (!(argidx+1 < GetSize(args)))
+ cmd_error(args, argidx+1, "No module name specified.\n");
+ std::string module = args[++argidx];
+ VeriLibrary* veri_lib = veri_file::GetLibrary(work.c_str(), 1);
+ selected_module = veri_lib ? veri_lib->GetModule(module.c_str(), 1) : nullptr;
+ if (!selected_module) {
+ log_error("Can't find module '%s'.\n", module.c_str());
+ }
+ continue;
+ }
+ if (args[argidx] == "-blacklist" && argidx < GetSize(args)) {
+ if (!(argidx+1 < GetSize(args)))
+ cmd_error(args, argidx+1, "No blacklist specified.\n");
+
+ std::string line = args[++argidx];
+ std::string p;
+ while (!(p = next_token(line, ",\t\r\n ")).empty())
+ blacklists.push_back(p);
+ continue;
+ }
+ if (args[argidx] == "-blfile" && argidx < GetSize(args)) {
+ if (!(argidx+1 < GetSize(args)))
+ cmd_error(args, argidx+1, "No blacklist file specified.\n");
+ std::string fn = args[++argidx];
+ std::ifstream f(fn);
+ if (f.fail())
+ log_cmd_error("Can't open blacklist file '%s'!\n", fn.c_str());
+
+ std::string line,p;
+ while (std::getline(f, line)) {
+ while (!(p = next_token(line, ",\t\r\n ")).empty())
+ blacklists.push_back(p);
+ }
+ continue;
+ }
+ break;
+ }
+ if (argidx < GetSize(args))
+ cmd_error(args, argidx, "unknown option/parameter");
+
+ application->setBlacklists(&blacklists);
+ application->setSingleModuleMode(selected_module!=nullptr);
+
+ const char *err = application->validate();
+ if (err)
+ cmd_error(args, argidx, err);
+
+ MapIter mi;
+ VeriLibrary *veri_lib = veri_file::GetLibrary(work.c_str(), 1);
+ log("Running formal application '%s'.\n", app.c_str());
+
+ if (selected_module) {
+ std::string out;
+ if (!application->execute(selected_module, out))
+ log_error("%s", out.c_str());
+ }
+ else {
+ VeriModule *module ;
+ FOREACH_VERILOG_MODULE_IN_LIBRARY(veri_lib, mi, module) {
+ std::string out;
+ if (!application->execute(module, out)) {
+ log_error("%s", out.c_str());
+ break;
+ }
+ }
+ }
+ goto check_error;
+ }
+#endif
+ if (argidx < GetSize(args) && args[argidx] == "-pp")
+ {
+ const char* filename = nullptr;
+ 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;
+ }
+
+ if (args[argidx].compare(0, 1, "-") == 0) {
+ cmd_error(args, argidx, "unknown option");
+ goto check_error;
+ }
+
+ if (!filename) {
+ filename = args[argidx].c_str();
+ continue;
+ }
+ if (module)
+ log_cmd_error("Only one module can be specified.\n");
+ module = args[argidx].c_str();
+ }
+
+ if (argidx < GetSize(args))
+ cmd_error(args, argidx, "unknown option/parameter");
+
+ if (!filename)
+ 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;
+ }
+
+#ifdef YOSYSHQ_VERIFIC_TEMPLATES
+ if (argidx < GetSize(args) && args[argidx] == "-template")
+ {
+ if (!(argidx+1 < GetSize(args)))
+ cmd_error(args, argidx+1, "No template type specified.\n");
+
+ VerificTemplateGenerator vfg;
+ auto gens = vfg.GetGenerators();
+ std::string app = args[++argidx];
+ if (gens.find(app) == gens.end())
+ log_cmd_error("Template generator '%s' does not exist.\n", app.c_str());
+ TemplateGenerator *generator = gens[app];
+ 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;
+ if (!veri_module) {
+ log_error("Can't find module/unit '%s'.\n", module.c_str());
+ }
+
+ log("Template '%s' is running for module '%s'.\n", app.c_str(),module.c_str());
+
+ Map parameters(STRING_HASH);
+ const char *out_filename = nullptr;
+
+ for (argidx++; argidx < GetSize(args); argidx++) {
+ std::string error;
+ if (generator->checkParams(args, argidx, error)) {
+ if (!error.empty())
+ cmd_error(args, argidx, error);
+ continue;
+ }
+
+ if (args[argidx] == "-chparam" && argidx < GetSize(args)) {
+ if (!(argidx+1 < GetSize(args)))
+ cmd_error(args, argidx+1, "No param name specified.\n");
+ if (!(argidx+2 < GetSize(args)))
+ cmd_error(args, argidx+2, "No param value specified.\n");
+
+ const std::string &key = args[++argidx];
+ const std::string &value = args[++argidx];
+ unsigned new_insertion = parameters.Insert(key.c_str(), value.c_str(),
+ 1 /* force_overwrite */);
+ if (!new_insertion)
+ log_warning_noprefix("-chparam %s already specified: overwriting.\n", key.c_str());
+ continue;
+ }
+ if (args[argidx] == "-out" && argidx < GetSize(args)) {
+ if (!(argidx+1 < GetSize(args)))
+ cmd_error(args, argidx+1, "No output file specified.\n");
+ out_filename = args[++argidx].c_str();
+ continue;
+ }
+
+ break;
+ }
+ if (argidx < GetSize(args))
+ cmd_error(args, argidx, "unknown option/parameter");
+
+ const char *err = generator->validate();
+ if (err)
+ cmd_error(args, argidx, err);
+
+ std::string val;
+ if (!generator->generate(veri_module, val, &parameters))
+ log_error("%s", val.c_str());
+
+ FILE *of = stdout;
+ if (out_filename) {
+ of = fopen(out_filename, "w");
+ if (of == nullptr)
+ log_error("Can't open '%s' for writing: %s\n", out_filename, strerror(errno));
+ log("Writing output to '%s'\n",out_filename);
+ }
+ fprintf(of, "%s\n",val.c_str());
+ fflush(of);
+ if (of!=stdout)
+ fclose(of);
+ goto check_error;
+ }
+#endif
if (GetSize(args) > argidx && args[argidx] == "-import")
{
std::set<Netlist*> nl_todo, nl_done;
@@ -2467,15 +3129,20 @@ struct VerificPass : public Pass {
std::set<std::string> top_mod_names;
+#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);
@@ -2491,40 +3158,44 @@ struct VerificPass : public Pass {
if (argidx == GetSize(args))
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++)
{
const char *name = args[argidx].c_str();
top_mod_names.insert(name);
- VeriLibrary* veri_lib = veri_file::GetLibrary(work.c_str(), 1);
-
- if (veri_lib) {
- VeriModule *veri_module = veri_lib->GetModule(name, 1);
- if (veri_module) {
- log("Adding Verilog module '%s' to elaboration queue.\n", name);
- veri_modules.InsertLast(veri_module);
- continue;
- }
- // Also elaborate all root modules since they may contain bind statements
- MapIter mi;
- FOREACH_VERILOG_MODULE_IN_LIBRARY(veri_lib, mi, veri_module) {
- if (!veri_module->IsRootModule()) continue;
- veri_modules.InsertLast(veri_module);
- }
+ VeriModule *veri_module = veri_lib ? veri_lib->GetModule(name, 1) : nullptr;
+ if (veri_module) {
+ log("Adding Verilog module '%s' to elaboration queue.\n", name);
+ veri_modules.InsertLast(veri_module);
+ continue;
}
-
- VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary(work.c_str(), 1);
- VhdlDesignUnit *vhdl_unit = vhdl_lib->GetPrimUnit(name);
+#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);
}
+ if (veri_lib) {
+ // Also elaborate all root modules since they may contain bind statements
+ MapIter mi;
+ VeriModule *veri_module;
+ FOREACH_VERILOG_MODULE_IN_LIBRARY(veri_lib, mi, veri_module) {
+ if (!veri_module->IsRootModule()) continue;
+ veri_modules.InsertLast(veri_module);
+ }
+ }
+
log("Running hier_tree::Elaborate().\n");
Array *netlists = hier_tree::Elaborate(&veri_modules, &vhdl_units, &parameters);
Netlist *nl;
@@ -2571,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();
@@ -2579,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:
@@ -2590,11 +3322,11 @@ struct VerificPass : public Pass {
void execute(std::vector<std::string>, RTLIL::Design *) override {
log_cmd_error("This version of Yosys is built without Verific support.\n"
"\n"
- "Use Symbiotic EDA Suite if you need Yosys+Verifc.\n"
- "https://www.symbioticeda.com/seda-suite\n"
+ "Use YosysHQ Tabby CAD Suite if you need Yosys+Verific.\n"
+ "https://www.yosyshq.com/\n"
"\n"
- "Contact office@symbioticeda.com for free evaluation\n"
- "binaries of Symbiotic EDA Suite.\n");
+ "Contact office@yosyshq.com for free evaluation\n"
+ "binaries of YosysHQ Tabby CAD Suite.\n");
}
#endif
} VerificPass;
@@ -2614,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");
@@ -2695,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";
@@ -2704,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 49c0c40ac..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
@@ -1040,8 +1040,14 @@ struct VerificSvaImporter
[[noreturn]] void parser_error(Instance *inst)
{
- parser_error(stringf("Verific SVA primitive %s (%s) is currently unsupported in this context",
- inst->View()->Owner()->Name(), inst->Name()), inst->Linefile());
+ std::string msg;
+ if (inst->Type() == PRIM_SVA_MATCH_ITEM_TRIGGER || inst->Type() == PRIM_SVA_MATCH_ITEM_ASSIGN)
+ {
+ msg = "SVA sequences with local variable assignments are currently not supported.\n";
+ }
+
+ parser_error(stringf("%sVerific SVA primitive %s (%s) is currently unsupported in this context",
+ msg.c_str(), inst->View()->Owner()->Name(), inst->Name()), inst->Linefile());
}
dict<Net*, bool, hash_ptr_ops> check_expression_cache;
@@ -1753,6 +1759,11 @@ struct VerificSvaImporter
clocking.addDff(NEW_ID, sig_en, sig_en_q, State::S0);
}
+ // accept in disable case
+
+ if (clocking.disable_sig != State::S0)
+ sig_a_q = module->Or(NEW_ID, sig_a_q, clocking.disable_sig);
+
// generate fair/live cell
RTLIL::Cell *c = nullptr;
diff --git a/frontends/verilog/Makefile.inc b/frontends/verilog/Makefile.inc
index cf9b9531e..2c923f0b7 100644
--- a/frontends/verilog/Makefile.inc
+++ b/frontends/verilog/Makefile.inc
@@ -6,7 +6,7 @@ GENFILES += frontends/verilog/verilog_lexer.cc
frontends/verilog/verilog_parser.tab.cc: frontends/verilog/verilog_parser.y
$(Q) mkdir -p $(dir $@)
- $(P) $(BISON) -o $@ -d -r all -b frontends/verilog/verilog_parser $<
+ $(P) $(BISON) -Wall -Werror -o $@ -d -r all -b frontends/verilog/verilog_parser $<
frontends/verilog/verilog_parser.tab.hh: frontends/verilog/verilog_parser.tab.cc
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 ea23139e2..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) {
@@ -321,7 +332,6 @@ struct define_body_t
define_map_t::define_map_t()
{
add("YOSYS", "1");
- add(formal_mode ? "FORMAL" : "SYNTHESIS", "1");
}
// We must define this destructor here (rather than relying on the default), because we need to
@@ -335,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) {
@@ -391,13 +406,16 @@ static void input_file(std::istream &f, std::string filename)
// the argument list); false if we finished with ','.
static bool read_argument(std::string &dest)
{
+ skip_spaces();
std::vector<char> openers;
for (;;) {
- skip_spaces();
std::string tok = next_token(true);
if (tok == ")") {
- if (openers.empty())
+ if (openers.empty()) {
+ while (dest.size() && (dest.back() == ' ' || dest.back() == '\t'))
+ dest = dest.substr(0, dest.size() - 1);
return true;
+ }
if (openers.back() != '(')
log_error("Mismatched brackets in macro argument: %c and %c.\n",
openers.back(), tok[0]);
@@ -438,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("\"");
@@ -448,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;
}
}
@@ -475,7 +503,16 @@ static bool try_expand_macro(define_map_t &defines, std::string &tok)
std::string name = tok.substr(1);
std::string skipped_spaces = skip_spaces();
tok = next_token(false);
- if (tok == "(" && body->has_args) {
+ if (body->has_args) {
+ if (tok != "(") {
+ if (tok.size() == 1 && iscntrl(tok[0])) {
+ char buf[5];
+ snprintf(buf, sizeof(buf), "\\x%02x", tok[0]);
+ tok = buf;
+ }
+ log_error("Expected to find '(' to begin macro arguments for '%s', but instead found '%s'\n",
+ name.c_str(), tok.c_str());
+ }
std::vector<std::string> args;
bool done = false;
while (!done) {
@@ -484,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 {
@@ -714,9 +755,19 @@ 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;
- bool in_elseif = false;
+ 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();
input_buffer.clear();
@@ -732,42 +783,70 @@ frontend_verilog_preproc(std::istream &f,
if (tok == "`endif") {
if (ifdef_fail_level > 0)
ifdef_fail_level--;
- if (ifdef_fail_level == 0)
- in_elseif = false;
+ else if (ifdef_pass_level > 0)
+ ifdef_pass_level--;
+ else
+ log_error("Found %s outside of macro conditional branch!\n", tok.c_str());
continue;
}
if (tok == "`else") {
- if (ifdef_fail_level == 0)
+ if (ifdef_fail_level == 0) {
+ if (ifdef_pass_level == 0)
+ log_error("Found %s outside of macro conditional branch!\n", tok.c_str());
+ ifdef_pass_level--;
ifdef_fail_level = 1;
- else if (ifdef_fail_level == 1 && !in_elseif)
+ ifdef_already_satisfied = true;
+ } else if (ifdef_fail_level == 1 && !ifdef_already_satisfied) {
ifdef_fail_level = 0;
+ ifdef_pass_level++;
+ ifdef_already_satisfied = true;
+ }
continue;
}
if (tok == "`elsif") {
skip_spaces();
std::string name = next_token(true);
- if (ifdef_fail_level == 0)
- ifdef_fail_level = 1, in_elseif = true;
- else if (ifdef_fail_level == 1 && defines.find(name))
- ifdef_fail_level = 0, in_elseif = true;
+ if (ifdef_fail_level == 0) {
+ if (ifdef_pass_level == 0)
+ log_error("Found %s outside of macro conditional branch!\n", tok.c_str());
+ 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++;
+ ifdef_already_satisfied = true;
+ }
continue;
}
if (tok == "`ifdef") {
skip_spaces();
std::string name = next_token(true);
- if (ifdef_fail_level > 0 || !defines.find(name))
+ if (ifdef_fail_level > 0 || !defines.find(name)) {
ifdef_fail_level++;
+ } else {
+ ifdef_pass_level++;
+ ifdef_already_satisfied = true;
+ }
+ if (ifdef_fail_level == 1)
+ ifdef_already_satisfied = false;
continue;
}
if (tok == "`ifndef") {
skip_spaces();
std::string name = next_token(true);
- if (ifdef_fail_level > 0 || defines.find(name))
+ if (ifdef_fail_level > 0 || defines.find(name)) {
ifdef_fail_level++;
+ } else {
+ ifdef_pass_level++;
+ ifdef_already_satisfied = true;
+ }
+ if (ifdef_fail_level == 1)
+ ifdef_already_satisfied = false;
continue;
}
@@ -780,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) {
@@ -887,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 2e9c9b2e2..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 {
@@ -84,6 +82,9 @@ struct VerilogFrontend : public Frontend {
log(" enable support for SystemVerilog assertions and some Yosys extensions\n");
log(" replace the implicit -D SYNTHESIS with -D FORMAL\n");
log("\n");
+ log(" -nosynthesis\n");
+ log(" don't add implicit -D SYNTHESIS\n");
+ log("\n");
log(" -noassert\n");
log(" ignore assert() statements\n");
log("\n");
@@ -225,8 +226,8 @@ struct VerilogFrontend : public Frontend {
log("the syntax of the code, rather than to rely on read_verilog for that.\n");
log("\n");
log("Depending on if read_verilog is run in -formal mode, either the macro\n");
- log("SYNTHESIS or FORMAL is defined automatically. In addition, read_verilog\n");
- log("always defines the macro YOSYS.\n");
+ log("SYNTHESIS or FORMAL is defined automatically, unless -nosynthesis is used.\n");
+ log("In addition, read_verilog always defines the macro YOSYS.\n");
log("\n");
log("See the Yosys README file for a list of non-standard Verilog features\n");
log("supported by the Yosys Verilog front-end.\n");
@@ -255,6 +256,7 @@ struct VerilogFrontend : public Frontend {
bool flag_defer = false;
bool flag_noblackbox = false;
bool flag_nowb = false;
+ bool flag_nosynthesis = false;
define_map_t defines_map;
std::list<std::string> include_dirs;
@@ -282,6 +284,10 @@ struct VerilogFrontend : public Frontend {
formal_mode = true;
continue;
}
+ if (arg == "-nosynthesis") {
+ flag_nosynthesis = true;
+ continue;
+ }
if (arg == "-noassert") {
noassert_mode = true;
continue;
@@ -446,6 +452,10 @@ struct VerilogFrontend : public Frontend {
}
break;
}
+
+ if (formal_mode || !flag_nosynthesis)
+ defines_map.add(formal_mode ? "FORMAL" : "SYNTHESIS", "1");
+
extra_args(f, filename, args, argidx);
log_header(design, "Executing Verilog-2005 frontend: %s\n", filename.c_str());
@@ -472,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();
@@ -494,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 f2241066f..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;
}
}
@@ -234,7 +236,7 @@ static bool isUserType(std::string &s)
"automatic" { return TOK_AUTOMATIC; }
"unique" { SV_KEYWORD(TOK_UNIQUE); }
-"unique0" { SV_KEYWORD(TOK_UNIQUE); }
+"unique0" { SV_KEYWORD(TOK_UNIQUE0); }
"priority" { SV_KEYWORD(TOK_PRIORITY); }
"always_comb" { SV_KEYWORD(TOK_ALWAYS_COMB); }
@@ -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); }
@@ -267,6 +270,7 @@ static bool isUserType(std::string &s)
"int" { SV_KEYWORD(TOK_INT); }
"byte" { SV_KEYWORD(TOK_BYTE); }
"shortint" { SV_KEYWORD(TOK_SHORTINT); }
+"longint" { SV_KEYWORD(TOK_LONGINT); }
"eventually" { if (formal_mode) return TOK_EVENTUALLY; SV_KEYWORD(TOK_EVENTUALLY); }
"s_eventually" { if (formal_mode) return TOK_EVENTUALLY; SV_KEYWORD(TOK_EVENTUALLY); }
@@ -275,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; }
@@ -430,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);
@@ -446,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;
@@ -455,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;
@@ -528,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 656910c0c..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)
@@ -210,17 +226,95 @@ static AstNode *checkRange(AstNode *type_node, AstNode *range_node)
return range_node;
}
-static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode)
+static void rewriteRange(AstNode *rangeNode)
{
- node->type = AST_MEMORY;
if (rangeNode->type == AST_RANGE && rangeNode->children.size() == 1) {
// SV array size [n], rewrite as [n-1:0]
rangeNode->children[0] = new AstNode(AST_SUB, rangeNode->children[0], AstNode::mkconst_int(1, true));
rangeNode->children.push_back(AstNode::mkconst_int(0, false));
}
+}
+
+static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode)
+{
+ node->type = AST_MEMORY;
+ if (rangeNode->type == AST_MULTIRANGE) {
+ for (auto *itr : rangeNode->children)
+ rewriteRange(itr);
+ } else
+ rewriteRange(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}
@@ -244,6 +338,8 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode)
struct specify_rise_fall *specify_rise_fall_ptr;
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
@@ -256,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
@@ -268,18 +364,25 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode)
%token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED
%token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_PROPERTY TOK_ENUM TOK_TYPEDEF
%token TOK_RAND TOK_CONST TOK_CHECKER TOK_ENDCHECKER TOK_EVENTUALLY
-%token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_PRIORITY
-%token TOK_STRUCT TOK_PACKED TOK_UNSIGNED TOK_INT TOK_BYTE TOK_SHORTINT TOK_UNION
-%token TOK_OR_ASSIGN TOK_XOR_ASSIGN TOK_AND_ASSIGN TOK_SUB_ASSIGN
-
-%type <ast> range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int
-%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list
+%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_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
-%type <boolean> opt_signed opt_property unique_case_attr always_comb_or_latch always_or_always_ff
+%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 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
@@ -299,14 +402,14 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode)
%left '+' '-'
%left '*' '/' '%'
%left OP_POW
-%left OP_CAST
-%right UNARY_OPS
+%precedence OP_CAST
+%precedence UNARY_OPS
%define parse.error verbose
%define parse.lac full
-%nonassoc FAKE_THEN
-%nonassoc TOK_ELSE
+%precedence FAKE_THEN
+%precedence TOK_ELSE
%debug
%locations
@@ -333,7 +436,8 @@ design:
typedef_decl design |
package design |
interface design |
- /* empty */;
+ bind_directive design |
+ %empty;
attr:
{
@@ -355,7 +459,7 @@ attr_opt:
attr_opt ATTR_BEGIN opt_attr_list ATTR_END {
SET_RULE_LOC(@$, @2, @$);
}|
- /* empty */;
+ %empty;
defattr:
DEFATTR_BEGIN {
@@ -376,7 +480,7 @@ defattr:
} DEFATTR_END;
opt_attr_list:
- attr_list | /* empty */;
+ attr_list | %empty;
attr_list:
attr_assign |
@@ -436,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'.",
@@ -444,18 +547,21 @@ 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();
};
module_para_opt:
- '#' '(' { astbuf1 = nullptr; } module_para_list { if (astbuf1) delete astbuf1; } ')' | /* empty */;
+ '#' '(' { astbuf1 = nullptr; } module_para_list { if (astbuf1) delete astbuf1; } ')' | %empty;
module_para_list:
single_module_para | module_para_list ',' single_module_para;
single_module_para:
- /* empty */ |
+ %empty |
attr TOK_PARAMETER {
if (astbuf1) delete astbuf1;
astbuf1 = new AstNode(AST_PARAMETER);
@@ -471,33 +577,34 @@ single_module_para:
single_param_decl;
module_args_opt:
- '(' ')' | /* empty */ | '(' module_args optional_comma ')';
+ '(' ')' | %empty | '(' module_args optional_comma ')';
module_args:
module_arg | module_args ',' module_arg;
optional_comma:
- ',' | /* empty */;
+ ',' | %empty;
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.");
} |
- /* empty */;
+ %empty;
module_arg:
TOK_ID {
@@ -534,8 +641,9 @@ module_arg:
node->str = *$4;
SET_AST_NODE_LOC(node, @4, @4);
node->port_id = ++port_counter;
- if ($3 != NULL)
- node->children.push_back($3);
+ AstNode *range = checkRange(node, $3);
+ if (range != NULL)
+ node->children.push_back(range);
if (!node->is_input && !node->is_output)
frontend_verilog_yyerror("Module port `%s' is neither input nor output.", $4->c_str());
if (node->is_reg && node->is_input && !node->is_output && !sv_mode)
@@ -560,20 +668,18 @@ 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();
};
package_body:
- package_body package_body_stmt
- | // optional
- ;
+ 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 {
@@ -599,42 +705,100 @@ interface:
};
interface_body:
- interface_body interface_body_stmt |;
+ interface_body interface_body_stmt | %empty;
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; } |
+ expr ':' expr ':' expr { delete $1; delete $3; delete $5; };
non_opt_delay:
'#' TOK_ID { delete $2; } |
'#' TOK_CONSTVAL { delete $2; } |
'#' TOK_REALVAL { delete $2; } |
- '#' '(' expr ')' { delete $3; } |
- '#' '(' expr ':' expr ':' expr ')' { delete $3; delete $5; delete $7; };
+ '#' '(' mintypmax_expr ')' |
+ '#' '(' mintypmax_expr ',' mintypmax_expr ')' |
+ '#' '(' mintypmax_expr ',' mintypmax_expr ',' mintypmax_expr ')';
delay:
- non_opt_delay | /* empty */;
+ non_opt_delay | %empty;
-wire_type:
- {
- astbuf3 = new AstNode(AST_WIRE);
- current_wire_rand = false;
- current_wire_const = false;
- } wire_type_token_list {
- $$ = astbuf3;
- SET_RULE_LOC(@$, @2, @$);
- };
+io_wire_type:
+ { astbuf3 = new AstNode(AST_WIRE); current_wire_rand = false; current_wire_const = false; }
+ wire_type_token_io wire_type_const_rand opt_wire_type_token wire_type_signedness
+ { $$ = astbuf3; SET_RULE_LOC(@$, @2, @$); };
-wire_type_token_list:
- wire_type_token |
- wire_type_token_list wire_type_token |
- wire_type_token_io |
- hierarchical_type_id {
- astbuf3->is_custom_type = true;
- astbuf3->children.push_back(new AstNode(AST_WIRETYPE));
- astbuf3->children.back()->str = *$1;
- delete $1;
- };
+non_io_wire_type:
+ { astbuf3 = new AstNode(AST_WIRE); current_wire_rand = false; current_wire_const = false; }
+ wire_type_const_rand wire_type_token wire_type_signedness
+ { $$ = astbuf3; SET_RULE_LOC(@$, @2, @$); };
+
+wire_type:
+ io_wire_type |
+ non_io_wire_type;
wire_type_token_io:
TOK_INPUT {
@@ -648,29 +812,49 @@ wire_type_token_io:
astbuf3->is_output = true;
};
-wire_type_token:
- TOK_WIRE {
+wire_type_signedness:
+ TOK_SIGNED { astbuf3->is_signed = true; } |
+ TOK_UNSIGNED { astbuf3->is_signed = false; } |
+ %empty;
+
+wire_type_const_rand:
+ TOK_RAND TOK_CONST {
+ current_wire_rand = true;
+ current_wire_const = true;
} |
- TOK_WOR {
- astbuf3->is_wor = true;
+ TOK_CONST {
+ current_wire_const = true;
} |
- TOK_WAND {
- astbuf3->is_wand = true;
+ TOK_RAND {
+ current_wire_rand = true;
+ } |
+ %empty;
+
+opt_wire_type_token:
+ wire_type_token | %empty;
+
+wire_type_token:
+ // nets
+ net_type {
} |
+ net_type logic_type {
+ } |
+ // regs
TOK_REG {
astbuf3->is_reg = true;
} |
- TOK_LOGIC {
- astbuf3->is_logic = true;
+ TOK_VAR TOK_REG {
+ astbuf3->is_reg = true;
} |
+ // logics
TOK_VAR {
astbuf3->is_logic = true;
} |
- TOK_INTEGER {
- astbuf3->is_reg = true;
- astbuf3->range_left = 31;
- astbuf3->range_right = 0;
- astbuf3->is_signed = true;
+ TOK_VAR logic_type {
+ astbuf3->is_logic = true;
+ } |
+ logic_type {
+ astbuf3->is_logic = true;
} |
TOK_GENVAR {
astbuf3->type = AST_GENVAR;
@@ -678,17 +862,40 @@ wire_type_token:
astbuf3->is_signed = true;
astbuf3->range_left = 31;
astbuf3->range_right = 0;
+ };
+
+net_type:
+ TOK_WOR {
+ astbuf3->is_wor = true;
} |
- TOK_SIGNED {
- astbuf3->is_signed = true;
+ TOK_WAND {
+ astbuf3->is_wand = true;
} |
- TOK_RAND {
- current_wire_rand = true;
+ TOK_WIRE;
+
+logic_type:
+ TOK_LOGIC {
} |
- TOK_CONST {
- current_wire_const = true;
+ integer_atom_type {
+ astbuf3->range_left = $1 - 1;
+ astbuf3->range_right = 0;
+ astbuf3->is_signed = true;
+ } |
+ hierarchical_type_id {
+ addWiretypeNode($1, astbuf3);
};
+integer_atom_type:
+ TOK_INTEGER { $$ = 32; } |
+ TOK_INT { $$ = 32; } |
+ TOK_SHORTINT { $$ = 16; } |
+ 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);
@@ -725,7 +932,7 @@ range:
non_opt_range {
$$ = $1;
} |
- /* empty */ {
+ %empty {
$$ = NULL;
};
@@ -733,21 +940,18 @@ range_or_multirange:
range { $$ = $1; } |
non_opt_multirange { $$ = $1; };
-range_or_signed_int:
- range { $$ = $1; }
- | TOK_INTEGER { $$ = makeRange(); }
- ;
-
module_body:
module_body module_body_stmt |
/* the following line makes the generate..endgenrate keywords optional */
module_body gen_stmt |
- /* empty */;
+ module_body gen_block |
+ module_body ';' |
+ %empty;
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 |
- always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl | ignored_specify_block | /* empty statement */ ';';
+ 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:
TOK_CHECKER TOK_ID ';' {
@@ -806,29 +1010,64 @@ task_func_decl:
current_function_or_task = NULL;
ast_stack.pop_back();
} |
- attr TOK_FUNCTION opt_automatic opt_signed range_or_signed_int TOK_ID {
+ attr TOK_FUNCTION opt_automatic func_return_type TOK_ID {
current_function_or_task = new AstNode(AST_FUNCTION);
- current_function_or_task->str = *$6;
+ current_function_or_task->str = *$5;
append_attr(current_function_or_task, $1);
ast_stack.back()->children.push_back(current_function_or_task);
ast_stack.push_back(current_function_or_task);
AstNode *outreg = new AstNode(AST_WIRE);
- outreg->str = *$6;
- outreg->is_signed = $4;
+ outreg->str = *$5;
+ outreg->is_signed = false;
outreg->is_reg = true;
- if ($5 != NULL) {
- outreg->children.push_back($5);
- outreg->is_signed = $4 || $5->is_signed;
- $5->is_signed = false;
+ if ($4 != NULL) {
+ 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;
- delete $6;
+ delete $5;
} task_func_args_opt ';' task_func_body TOK_ENDFUNCTION {
current_function_or_task = NULL;
ast_stack.pop_back();
};
+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);
+ } |
+ opt_type_vec opt_signedness_default_unsigned non_opt_range {
+ $$ = $3;
+ $$->is_signed = $2;
+ } |
+ integer_atom_type opt_signedness_default_signed {
+ $$ = makeRange($1 - 1, 0, $2);
+ };
+
+opt_type_vec:
+ %empty
+ | TOK_REG
+ | TOK_LOGIC
+ ;
+
+opt_signedness_default_signed:
+ %empty { $$ = true; }
+ | TOK_SIGNED { $$ = true; }
+ | TOK_UNSIGNED { $$ = false; }
+ ;
+opt_signedness_default_unsigned:
+ %empty { $$ = false; }
+ | TOK_SIGNED { $$ = true; }
+ | TOK_UNSIGNED { $$ = false; }
+ ;
+
dpi_function_arg:
TOK_ID TOK_ID {
current_function_or_task->children.push_back(AstNode::mkconst_str(*$1));
@@ -842,28 +1081,20 @@ dpi_function_arg:
opt_dpi_function_args:
'(' dpi_function_args ')' |
- /* empty */;
+ %empty;
dpi_function_args:
dpi_function_args ',' dpi_function_arg |
dpi_function_args ',' |
dpi_function_arg |
- /* empty */;
+ %empty;
opt_automatic:
TOK_AUTOMATIC |
- /* empty */;
-
-opt_signed:
- TOK_SIGNED {
- $$ = true;
- } |
- /* empty */ {
- $$ = false;
- };
+ %empty;
task_func_args_opt:
- '(' ')' | /* empty */ | '(' {
+ '(' ')' | %empty | '(' {
albuf = nullptr;
astbuf1 = nullptr;
astbuf2 = nullptr;
@@ -879,7 +1110,11 @@ task_func_args:
task_func_port:
attr wire_type range {
+ bool prev_was_input = true;
+ bool prev_was_output = false;
if (albuf) {
+ prev_was_input = astbuf1->is_input;
+ prev_was_output = astbuf1->is_output;
delete astbuf1;
if (astbuf2 != NULL)
delete astbuf2;
@@ -888,6 +1123,12 @@ task_func_port:
albuf = $1;
astbuf1 = $2;
astbuf2 = checkRange(astbuf1, $3);
+ if (!astbuf1->is_input && !astbuf1->is_output) {
+ if (!sv_mode)
+ frontend_verilog_yyerror("task/function argument direction missing");
+ astbuf1->is_input = prev_was_input;
+ astbuf1->is_output = prev_was_output;
+ }
} wire_name |
{
if (!astbuf1) {
@@ -904,7 +1145,7 @@ task_func_port:
task_func_body:
task_func_body behavioral_stmt |
- /* empty */;
+ %empty;
/*************************** specify parser ***************************/
@@ -913,7 +1154,7 @@ specify_block:
specify_item_list:
specify_item specify_item_list |
- /* empty */;
+ %empty;
specify_item:
specify_if '(' specify_edge expr TOK_SPECIFY_OPER specify_target ')' '=' specify_rise_fall ';' {
@@ -1069,13 +1310,15 @@ specify_item:
cell->children.back()->str = "\\DST";
delete $1;
+ delete limit;
+ delete limit2;
};
specify_opt_triple:
',' specify_triple {
$$ = $2;
} |
- /* empty */ {
+ %empty {
$$ = nullptr;
};
@@ -1083,7 +1326,7 @@ specify_if:
TOK_IF '(' expr ')' {
$$ = $3;
} |
- /* empty */ {
+ %empty {
$$ = nullptr;
};
@@ -1091,7 +1334,7 @@ specify_condition:
TOK_SPECIFY_AND expr {
$$ = $2;
} |
- /* empty */ {
+ %empty {
$$ = nullptr;
};
@@ -1124,7 +1367,7 @@ specify_target:
specify_edge:
TOK_POSEDGE { $$ = 'p'; } |
TOK_NEGEDGE { $$ = 'n'; } |
- { $$ = 0; };
+ %empty { $$ = 0; };
specify_rise_fall:
specify_triple {
@@ -1231,7 +1474,7 @@ specparam_assignment:
ignspec_id '=' ignspec_expr ;
ignspec_opt_cond:
- TOK_IF '(' ignspec_expr ')' | /* empty */;
+ TOK_IF '(' ignspec_expr ')' | %empty;
path_declaration :
simple_path_declaration ';'
@@ -1282,9 +1525,7 @@ list_of_path_outputs :
list_of_path_outputs ',' specify_output_terminal_descriptor ;
opt_polarity_operator :
- '+'
- | '-'
- | ;
+ '+' | '-' | %empty;
// Good enough for the time being
specify_input_terminal_descriptor :
@@ -1333,37 +1574,34 @@ param_signed:
astbuf1->is_signed = true;
} | TOK_UNSIGNED {
astbuf1->is_signed = false;
- } | /* empty */;
+ } | %empty;
param_integer:
- TOK_INTEGER {
- if (astbuf1->children.size() != 1)
- frontend_verilog_yyerror("Internal error in param_integer - should not happen?");
- astbuf1->children.push_back(new AstNode(AST_RANGE));
- astbuf1->children.back()->children.push_back(AstNode::mkconst_int(31, true));
- astbuf1->children.back()->children.push_back(AstNode::mkconst_int(0, true));
- astbuf1->is_signed = true;
- }
+ type_atom {
+ astbuf1->is_reg = false;
+ };
param_real:
TOK_REAL {
- if (astbuf1->children.size() != 1)
- frontend_verilog_yyerror("Parameter already declared as integer, cannot set to real.");
astbuf1->children.push_back(new AstNode(AST_REALVALUE));
- }
+ };
param_range:
range {
if ($1 != NULL) {
- if (astbuf1->children.size() != 1)
- frontend_verilog_yyerror("integer/real parameters should not have a range.");
astbuf1->children.push_back($1);
}
};
-param_integer_type: param_integer param_signed
-param_range_type: type_vec param_signed param_range
-param_implicit_type: param_signed param_range
+param_integer_type: param_integer param_signed;
+param_range_type:
+ type_vec param_signed {
+ addRange(astbuf1, 0, 0);
+ } |
+ type_vec param_signed non_opt_range {
+ astbuf1->children.push_back($3);
+ };
+param_implicit_type: param_signed param_range;
param_type:
param_integer_type | param_real | param_range_type | param_implicit_type |
@@ -1371,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:
@@ -1395,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)
@@ -1406,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:
@@ -1442,28 +1699,30 @@ 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); }
- | /* nothing */ { astbuf1->is_reg = true; addRange(astbuf1); }
+ | %empty { astbuf1->is_reg = true; addRange(astbuf1); }
;
-type_atom: TOK_INTEGER { astbuf1->is_reg = true; addRange(astbuf1); } // 4-state signed
- | TOK_INT { astbuf1->is_reg = true; addRange(astbuf1); } // 2-state signed
- | TOK_SHORTINT { astbuf1->is_reg = true; addRange(astbuf1, 15, 0); } // 2-state signed
- | TOK_BYTE { astbuf1->is_reg = true; addRange(astbuf1, 7, 0); } // 2-state signed
- ;
+type_atom:
+ integer_atom_type {
+ astbuf1->is_reg = true;
+ astbuf1->is_signed = true;
+ addRange(astbuf1, $1 - 1, 0);
+ };
type_vec: TOK_REG { astbuf1->is_reg = true; } // unsigned
| TOK_LOGIC { astbuf1->is_logic = true; } // unsigned
@@ -1472,7 +1731,7 @@ type_vec: TOK_REG { astbuf1->is_reg = true; } // unsigned
type_signing:
TOK_SIGNED { astbuf1->is_signed = true; }
| TOK_UNSIGNED { astbuf1->is_signed = false; }
- | // optional
+ | %empty
;
enum_name_list: enum_name_decl
@@ -1496,7 +1755,7 @@ enum_name_decl:
opt_enum_init:
'=' basic_expr { $$ = $2; } // TODO: restrict this
- | /* optional */ { $$ = NULL; }
+ | %empty { $$ = NULL; }
;
enum_var_list:
@@ -1537,14 +1796,14 @@ struct_union:
struct_body: opt_packed '{' struct_member_list '}'
;
-opt_packed: TOK_PACKED opt_signed_struct
- | { frontend_verilog_yyerror("Only PACKED supported at this time"); }
- ;
+opt_packed:
+ TOK_PACKED opt_signed_struct |
+ %empty { frontend_verilog_yyerror("Only PACKED supported at this time"); };
opt_signed_struct:
TOK_SIGNED { astbuf2->is_signed = true; }
| TOK_UNSIGNED { astbuf2->is_signed = false; }
- | // default is unsigned
+ | %empty // default is unsigned
;
struct_member_list: struct_member
@@ -1590,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
@@ -1651,7 +1912,7 @@ wire_decl:
} opt_supply_wires ';';
opt_supply_wires:
- /* empty */ |
+ %empty |
opt_supply_wires ',' TOK_ID {
AstNode *wire_node = ast_stack.back()->children.at(GetSize(ast_stack.back()->children)-2)->clone();
AstNode *assign_node = ast_stack.back()->children.at(GetSize(ast_stack.back()->children)-1)->clone();
@@ -1752,7 +2013,13 @@ wire_name:
}
rewriteAsMemoryNode(node, $2);
}
- if (current_function_or_task == NULL) {
+ if (current_function_or_task) {
+ if (node->is_input || node->is_output)
+ node->port_id = current_function_or_task_port_id++;
+ } else if (ast_stack.back()->type == AST_GENBLOCK) {
+ if (node->is_input || node->is_output)
+ frontend_verilog_yyerror("Cannot declare module port `%s' within a generate block.", $1->c_str());
+ } else {
if (do_not_require_port_stubs && (node->is_input || node->is_output) && port_stubs.count(*$1) == 0) {
port_stubs[*$1] = ++port_counter;
}
@@ -1767,9 +2034,6 @@ wire_name:
if (node->is_input || node->is_output)
frontend_verilog_yyerror("Module port `%s' is not declared in module header.", $1->c_str());
}
- } else {
- if (node->is_input || node->is_output)
- node->port_id = current_function_or_task_port_id++;
}
//FIXME: for some reason, TOK_ID has a location which always points to one column *after* the real last column...
SET_AST_NODE_LOC(node, @1, @1);
@@ -1796,7 +2060,7 @@ type_name: TOK_ID // first time seen
;
typedef_decl:
- TOK_TYPEDEF 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)
@@ -1809,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
;
@@ -1849,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)
@@ -1857,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)
@@ -1868,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;
@@ -1882,18 +2178,21 @@ single_prim:
}
cell_parameter_list_opt:
- '#' '(' cell_parameter_list ')' | /* empty */;
+ '#' '(' cell_parameter_list ')' | %empty;
cell_parameter_list:
cell_parameter | cell_parameter_list ',' cell_parameter;
cell_parameter:
- /* empty */ |
+ %empty |
expr {
AstNode *node = new AstNode(AST_PARASET);
astbuf1->children.push_back(node);
node->children.push_back($1);
} |
+ '.' TOK_ID '(' ')' {
+ // just ignore empty parameters
+ } |
'.' TOK_ID '(' expr ')' {
AstNode *node = new AstNode(AST_PARASET);
node->str = *$2;
@@ -1972,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:
@@ -2046,7 +2346,7 @@ always_cond:
'@' ATTR_BEGIN ')' |
'@' '(' ATTR_END |
'@' '*' |
- /* empty */;
+ %empty;
always_events:
always_event |
@@ -2076,7 +2376,7 @@ opt_label:
':' TOK_ID {
$$ = $2;
} |
- /* empty */ {
+ %empty {
$$ = NULL;
};
@@ -2084,7 +2384,7 @@ opt_sva_label:
TOK_SVA_LABEL ':' {
$$ = $1;
} |
- /* empty */ {
+ %empty {
$$ = NULL;
};
@@ -2095,7 +2395,7 @@ opt_property:
TOK_FINAL {
$$ = false;
} |
- /* empty */ {
+ %empty {
$$ = false;
};
@@ -2343,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);
+ 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_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);
- SET_AST_NODE_LOC(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_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);
- 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_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);
- } |
- 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
@@ -2423,8 +2759,17 @@ 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
+ if (sv_mode && node->str.empty())
+ for (const AstNode* child : node->children)
+ if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER
+ || child->type == AST_LOCALPARAM || child->type == AST_TYPEDEF) {
+ node->str = "$unnamed_block$" + std::to_string(autoidx++);
+ break;
+ }
SET_AST_NODE_LOC(ast_stack.back(), @2, @8);
delete $4;
delete $8;
@@ -2435,10 +2780,11 @@ 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);
+ block->str = "$for_loop$" + std::to_string(autoidx++);
ast_stack.back()->children.push_back(block);
ast_stack.push_back(block);
} behavioral_stmt {
@@ -2505,20 +2851,21 @@ behavioral_stmt:
ast_stack.pop_back();
};
-unique_case_attr:
- /* empty */ {
- $$ = false;
+case_attr:
+ attr {
+ $$ = $1;
} |
- TOK_PRIORITY case_attr {
- $$ = $2;
+ attr TOK_UNIQUE0 {
+ (*$1)[ID::parallel_case] = AstNode::mkconst_int(1, false);
+ $$ = $1;
} |
- TOK_UNIQUE case_attr {
- $$ = true;
- };
-
-case_attr:
- attr unique_case_attr {
- if ($2) (*$1)[ID::parallel_case] = AstNode::mkconst_int(1, false);
+ attr TOK_PRIORITY {
+ (*$1)[ID::full_case] = AstNode::mkconst_int(1, false);
+ $$ = $1;
+ } |
+ attr TOK_UNIQUE {
+ (*$1)[ID::full_case] = AstNode::mkconst_int(1, false);
+ (*$1)[ID::parallel_case] = AstNode::mkconst_int(1, false);
$$ = $1;
};
@@ -2542,11 +2889,11 @@ opt_synopsys_attr:
if (ast_stack.back()->attributes.count(ID::parallel_case) == 0)
ast_stack.back()->attributes[ID::parallel_case] = AstNode::mkconst_int(1, false);
} |
- /* empty */;
+ %empty;
behavioral_stmt_list:
behavioral_stmt_list behavioral_stmt |
- /* empty */;
+ %empty;
optional_else:
TOK_ELSE {
@@ -2560,11 +2907,11 @@ optional_else:
} behavioral_stmt {
SET_AST_NODE_LOC(ast_stack.back(), @3, @3);
} |
- /* empty */ %prec FAKE_THEN;
+ %empty %prec FAKE_THEN;
case_body:
case_body case_item |
- /* empty */;
+ %empty;
case_item:
{
@@ -2587,7 +2934,7 @@ case_item:
gen_case_body:
gen_case_body gen_case_item |
- /* empty */;
+ %empty;
gen_case_item:
{
@@ -2632,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 {
@@ -2671,11 +3019,11 @@ lvalue_concat_list:
opt_arg_list:
'(' arg_list optional_comma ')' |
- /* empty */;
+ %empty;
arg_list:
arg_list2 |
- /* empty */;
+ %empty;
arg_list2:
single_arg |
@@ -2688,7 +3036,8 @@ single_arg:
module_gen_body:
module_gen_body gen_stmt_or_module_body_stmt |
- /* empty */;
+ module_gen_body gen_block |
+ %empty;
gen_stmt_or_module_body_stmt:
gen_stmt | module_body_stmt |
@@ -2696,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 ')' {
@@ -2713,12 +3096,7 @@ gen_stmt:
ast_stack.back()->children.push_back(node);
ast_stack.push_back(node);
ast_stack.back()->children.push_back($3);
- AstNode *block = new AstNode(AST_GENBLOCK);
- ast_stack.back()->children.push_back(block);
- ast_stack.push_back(block);
- } gen_stmt_block {
- ast_stack.pop_back();
- } opt_gen_else {
+ } gen_stmt_block opt_gen_else {
SET_AST_NODE_LOC(ast_stack.back(), @1, @7);
ast_stack.pop_back();
} |
@@ -2731,6 +3109,18 @@ gen_stmt:
SET_AST_NODE_LOC(ast_stack.back(), @1, @7);
ast_stack.pop_back();
} |
+ TOK_MSG_TASKS {
+ AstNode *node = new AstNode(AST_TECALL);
+ node->str = *$1;
+ delete $1;
+ ast_stack.back()->children.push_back(node);
+ ast_stack.push_back(node);
+ } opt_arg_list ';'{
+ SET_AST_NODE_LOC(ast_stack.back(), @1, @3);
+ ast_stack.pop_back();
+ };
+
+gen_block:
TOK_BEGIN {
enterTypeScope();
} opt_label {
@@ -2740,22 +3130,14 @@ gen_stmt:
ast_stack.push_back(node);
} module_gen_body TOK_END opt_label {
exitTypeScope();
+ checkLabelsMatch("Begin label", $3, $7);
delete $3;
delete $7;
SET_AST_NODE_LOC(ast_stack.back(), @1, @7);
ast_stack.pop_back();
- } |
- TOK_MSG_TASKS {
- AstNode *node = new AstNode(AST_TECALL);
- node->str = *$1;
- delete $1;
- ast_stack.back()->children.push_back(node);
- ast_stack.push_back(node);
- } opt_arg_list ';'{
- SET_AST_NODE_LOC(ast_stack.back(), @1, @3);
- ast_stack.pop_back();
};
+// result is wrapped in a genblock only if necessary
gen_stmt_block:
{
AstNode *node = new AstNode(AST_GENBLOCK);
@@ -2764,10 +3146,10 @@ gen_stmt_block:
} gen_stmt_or_module_body_stmt {
SET_AST_NODE_LOC(ast_stack.back(), @2, @2);
ast_stack.pop_back();
- };
+ } | gen_block;
opt_gen_else:
- TOK_ELSE gen_stmt_block | /* empty */ %prec FAKE_THEN;
+ TOK_ELSE gen_stmt_block | %empty %prec FAKE_THEN;
expr:
basic_expr {
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 ae18809d3..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
@@ -275,10 +275,15 @@ RTLIL::Const RTLIL::const_logic_or(const RTLIL::Const &arg1, const RTLIL::Const
return result;
}
-static RTLIL::Const const_shift_worker(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool sign_ext, int direction, int result_len)
+// Shift `arg1` by `arg2` bits.
+// If `direction` is +1, `arg1` is shifted right by `arg2` bits; if `direction` is -1, `arg1` is shifted left by `arg2` bits.
+// If `signed2` is true, `arg2` is interpreted as a signed integer; a negative `arg2` will cause a shift in the opposite direction.
+// Any required bits outside the bounds of `arg1` are padded with `vacant_bits` unless `sign_ext` is true, in which case any bits outside the left
+// bounds are filled with the leftmost bit of `arg1` (arithmetic shift).
+static RTLIL::Const const_shift_worker(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool sign_ext, bool signed2, int direction, int result_len, RTLIL::State vacant_bits = RTLIL::State::S0)
{
int undef_bit_pos = -1;
- BigInteger offset = const2big(arg2, false, undef_bit_pos) * direction;
+ BigInteger offset = const2big(arg2, signed2, undef_bit_pos) * direction;
if (result_len < 0)
result_len = arg1.bits.size();
@@ -290,9 +295,9 @@ static RTLIL::Const const_shift_worker(const RTLIL::Const &arg1, const RTLIL::Co
for (int i = 0; i < result_len; i++) {
BigInteger pos = BigInteger(i) + offset;
if (pos < 0)
- result.bits[i] = RTLIL::State::S0;
+ result.bits[i] = vacant_bits;
else if (pos >= BigInteger(int(arg1.bits.size())))
- result.bits[i] = sign_ext ? arg1.bits.back() : RTLIL::State::S0;
+ result.bits[i] = sign_ext ? arg1.bits.back() : vacant_bits;
else
result.bits[i] = arg1.bits[pos.toInt()];
}
@@ -304,61 +309,36 @@ RTLIL::Const RTLIL::const_shl(const RTLIL::Const &arg1, const RTLIL::Const &arg2
{
RTLIL::Const arg1_ext = arg1;
extend_u0(arg1_ext, result_len, signed1);
- return const_shift_worker(arg1_ext, arg2, false, -1, result_len);
+ return const_shift_worker(arg1_ext, arg2, false, false, -1, result_len);
}
RTLIL::Const RTLIL::const_shr(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool, int result_len)
{
RTLIL::Const arg1_ext = arg1;
extend_u0(arg1_ext, max(result_len, GetSize(arg1)), signed1);
- return const_shift_worker(arg1_ext, arg2, false, +1, result_len);
+ return const_shift_worker(arg1_ext, arg2, false, false, +1, result_len);
}
-RTLIL::Const RTLIL::const_sshl(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
+RTLIL::Const RTLIL::const_sshl(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool, int result_len)
{
- if (!signed1)
- return const_shl(arg1, arg2, signed1, signed2, result_len);
- return const_shift_worker(arg1, arg2, true, -1, result_len);
+ return const_shift_worker(arg1, arg2, signed1, false, -1, result_len);
}
-RTLIL::Const RTLIL::const_sshr(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
+RTLIL::Const RTLIL::const_sshr(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool, int result_len)
{
- if (!signed1)
- return const_shr(arg1, arg2, signed1, signed2, result_len);
- return const_shift_worker(arg1, arg2, true, +1, result_len);
-}
-
-static RTLIL::Const const_shift_shiftx(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool, bool signed2, int result_len, RTLIL::State other_bits)
-{
- int undef_bit_pos = -1;
- BigInteger offset = const2big(arg2, signed2, undef_bit_pos);
-
- if (result_len < 0)
- result_len = arg1.bits.size();
-
- RTLIL::Const result(RTLIL::State::Sx, result_len);
- if (undef_bit_pos >= 0)
- return result;
-
- for (int i = 0; i < result_len; i++) {
- BigInteger pos = BigInteger(i) + offset;
- if (pos < 0 || pos >= BigInteger(int(arg1.bits.size())))
- result.bits[i] = other_bits;
- else
- result.bits[i] = arg1.bits[pos.toInt()];
- }
-
- return result;
+ return const_shift_worker(arg1, arg2, signed1, false, +1, result_len);
}
RTLIL::Const RTLIL::const_shift(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
{
- return const_shift_shiftx(arg1, arg2, signed1, signed2, result_len, RTLIL::State::S0);
+ RTLIL::Const arg1_ext = arg1;
+ extend_u0(arg1_ext, max(result_len, GetSize(arg1)), signed1);
+ return const_shift_worker(arg1_ext, arg2, false, signed2, +1, result_len);
}
-RTLIL::Const RTLIL::const_shiftx(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
+RTLIL::Const RTLIL::const_shiftx(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool, bool signed2, int result_len)
{
- return const_shift_shiftx(arg1, arg2, signed1, signed2, result_len, RTLIL::State::Sx);
+ return const_shift_worker(arg1, arg2, false, signed2, +1, result_len, RTLIL::State::Sx);
}
RTLIL::Const RTLIL::const_lt(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
@@ -629,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 12dea93b8..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);
@@ -139,12 +142,14 @@ struct CellTypes
setup_type(ID($dff), {ID::CLK, ID::D}, {ID::Q});
setup_type(ID($dffe), {ID::CLK, ID::EN, ID::D}, {ID::Q});
setup_type(ID($dffsr), {ID::CLK, ID::SET, ID::CLR, ID::D}, {ID::Q});
- setup_type(ID($dffsre), {ID::CLK, ID::SET, ID::CLR, ID::D, ID::E}, {ID::Q});
+ 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::E}, {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::E}, {ID::Q});
- setup_type(ID($sdffce), {ID::CLK, ID::SRST, ID::D, ID::E}, {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});
setup_type(ID($dlatch), {ID::EN, ID::D}, {ID::Q});
setup_type(ID($adlatch), {ID::EN, ID::D, ID::ARST}, {ID::Q});
setup_type(ID($dlatchsr), {ID::EN, ID::SET, ID::CLR, ID::D}, {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 69bc06d2c..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)
@@ -172,6 +191,7 @@ X(T)
X(TABLE)
X(techmap_autopurge)
X(_TECHMAP_BITS_CONNMAP_)
+X(_TECHMAP_CELLNAME_)
X(_TECHMAP_CELLTYPE_)
X(techmap_celltype)
X(_TECHMAP_FAIL_)
@@ -194,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)
@@ -219,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 57ed7b8b4..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;
@@ -267,9 +268,11 @@ int main(int argc, char **argv)
printf("\n");
printf(" -s scriptfile\n");
printf(" execute the commands in the script file\n");
+#ifdef YOSYS_ENABLE_TCL
printf("\n");
printf(" -c tcl_scriptfile\n");
printf(" execute the commands in the tcl script file (see 'help tcl' for details)\n");
+#endif
printf("\n");
printf(" -p command\n");
printf(" execute the commands\n");
@@ -286,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");
@@ -340,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)
{
@@ -364,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++;
@@ -376,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':
@@ -420,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));
@@ -434,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;
@@ -504,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)
@@ -518,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) {
@@ -529,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
new file mode 100644
index 000000000..5a629d5dd
--- /dev/null
+++ b/kernel/ff.h
@@ -0,0 +1,216 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef FF_H
+#define FF_H
+
+#include "kernel/yosys.h"
+#include "kernel/ffinit.h"
+
+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;
+ // 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;
+ // True if this is a clocked (edge-sensitive) flip-flop.
+ bool has_clk;
+ // 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_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;
+ // The FF data width in bits.
+ int width;
+ dict<IdString, Const> attributes;
+
+ FfData(Module *module = nullptr, FfInitVals *initvals = nullptr, IdString name = IdString()) : module(module), initvals(initvals), cell(nullptr), name(name) {
+ width = 0;
+ has_clk = 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_aload = false;
+ pol_ce = false;
+ pol_arst = false;
+ pol_srst = false;
+ pol_clr = false;
+ pol_set = false;
+ }
+
+ FfData(FfInitVals *initvals, Cell *cell_);
+
+ // Returns a FF identical to this one, but only keeping bit indices from the argument.
+ FfData slice(const std::vector<int> &bits);
+
+ void add_dummy_ce();
+ void add_dummy_srst();
+ void add_dummy_arst();
+ void add_dummy_aload();
+ void add_dummy_sr();
+ void add_dummy_clk();
+
+ void arst_to_aload();
+ void arst_to_sr();
+
+ void aload_to_sr();
+
+ // 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();
+ void unmap_srst();
+
+ void unmap_ce_srst() {
+ unmap_ce();
+ unmap_srst();
+ }
+
+ Cell *emit();
+
+ // 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 remove();
+
+ // 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
+
+#endif
diff --git a/kernel/ffinit.h b/kernel/ffinit.h
new file mode 100644
index 000000000..9d33ac572
--- /dev/null
+++ b/kernel/ffinit.h
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef FFINIT_H
+#define FFINIT_H
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+
+YOSYS_NAMESPACE_BEGIN
+
+struct FfInitVals
+{
+ const SigMap *sigmap;
+ dict<SigBit, std::pair<State,SigBit>> initbits;
+
+ void set(const SigMap *sigmap_, RTLIL::Module *module)
+ {
+ sigmap = sigmap_;
+ initbits.clear();
+ for (auto wire : module->wires())
+ {
+ if (wire->attributes.count(ID::init) == 0)
+ continue;
+
+ SigSpec wirebits = (*sigmap)(wire);
+ Const initval = wire->attributes.at(ID::init);
+
+ for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++)
+ {
+ SigBit bit = wirebits[i];
+ State val = initval[i];
+
+ if (val != State::S0 && val != State::S1 && bit.wire != nullptr)
+ continue;
+
+ if (initbits.count(bit)) {
+ if (initbits.at(bit).first != val)
+ log_error("Conflicting init values for signal %s (%s = %s != %s).\n",
+ log_signal(bit), log_signal(SigBit(wire, i)),
+ log_signal(val), log_signal(initbits.at(bit).first));
+ continue;
+ }
+
+ initbits[bit] = std::make_pair(val,SigBit(wire,i));
+ }
+ }
+ }
+
+ RTLIL::State operator()(RTLIL::SigBit bit) const
+ {
+ auto it = initbits.find((*sigmap)(bit));
+ if (it != initbits.end())
+ return it->second.first;
+ else
+ return State::Sx;
+ }
+
+ RTLIL::Const operator()(const RTLIL::SigSpec &sig) const
+ {
+ RTLIL::Const res;
+ for (auto bit : sig)
+ res.bits.push_back((*this)(bit));
+ return res;
+ }
+
+ void set_init(RTLIL::SigBit bit, RTLIL::State val)
+ {
+ SigBit mbit = (*sigmap)(bit);
+ SigBit abit = bit;
+ auto it = initbits.find(mbit);
+ if (it != initbits.end())
+ abit = it->second.second;
+ else if (val == State::Sx)
+ return;
+ log_assert(abit.wire);
+ initbits[mbit] = std::make_pair(val,abit);
+ auto it2 = abit.wire->attributes.find(ID::init);
+ if (it2 != abit.wire->attributes.end()) {
+ it2->second[abit.offset] = val;
+ if (it2->second.is_fully_undef())
+ abit.wire->attributes.erase(it2);
+ } else if (val != State::Sx) {
+ Const cval(State::Sx, GetSize(abit.wire));
+ cval[abit.offset] = val;
+ abit.wire->attributes[ID::init] = cval;
+ }
+ }
+
+ void set_init(const RTLIL::SigSpec &sig, RTLIL::Const val)
+ {
+ log_assert(GetSize(sig) == GetSize(val));
+ for (int i = 0; i < GetSize(sig); i++)
+ set_init(sig[i], val[i]);
+ }
+
+ void remove_init(RTLIL::SigBit bit)
+ {
+ set_init(bit, State::Sx);
+ }
+
+ void remove_init(const RTLIL::SigSpec &sig)
+ {
+ for (auto bit : sig)
+ remove_init(bit);
+ }
+
+ void clear()
+ {
+ initbits.clear();
+ }
+
+ FfInitVals (const SigMap *sigmap, RTLIL::Module *module)
+ {
+ set(sigmap, module);
+ }
+
+ FfInitVals () {}
+};
+
+
+YOSYS_NAMESPACE_END
+
+#endif
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 1c1d0182e..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
@@ -19,7 +19,7 @@
#include "kernel/yosys.h"
#include "libs/sha1/sha1.h"
-#include "backends/ilang/ilang_backend.h"
+#include "backends/rtlil/rtlil_backend.h"
#if !defined(_WIN32) || defined(__MINGW32__)
# include <sys/time.h>
@@ -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,21 +337,19 @@ 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;
- if (log_error_atexit)
- log_error_atexit();
-
for (auto &item : log_expect_error)
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();
YS_DEBUGTRAP_IF_DEBUGGING;
@@ -600,7 +596,7 @@ void log_dump_val_worker(RTLIL::State v) {
const char *log_signal(const RTLIL::SigSpec &sig, bool autoint)
{
std::stringstream buf;
- ILANG_BACKEND::dump_sigspec(buf, sig, autoint);
+ RTLIL_BACKEND::dump_sigspec(buf, sig, autoint);
if (string_buf.size() < 100) {
string_buf.push_back(buf.str());
@@ -647,29 +643,34 @@ const char *log_id(RTLIL::IdString str)
void log_module(RTLIL::Module *module, std::string indent)
{
std::stringstream buf;
- ILANG_BACKEND::dump_module(buf, indent, module, module->design, false);
+ RTLIL_BACKEND::dump_module(buf, indent, module, module->design, false);
log("%s", buf.str().c_str());
}
void log_cell(RTLIL::Cell *cell, std::string indent)
{
std::stringstream buf;
- ILANG_BACKEND::dump_cell(buf, indent, cell);
+ RTLIL_BACKEND::dump_cell(buf, indent, cell);
log("%s", buf.str().c_str());
}
void log_wire(RTLIL::Wire *wire, std::string indent)
{
std::stringstream buf;
- ILANG_BACKEND::dump_wire(buf, indent, wire);
+ RTLIL_BACKEND::dump_wire(buf, indent, wire);
log("%s", buf.str().c_str());
}
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
new file mode 100644
index 000000000..059f8f934
--- /dev/null
+++ b/kernel/mem.cc
@@ -0,0 +1,1666 @@
+/*
+ * 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/mem.h"
+#include "kernel/ff.h"
+
+USING_YOSYS_NAMESPACE
+
+void Mem::remove() {
+ if (cell) {
+ module->remove(cell);
+ cell = nullptr;
+ }
+ if (mem) {
+ module->memories.erase(mem->name);
+ delete mem;
+ mem = nullptr;
+ }
+ for (auto &port : rd_ports) {
+ if (port.cell) {
+ module->remove(port.cell);
+ port.cell = nullptr;
+ }
+ }
+ for (auto &port : wr_ports) {
+ if (port.cell) {
+ module->remove(port.cell);
+ port.cell = nullptr;
+ }
+ }
+ for (auto &init : inits) {
+ if (init.cell) {
+ module->remove(init.cell);
+ init.cell = nullptr;
+ }
+ }
+}
+
+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);
+ delete mem;
+ mem = nullptr;
+ }
+ if (!cell) {
+ if (memid.empty())
+ memid = NEW_ID;
+ 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);
+ 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;
+ }
+ 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);
+ 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_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_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) {
+ if (port.cell) {
+ module->remove(port.cell);
+ port.cell = nullptr;
+ }
+ 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);
+ wr_data.append(port.data);
+ }
+ 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);
+ cell->setPort(ID::WR_DATA, wr_data);
+ for (auto &init : inits) {
+ if (init.cell) {
+ module->remove(init.cell);
+ init.cell = nullptr;
+ }
+ }
+ cell->parameters[ID::INIT] = get_init_data();
+ } else {
+ if (cell) {
+ module->remove(cell);
+ cell = nullptr;
+ }
+ if (!mem) {
+ if (memid.empty())
+ memid = NEW_ID;
+ mem = new RTLIL::Memory;
+ mem->name = memid;
+ module->memories[memid] = mem;
+ }
+ 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_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.wide_log2;
+ port.cell->parameters[ID::CLK_ENABLE] = port.clk_enable;
+ port.cell->parameters[ID::CLK_POLARITY] = port.clk_polarity;
+ 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_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.wide_log2;
+ port.cell->parameters[ID::CLK_ENABLE] = port.clk_enable;
+ port.cell->parameters[ID::CLK_POLARITY] = port.clk_polarity;
+ 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);
+ port.cell->setPort(ID::DATA, port.data);
+ }
+ idx = 0;
+ for (auto &init : inits) {
+ bool v2 = !init.en.is_fully_ones();
+ if (!init.cell)
+ 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;
+ init.cell->parameters[ID::WORDS] = GetSize(init.data) / width;
+ 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::clear_inits() {
+ for (auto &init : inits)
+ init.removed = true;
+}
+
+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);
+ }
+}
+
+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) && 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 {
+ dict<IdString, pool<Cell *>> rd_ports;
+ dict<IdString, pool<Cell *>> wr_ports;
+ dict<IdString, pool<Cell *>> inits;
+ MemIndex (Module *module) {
+ for (auto cell: module->cells()) {
+ if (cell->type.in(ID($memwr), ID($memwr_v2)))
+ wr_ports[cell->parameters.at(ID::MEMID).decode_string()].insert(cell);
+ 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.in(ID($meminit), ID($meminit_v2)))
+ inits[cell->parameters.at(ID::MEMID).decode_string()].insert(cell);
+ }
+ }
+ };
+
+ Mem mem_from_memory(Module *module, RTLIL::Memory *mem, const MemIndex &index) {
+ Mem res(module, mem->name, mem->width, mem->start_offset, mem->size);
+ 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.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();
+ mwr.clk_polarity = cell->parameters.at(ID::CLK_POLARITY).as_bool();
+ mwr.clk = cell->getPort(ID::CLK);
+ mwr.en = cell->getPort(ID::EN);
+ mwr.addr = cell->getPort(ID::ADDR);
+ mwr.data = cell->getPort(ID::DATA);
+ 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) {
+ 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;
+ for (auto cell : index.inits.at(mem->name)) {
+ MemInit init;
+ init.cell = cell;
+ init.attributes = cell->attributes;
+ auto addr = cell->getPort(ID::ADDR);
+ auto data = cell->getPort(ID::DATA);
+ if (!addr.is_fully_const())
+ log_error("Non-constant address %s in memory initialization %s.\n", log_signal(addr), log_id(cell));
+ if (!data.is_fully_const())
+ 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;
+ }
+
+ Mem mem_from_cell(Cell *cell) {
+ Mem res(cell->module, cell->parameters.at(ID::MEMID).decode_string(),
+ cell->parameters.at(ID::WIDTH).as_int(),
+ 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;
+ res.attributes = cell->attributes;
+ Const &init = cell->parameters.at(ID::INIT);
+ if (!init.is_fully_undef()) {
+ int pos = 0;
+ while (pos < res.size) {
+ Const word = init.extract(pos * res.width, res.width, State::Sx);
+ if (word.is_fully_undef()) {
+ pos++;
+ } else {
+ int epos;
+ for (epos = pos; epos < res.size; epos++) {
+ Const eword = init.extract(epos * res.width, res.width, State::Sx);
+ if (eword.is_fully_undef())
+ break;
+ }
+ 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;
+ }
+ }
+ }
+ 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.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, (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, 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, (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, (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;
+ }
+
+}
+
+std::vector<Mem> Mem::get_all_memories(Module *module) {
+ std::vector<Mem> res;
+ MemIndex index(module);
+ for (auto it: module->memories) {
+ res.push_back(mem_from_memory(module, it.second, index));
+ }
+ for (auto cell: module->cells()) {
+ if (cell->type.in(ID($mem), ID($mem_v2)))
+ res.push_back(mem_from_cell(cell));
+ }
+ return res;
+}
+
+std::vector<Mem> Mem::get_selected_memories(Module *module) {
+ std::vector<Mem> res;
+ MemIndex index(module);
+ for (auto it: module->memories) {
+ if (module->design->selected(module, it.second))
+ res.push_back(mem_from_memory(module, it.second, index));
+ }
+ for (auto cell: module->selected_cells()) {
+ if (cell->type.in(ID($mem), ID($mem_v2)))
+ res.push_back(mem_from_cell(cell));
+ }
+ return res;
+}
+
+Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) {
+ MemRd &port = rd_ports[idx];
+
+ if (!port.clk_enable)
+ return nullptr;
+
+ Cell *c;
+
+ // 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)
+ {
+ // 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
+ {
+ 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();
+ }
+
+ 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
new file mode 100644
index 000000000..ae87b1285
--- /dev/null
+++ b/kernel/mem.h
@@ -0,0 +1,229 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef MEM_H
+#define MEM_H
+
+#include "kernel/yosys.h"
+#include "kernel/ffinit.h"
+
+YOSYS_NAMESPACE_BEGIN
+
+struct MemRd : RTLIL::AttrObject {
+ bool removed;
+ Cell *cell;
+ 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 : 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() : 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 : RTLIL::AttrObject {
+ bool removed;
+ Cell *cell;
+ Const addr;
+ Const data;
+ Const en;
+ MemInit() : removed(false), cell(nullptr) {}
+};
+
+struct Mem : RTLIL::AttrObject {
+ Module *module;
+ IdString memid;
+ bool packed;
+ RTLIL::Memory *mem;
+ Cell *cell;
+ int width, start_offset, size;
+ std::vector<MemInit> inits;
+ 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();
+
+ // 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);
+
+ // 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) {}
+};
+
+YOSYS_NAMESPACE_END
+
+#endif
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 d7d226942..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,9 +20,10 @@
#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/ilang/ilang_backend.h"
+#include "backends/rtlil/rtlil_backend.h"
#include <string.h>
#include <algorithm>
@@ -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)
@@ -923,7 +1008,7 @@ namespace {
void error(int linenr)
{
std::stringstream buf;
- ILANG_BACKEND::dump_cell(buf, " ", cell);
+ RTLIL_BACKEND::dump_cell(buf, " ", cell);
log_error("Found error in internal cell %s%s%s (%s) at %s:%d:\n%s",
module ? module->name.c_str() : "", module ? "." : "",
@@ -1035,7 +1120,11 @@ namespace {
}
if (cell->type.in(ID($shift), ID($shiftx))) {
- param_bool(ID::A_SIGNED);
+ if (cell->type == ID($shiftx)) {
+ param_bool(ID::A_SIGNED, /*expected=*/false);
+ } else {
+ param_bool(ID::A_SIGNED);
+ }
param_bool(ID::B_SIGNED);
port(ID::A, param(ID::A_WIDTH));
port(ID::B, param(ID::B_WIDTH));
@@ -1162,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));
@@ -1296,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);
@@ -1362,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);
@@ -1375,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);
@@ -1384,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);
@@ -1406,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));
@@ -1532,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; }
@@ -1636,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());
@@ -1682,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)
@@ -1809,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);
@@ -1822,7 +2052,7 @@ void RTLIL::Module::remove(const pool<RTLIL::Wire*> &wires)
sig.pack();
for (auto &c : sig.chunks_)
if (c.wire != NULL && wires_p->count(c.wire)) {
- c.wire = module->addWire(NEW_ID, c.width);
+ c.wire = module->addWire(stringf("$delete_wire$%d", autoidx++), c.width);
c.offset = 0;
}
}
@@ -1865,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);
@@ -2090,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;
}
@@ -2215,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); \
@@ -2529,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)
{
@@ -2719,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)
{
@@ -2890,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;
@@ -3061,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;
@@ -3115,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;
@@ -3271,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();
}
@@ -3281,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();
}
@@ -3291,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();
}
@@ -3301,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();
}
@@ -3311,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();
}
@@ -3321,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();
@@ -3331,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();
@@ -3341,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();
@@ -3790,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;
}
@@ -3937,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)
{
@@ -3950,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);
@@ -3962,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;
}
@@ -3972,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());
}
@@ -4160,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");
@@ -4533,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 6c561cb85..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()) {
@@ -334,6 +337,10 @@ namespace RTLIL
return compare(size()-len, len, suffix) == 0;
}
+ bool contains(const char* str) const {
+ return strstr(c_str(), str);
+ }
+
size_t size() const {
return strlen(c_str());
}
@@ -375,6 +382,8 @@ namespace RTLIL
bool in(const char *rhs) const { return *this == rhs; }
bool in(const std::string &rhs) const { return *this == rhs; }
bool in(const pool<IdString> &rhs) const { return rhs.count(*this) != 0; }
+
+ bool isPublic() const { return begins_with("\\"); }
};
namespace ID {
@@ -476,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.
@@ -654,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;
@@ -708,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
@@ -729,6 +745,7 @@ struct RTLIL::SigChunk
RTLIL::SigChunk extract(int offset, int length) const;
inline int size() const { return width; }
+ inline bool is_wire() const { return wire != NULL; }
bool operator <(const RTLIL::SigChunk &other) const;
bool operator ==(const RTLIL::SigChunk &other) const;
@@ -745,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);
@@ -754,6 +771,8 @@ struct RTLIL::SigBit
SigBit(const RTLIL::SigBit &sigbit) = default;
RTLIL::SigBit &operator =(const RTLIL::SigBit &other) = default;
+ inline bool is_wire() const { return wire != NULL; }
+
bool operator <(const RTLIL::SigBit &other) const;
bool operator ==(const RTLIL::SigBit &other) const;
bool operator !=(const RTLIL::SigBit &other) const;
@@ -825,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_;
@@ -923,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;
@@ -951,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
};
@@ -1020,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;
@@ -1032,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 {
@@ -1039,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);
@@ -1101,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
@@ -1115,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;
@@ -1125,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;
@@ -1138,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();
@@ -1180,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);
@@ -1205,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.
@@ -1257,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 = "");
@@ -1277,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 = "");
@@ -1314,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,
@@ -1330,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 = "");
@@ -1377,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 = "");
@@ -1502,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
@@ -1511,7 +1565,6 @@ struct RTLIL::CaseRule : public RTLIL::AttrObject
std::vector<RTLIL::SwitchRule*> switches;
~CaseRule();
- void optimize();
bool empty() const;
@@ -1534,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);
@@ -1547,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;
@@ -1686,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>
@@ -1695,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
new file mode 100644
index 000000000..9c40ec66d
--- /dev/null
+++ b/kernel/satgen.cc
@@ -0,0 +1,1339 @@
+/*
+ * 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/satgen.h"
+#include "kernel/ff.h"
+
+USING_YOSYS_NAMESPACE
+
+bool SatGen::importCell(RTLIL::Cell *cell, int timestep)
+{
+ bool arith_undef_handled = false;
+ bool is_arith_compare = cell->type.in(ID($lt), ID($le), ID($ge), ID($gt));
+
+ if (model_undef && (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($divfloor), ID($modfloor)) || is_arith_compare))
+ {
+ std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
+ std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+ if (is_arith_compare)
+ extendSignalWidth(undef_a, undef_b, cell, true);
+ else
+ extendSignalWidth(undef_a, undef_b, undef_y, cell, true);
+
+ int undef_any_a = ez->expression(ezSAT::OpOr, undef_a);
+ int undef_any_b = ez->expression(ezSAT::OpOr, undef_b);
+ int undef_y_bit = ez->OR(undef_any_a, undef_any_b);
+
+ if (cell->type.in(ID($div), ID($mod), ID($divfloor), ID($modfloor))) {
+ std::vector<int> b = importSigSpec(cell->getPort(ID::B), timestep);
+ undef_y_bit = ez->OR(undef_y_bit, ez->NOT(ez->expression(ezSAT::OpOr, b)));
+ }
+
+ if (is_arith_compare) {
+ for (size_t i = 1; i < undef_y.size(); i++)
+ ez->SET(ez->CONST_FALSE, undef_y.at(i));
+ ez->SET(undef_y_bit, undef_y.at(0));
+ } else {
+ std::vector<int> undef_y_bits(undef_y.size(), undef_y_bit);
+ ez->assume(ez->vec_eq(undef_y_bits, undef_y));
+ }
+
+ arith_undef_handled = true;
+ }
+
+ if (cell->type.in(ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_),
+ ID($and), ID($or), ID($xor), ID($xnor), ID($add), ID($sub)))
+ {
+ std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
+ std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
+ extendSignalWidth(a, b, y, cell);
+
+ std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
+
+ if (cell->type.in(ID($and), ID($_AND_)))
+ ez->assume(ez->vec_eq(ez->vec_and(a, b), yy));
+ if (cell->type == ID($_NAND_))
+ ez->assume(ez->vec_eq(ez->vec_not(ez->vec_and(a, b)), yy));
+ if (cell->type.in(ID($or), ID($_OR_)))
+ ez->assume(ez->vec_eq(ez->vec_or(a, b), yy));
+ if (cell->type == ID($_NOR_))
+ ez->assume(ez->vec_eq(ez->vec_not(ez->vec_or(a, b)), yy));
+ if (cell->type.in(ID($xor), ID($_XOR_)))
+ ez->assume(ez->vec_eq(ez->vec_xor(a, b), yy));
+ if (cell->type.in(ID($xnor), ID($_XNOR_)))
+ ez->assume(ez->vec_eq(ez->vec_not(ez->vec_xor(a, b)), yy));
+ if (cell->type == ID($_ANDNOT_))
+ ez->assume(ez->vec_eq(ez->vec_and(a, ez->vec_not(b)), yy));
+ if (cell->type == ID($_ORNOT_))
+ ez->assume(ez->vec_eq(ez->vec_or(a, ez->vec_not(b)), yy));
+ if (cell->type == ID($add))
+ ez->assume(ez->vec_eq(ez->vec_add(a, b), yy));
+ if (cell->type == ID($sub))
+ ez->assume(ez->vec_eq(ez->vec_sub(a, b), yy));
+
+ if (model_undef && !arith_undef_handled)
+ {
+ std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
+ std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+ extendSignalWidth(undef_a, undef_b, undef_y, cell, false);
+
+ if (cell->type.in(ID($and), ID($_AND_), ID($_NAND_))) {
+ std::vector<int> a0 = ez->vec_and(ez->vec_not(a), ez->vec_not(undef_a));
+ std::vector<int> b0 = ez->vec_and(ez->vec_not(b), ez->vec_not(undef_b));
+ std::vector<int> yX = ez->vec_and(ez->vec_or(undef_a, undef_b), ez->vec_not(ez->vec_or(a0, b0)));
+ ez->assume(ez->vec_eq(yX, undef_y));
+ }
+ else if (cell->type.in(ID($or), ID($_OR_), ID($_NOR_))) {
+ std::vector<int> a1 = ez->vec_and(a, ez->vec_not(undef_a));
+ std::vector<int> b1 = ez->vec_and(b, ez->vec_not(undef_b));
+ std::vector<int> yX = ez->vec_and(ez->vec_or(undef_a, undef_b), ez->vec_not(ez->vec_or(a1, b1)));
+ ez->assume(ez->vec_eq(yX, undef_y));
+ }
+ else if (cell->type.in(ID($xor), ID($xnor), ID($_XOR_), ID($_XNOR_))) {
+ std::vector<int> yX = ez->vec_or(undef_a, undef_b);
+ ez->assume(ez->vec_eq(yX, undef_y));
+ }
+ else if (cell->type == ID($_ANDNOT_)) {
+ std::vector<int> a0 = ez->vec_and(ez->vec_not(a), ez->vec_not(undef_a));
+ std::vector<int> b1 = ez->vec_and(b, ez->vec_not(undef_b));
+ std::vector<int> yX = ez->vec_and(ez->vec_or(undef_a, undef_b), ez->vec_not(ez->vec_or(a0, b1)));
+ ez->assume(ez->vec_eq(yX, undef_y));
+ }
+
+ else if (cell->type == ID($_ORNOT_)) {
+ std::vector<int> a1 = ez->vec_and(a, ez->vec_not(undef_a));
+ std::vector<int> b0 = ez->vec_and(ez->vec_not(b), ez->vec_not(undef_b));
+ std::vector<int> yX = ez->vec_and(ez->vec_or(undef_a, undef_b), ez->vec_not(ez->vec_or(a1, b0)));
+ ez->assume(ez->vec_eq(yX, undef_y));
+ }
+ else
+ log_abort();
+
+ undefGating(y, yy, undef_y);
+ }
+ else if (model_undef)
+ {
+ std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+ undefGating(y, yy, undef_y);
+ }
+ return true;
+ }
+
+ if (cell->type.in(ID($_AOI3_), ID($_OAI3_), ID($_AOI4_), ID($_OAI4_)))
+ {
+ bool aoi_mode = cell->type.in(ID($_AOI3_), ID($_AOI4_));
+ bool three_mode = cell->type.in(ID($_AOI3_), ID($_OAI3_));
+
+ int a = importDefSigSpec(cell->getPort(ID::A), timestep).at(0);
+ int b = importDefSigSpec(cell->getPort(ID::B), timestep).at(0);
+ int c = importDefSigSpec(cell->getPort(ID::C), timestep).at(0);
+ int d = three_mode ? (aoi_mode ? ez->CONST_TRUE : ez->CONST_FALSE) : importDefSigSpec(cell->getPort(ID::D), timestep).at(0);
+ int y = importDefSigSpec(cell->getPort(ID::Y), timestep).at(0);
+ int yy = model_undef ? ez->literal() : y;
+
+ if (cell->type.in(ID($_AOI3_), ID($_AOI4_)))
+ ez->assume(ez->IFF(ez->NOT(ez->OR(ez->AND(a, b), ez->AND(c, d))), yy));
+ else
+ ez->assume(ez->IFF(ez->NOT(ez->AND(ez->OR(a, b), ez->OR(c, d))), yy));
+
+ if (model_undef)
+ {
+ int undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep).at(0);
+ int undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep).at(0);
+ int undef_c = importUndefSigSpec(cell->getPort(ID::C), timestep).at(0);
+ int undef_d = three_mode ? ez->CONST_FALSE : importUndefSigSpec(cell->getPort(ID::D), timestep).at(0);
+ int undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep).at(0);
+
+ if (aoi_mode)
+ {
+ int a0 = ez->AND(ez->NOT(a), ez->NOT(undef_a));
+ int b0 = ez->AND(ez->NOT(b), ez->NOT(undef_b));
+ int c0 = ez->AND(ez->NOT(c), ez->NOT(undef_c));
+ int d0 = ez->AND(ez->NOT(d), ez->NOT(undef_d));
+
+ int ab = ez->AND(a, b), cd = ez->AND(c, d);
+ int undef_ab = ez->AND(ez->OR(undef_a, undef_b), ez->NOT(ez->OR(a0, b0)));
+ int undef_cd = ez->AND(ez->OR(undef_c, undef_d), ez->NOT(ez->OR(c0, d0)));
+
+ int ab1 = ez->AND(ab, ez->NOT(undef_ab));
+ int cd1 = ez->AND(cd, ez->NOT(undef_cd));
+ int yX = ez->AND(ez->OR(undef_ab, undef_cd), ez->NOT(ez->OR(ab1, cd1)));
+
+ ez->assume(ez->IFF(yX, undef_y));
+ }
+ else
+ {
+ int a1 = ez->AND(a, ez->NOT(undef_a));
+ int b1 = ez->AND(b, ez->NOT(undef_b));
+ int c1 = ez->AND(c, ez->NOT(undef_c));
+ int d1 = ez->AND(d, ez->NOT(undef_d));
+
+ int ab = ez->OR(a, b), cd = ez->OR(c, d);
+ int undef_ab = ez->AND(ez->OR(undef_a, undef_b), ez->NOT(ez->OR(a1, b1)));
+ int undef_cd = ez->AND(ez->OR(undef_c, undef_d), ez->NOT(ez->OR(c1, d1)));
+
+ int ab0 = ez->AND(ez->NOT(ab), ez->NOT(undef_ab));
+ int cd0 = ez->AND(ez->NOT(cd), ez->NOT(undef_cd));
+ int yX = ez->AND(ez->OR(undef_ab, undef_cd), ez->NOT(ez->OR(ab0, cd0)));
+
+ ez->assume(ez->IFF(yX, undef_y));
+ }
+
+ undefGating(y, yy, undef_y);
+ }
+
+ return true;
+ }
+
+ if (cell->type.in(ID($_NOT_), ID($not)))
+ {
+ std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
+ extendSignalWidthUnary(a, y, cell);
+
+ std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
+ ez->assume(ez->vec_eq(ez->vec_not(a), yy));
+
+ if (model_undef) {
+ std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+ extendSignalWidthUnary(undef_a, undef_y, cell, false);
+ ez->assume(ez->vec_eq(undef_a, undef_y));
+ undefGating(y, yy, undef_y);
+ }
+ return true;
+ }
+
+ if (cell->type.in(ID($_MUX_), ID($mux), ID($_NMUX_)))
+ {
+ std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), 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;
+ if (cell->type == ID($_NMUX_))
+ ez->assume(ez->vec_eq(ez->vec_not(ez->vec_ite(s.at(0), b, a)), yy));
+ else
+ ez->assume(ez->vec_eq(ez->vec_ite(s.at(0), b, a), yy));
+
+ if (model_undef)
+ {
+ std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
+ std::vector<int> undef_s = importUndefSigSpec(cell->getPort(ID::S), timestep);
+ std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+
+ std::vector<int> unequal_ab = ez->vec_not(ez->vec_iff(a, b));
+ std::vector<int> undef_ab = ez->vec_or(unequal_ab, ez->vec_or(undef_a, undef_b));
+ std::vector<int> yX = ez->vec_ite(undef_s.at(0), undef_ab, ez->vec_ite(s.at(0), undef_b, undef_a));
+ ez->assume(ez->vec_eq(yX, undef_y));
+ undefGating(y, yy, undef_y);
+ }
+ 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);
+ std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), 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> tmp = a;
+ for (size_t i = 0; i < s.size(); i++) {
+ std::vector<int> part_of_b(b.begin()+i*a.size(), b.begin()+(i+1)*a.size());
+ tmp = ez->vec_ite(s.at(i), part_of_b, tmp);
+ }
+ ez->assume(ez->vec_eq(tmp, yy));
+
+ if (model_undef)
+ {
+ std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
+ std::vector<int> undef_s = importUndefSigSpec(cell->getPort(ID::S), timestep);
+ std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+
+ int maybe_a = ez->CONST_TRUE;
+
+ std::vector<int> bits_set = std::vector<int>(undef_y.size(), ez->CONST_FALSE);
+ std::vector<int> bits_clr = std::vector<int>(undef_y.size(), ez->CONST_FALSE);
+
+ for (size_t i = 0; i < s.size(); i++)
+ {
+ std::vector<int> part_of_b(b.begin()+i*a.size(), b.begin()+(i+1)*a.size());
+ std::vector<int> part_of_undef_b(undef_b.begin()+i*a.size(), undef_b.begin()+(i+1)*a.size());
+
+ int maybe_s = ez->OR(s.at(i), undef_s.at(i));
+ int sure_s = ez->AND(s.at(i), ez->NOT(undef_s.at(i)));
+
+ maybe_a = ez->AND(maybe_a, ez->NOT(sure_s));
+
+ bits_set = ez->vec_ite(maybe_s, ez->vec_or(bits_set, ez->vec_or(part_of_b, part_of_undef_b)), bits_set);
+ bits_clr = ez->vec_ite(maybe_s, ez->vec_or(bits_clr, ez->vec_or(ez->vec_not(part_of_b), part_of_undef_b)), bits_clr);
+ }
+
+ bits_set = ez->vec_ite(maybe_a, ez->vec_or(bits_set, ez->vec_or(bits_set, ez->vec_or(a, undef_a))), bits_set);
+ bits_clr = ez->vec_ite(maybe_a, ez->vec_or(bits_clr, ez->vec_or(bits_clr, ez->vec_or(ez->vec_not(a), undef_a))), bits_clr);
+
+ ez->assume(ez->vec_eq(ez->vec_not(ez->vec_xor(bits_set, bits_clr)), undef_y));
+ undefGating(y, yy, undef_y);
+ }
+ return true;
+ }
+
+ if (cell->type.in(ID($pos), ID($neg)))
+ {
+ std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
+ extendSignalWidthUnary(a, y, cell);
+
+ std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
+
+ if (cell->type == ID($pos)) {
+ ez->assume(ez->vec_eq(a, yy));
+ } else {
+ std::vector<int> zero(a.size(), ez->CONST_FALSE);
+ ez->assume(ez->vec_eq(ez->vec_sub(zero, a), yy));
+ }
+
+ if (model_undef)
+ {
+ std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+ extendSignalWidthUnary(undef_a, undef_y, cell);
+
+ if (cell->type == ID($pos)) {
+ ez->assume(ez->vec_eq(undef_a, undef_y));
+ } else {
+ int undef_any_a = ez->expression(ezSAT::OpOr, undef_a);
+ std::vector<int> undef_y_bits(undef_y.size(), undef_any_a);
+ ez->assume(ez->vec_eq(undef_y_bits, undef_y));
+ }
+
+ undefGating(y, yy, undef_y);
+ }
+ return true;
+ }
+
+ if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool), ID($logic_not)))
+ {
+ std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
+
+ std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
+
+ if (cell->type == ID($reduce_and))
+ ez->SET(ez->expression(ez->OpAnd, a), yy.at(0));
+ if (cell->type.in(ID($reduce_or), ID($reduce_bool)))
+ ez->SET(ez->expression(ez->OpOr, a), yy.at(0));
+ if (cell->type == ID($reduce_xor))
+ ez->SET(ez->expression(ez->OpXor, a), yy.at(0));
+ if (cell->type == ID($reduce_xnor))
+ ez->SET(ez->NOT(ez->expression(ez->OpXor, a)), yy.at(0));
+ if (cell->type == ID($logic_not))
+ ez->SET(ez->NOT(ez->expression(ez->OpOr, a)), yy.at(0));
+ for (size_t i = 1; i < y.size(); i++)
+ ez->SET(ez->CONST_FALSE, yy.at(i));
+
+ if (model_undef)
+ {
+ std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+ int aX = ez->expression(ezSAT::OpOr, undef_a);
+
+ if (cell->type == ID($reduce_and)) {
+ int a0 = ez->expression(ezSAT::OpOr, ez->vec_and(ez->vec_not(a), ez->vec_not(undef_a)));
+ ez->assume(ez->IFF(ez->AND(ez->NOT(a0), aX), undef_y.at(0)));
+ }
+ else if (cell->type.in(ID($reduce_or), ID($reduce_bool), ID($logic_not))) {
+ int a1 = ez->expression(ezSAT::OpOr, ez->vec_and(a, ez->vec_not(undef_a)));
+ ez->assume(ez->IFF(ez->AND(ez->NOT(a1), aX), undef_y.at(0)));
+ }
+ else if (cell->type.in(ID($reduce_xor), ID($reduce_xnor))) {
+ ez->assume(ez->IFF(aX, undef_y.at(0)));
+ } else
+ log_abort();
+
+ for (size_t i = 1; i < undef_y.size(); i++)
+ ez->SET(ez->CONST_FALSE, undef_y.at(i));
+
+ undefGating(y, yy, undef_y);
+ }
+ return true;
+ }
+
+ if (cell->type.in(ID($logic_and), ID($logic_or)))
+ {
+ std::vector<int> vec_a = importDefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> vec_b = importDefSigSpec(cell->getPort(ID::B), timestep);
+
+ int a = ez->expression(ez->OpOr, vec_a);
+ int b = ez->expression(ez->OpOr, vec_b);
+ std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
+
+ std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
+
+ if (cell->type == ID($logic_and))
+ ez->SET(ez->expression(ez->OpAnd, a, b), yy.at(0));
+ else
+ ez->SET(ez->expression(ez->OpOr, a, b), yy.at(0));
+ for (size_t i = 1; i < y.size(); i++)
+ ez->SET(ez->CONST_FALSE, yy.at(i));
+
+ if (model_undef)
+ {
+ std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
+ std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+
+ int a0 = ez->NOT(ez->OR(ez->expression(ezSAT::OpOr, vec_a), ez->expression(ezSAT::OpOr, undef_a)));
+ int b0 = ez->NOT(ez->OR(ez->expression(ezSAT::OpOr, vec_b), ez->expression(ezSAT::OpOr, undef_b)));
+ int a1 = ez->expression(ezSAT::OpOr, ez->vec_and(vec_a, ez->vec_not(undef_a)));
+ int b1 = ez->expression(ezSAT::OpOr, ez->vec_and(vec_b, ez->vec_not(undef_b)));
+ int aX = ez->expression(ezSAT::OpOr, undef_a);
+ int bX = ez->expression(ezSAT::OpOr, undef_b);
+
+ if (cell->type == ID($logic_and))
+ ez->SET(ez->AND(ez->OR(aX, bX), ez->NOT(ez->AND(a1, b1)), ez->NOT(a0), ez->NOT(b0)), undef_y.at(0));
+ else if (cell->type == ID($logic_or))
+ ez->SET(ez->AND(ez->OR(aX, bX), ez->NOT(ez->AND(a0, b0)), ez->NOT(a1), ez->NOT(b1)), undef_y.at(0));
+ else
+ log_abort();
+
+ for (size_t i = 1; i < undef_y.size(); i++)
+ ez->SET(ez->CONST_FALSE, undef_y.at(i));
+
+ undefGating(y, yy, undef_y);
+ }
+ return true;
+ }
+
+ if (cell->type.in(ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt)))
+ {
+ bool is_signed = cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool();
+ std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
+ std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
+ extendSignalWidth(a, b, cell);
+
+ std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
+
+ if (model_undef && cell->type.in(ID($eqx), ID($nex))) {
+ std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
+ extendSignalWidth(undef_a, undef_b, cell, true);
+ a = ez->vec_or(a, undef_a);
+ b = ez->vec_or(b, undef_b);
+ }
+
+ if (cell->type == ID($lt))
+ ez->SET(is_signed ? ez->vec_lt_signed(a, b) : ez->vec_lt_unsigned(a, b), yy.at(0));
+ if (cell->type == ID($le))
+ ez->SET(is_signed ? ez->vec_le_signed(a, b) : ez->vec_le_unsigned(a, b), yy.at(0));
+ if (cell->type.in(ID($eq), ID($eqx)))
+ ez->SET(ez->vec_eq(a, b), yy.at(0));
+ if (cell->type.in(ID($ne), ID($nex)))
+ ez->SET(ez->vec_ne(a, b), yy.at(0));
+ if (cell->type == ID($ge))
+ ez->SET(is_signed ? ez->vec_ge_signed(a, b) : ez->vec_ge_unsigned(a, b), yy.at(0));
+ if (cell->type == ID($gt))
+ ez->SET(is_signed ? ez->vec_gt_signed(a, b) : ez->vec_gt_unsigned(a, b), yy.at(0));
+ for (size_t i = 1; i < y.size(); i++)
+ ez->SET(ez->CONST_FALSE, yy.at(i));
+
+ if (model_undef && cell->type.in(ID($eqx), ID($nex)))
+ {
+ std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
+ std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+ extendSignalWidth(undef_a, undef_b, cell, true);
+
+ if (cell->type == ID($eqx))
+ yy.at(0) = ez->AND(yy.at(0), ez->vec_eq(undef_a, undef_b));
+ else
+ yy.at(0) = ez->OR(yy.at(0), ez->vec_ne(undef_a, undef_b));
+
+ for (size_t i = 0; i < y.size(); i++)
+ ez->SET(ez->CONST_FALSE, undef_y.at(i));
+
+ ez->assume(ez->vec_eq(y, yy));
+ }
+ else if (model_undef && cell->type.in(ID($eq), ID($ne)))
+ {
+ std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
+ std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+ extendSignalWidth(undef_a, undef_b, cell, true);
+
+ int undef_any_a = ez->expression(ezSAT::OpOr, undef_a);
+ int undef_any_b = ez->expression(ezSAT::OpOr, undef_b);
+ int undef_any = ez->OR(undef_any_a, undef_any_b);
+
+ std::vector<int> masked_a_bits = ez->vec_or(a, ez->vec_or(undef_a, undef_b));
+ std::vector<int> masked_b_bits = ez->vec_or(b, ez->vec_or(undef_a, undef_b));
+
+ int masked_ne = ez->vec_ne(masked_a_bits, masked_b_bits);
+ int undef_y_bit = ez->AND(undef_any, ez->NOT(masked_ne));
+
+ for (size_t i = 1; i < undef_y.size(); i++)
+ ez->SET(ez->CONST_FALSE, undef_y.at(i));
+ ez->SET(undef_y_bit, undef_y.at(0));
+
+ undefGating(y, yy, undef_y);
+ }
+ else
+ {
+ if (model_undef) {
+ std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+ undefGating(y, yy, undef_y);
+ }
+ log_assert(!model_undef || arith_undef_handled);
+ }
+ return true;
+ }
+
+ if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)))
+ {
+ std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
+ std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
+
+ int extend_bit = ez->CONST_FALSE;
+
+ if (cell->parameters[ID::A_SIGNED].as_bool())
+ extend_bit = a.back();
+
+ while (y.size() < a.size())
+ y.push_back(ez->literal());
+ while (y.size() > a.size())
+ a.push_back(extend_bit);
+
+ std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
+ std::vector<int> shifted_a;
+
+ if (cell->type.in( ID($shl), ID($sshl)))
+ shifted_a = ez->vec_shift_left(a, b, false, ez->CONST_FALSE, ez->CONST_FALSE);
+
+ if (cell->type == ID($shr))
+ shifted_a = ez->vec_shift_right(a, b, false, ez->CONST_FALSE, ez->CONST_FALSE);
+
+ if (cell->type == ID($sshr))
+ shifted_a = ez->vec_shift_right(a, b, false, cell->parameters[ID::A_SIGNED].as_bool() ? a.back() : ez->CONST_FALSE, ez->CONST_FALSE);
+
+ if (cell->type.in(ID($shift), ID($shiftx)))
+ shifted_a = ez->vec_shift_right(a, b, cell->parameters[ID::B_SIGNED].as_bool(), ez->CONST_FALSE, ez->CONST_FALSE);
+
+ ez->assume(ez->vec_eq(shifted_a, yy));
+
+ if (model_undef)
+ {
+ std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
+ std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+ std::vector<int> undef_a_shifted;
+
+ extend_bit = cell->type == ID($shiftx) ? ez->CONST_TRUE : ez->CONST_FALSE;
+ if (cell->parameters[ID::A_SIGNED].as_bool())
+ extend_bit = undef_a.back();
+
+ while (undef_y.size() < undef_a.size())
+ undef_y.push_back(ez->literal());
+ while (undef_y.size() > undef_a.size())
+ undef_a.push_back(extend_bit);
+
+ if (cell->type.in(ID($shl), ID($sshl)))
+ undef_a_shifted = ez->vec_shift_left(undef_a, b, false, ez->CONST_FALSE, ez->CONST_FALSE);
+
+ if (cell->type == ID($shr))
+ undef_a_shifted = ez->vec_shift_right(undef_a, b, false, ez->CONST_FALSE, ez->CONST_FALSE);
+
+ if (cell->type == ID($sshr))
+ undef_a_shifted = ez->vec_shift_right(undef_a, b, false, cell->parameters[ID::A_SIGNED].as_bool() ? undef_a.back() : ez->CONST_FALSE, ez->CONST_FALSE);
+
+ if (cell->type == ID($shift))
+ undef_a_shifted = ez->vec_shift_right(undef_a, b, cell->parameters[ID::B_SIGNED].as_bool(), ez->CONST_FALSE, ez->CONST_FALSE);
+
+ if (cell->type == ID($shiftx))
+ undef_a_shifted = ez->vec_shift_right(undef_a, b, cell->parameters[ID::B_SIGNED].as_bool(), ez->CONST_TRUE, ez->CONST_TRUE);
+
+ int undef_any_b = ez->expression(ezSAT::OpOr, undef_b);
+ std::vector<int> undef_all_y_bits(undef_y.size(), undef_any_b);
+ ez->assume(ez->vec_eq(ez->vec_or(undef_a_shifted, undef_all_y_bits), undef_y));
+ undefGating(y, yy, undef_y);
+ }
+ return true;
+ }
+
+ if (cell->type == ID($mul))
+ {
+ std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
+ std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
+ extendSignalWidth(a, b, y, cell);
+
+ std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
+
+ std::vector<int> tmp(a.size(), ez->CONST_FALSE);
+ for (int i = 0; i < int(a.size()); i++)
+ {
+ std::vector<int> shifted_a(a.size(), ez->CONST_FALSE);
+ for (int j = i; j < int(a.size()); j++)
+ shifted_a.at(j) = a.at(j-i);
+ tmp = ez->vec_ite(b.at(i), ez->vec_add(tmp, shifted_a), tmp);
+ }
+ ez->assume(ez->vec_eq(tmp, yy));
+
+ if (model_undef) {
+ log_assert(arith_undef_handled);
+ std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+ undefGating(y, yy, undef_y);
+ }
+ return true;
+ }
+
+ if (cell->type == ID($macc))
+ {
+ std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
+ std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
+
+ Macc macc;
+ macc.from_cell(cell);
+
+ std::vector<int> tmp(GetSize(y), ez->CONST_FALSE);
+
+ for (auto &port : macc.ports)
+ {
+ std::vector<int> in_a = importDefSigSpec(port.in_a, timestep);
+ std::vector<int> in_b = importDefSigSpec(port.in_b, timestep);
+
+ while (GetSize(in_a) < GetSize(y))
+ in_a.push_back(port.is_signed && !in_a.empty() ? in_a.back() : ez->CONST_FALSE);
+ in_a.resize(GetSize(y));
+
+ if (GetSize(in_b))
+ {
+ while (GetSize(in_b) < GetSize(y))
+ in_b.push_back(port.is_signed && !in_b.empty() ? in_b.back() : ez->CONST_FALSE);
+ in_b.resize(GetSize(y));
+
+ for (int i = 0; i < GetSize(in_b); i++) {
+ std::vector<int> shifted_a(in_a.size(), ez->CONST_FALSE);
+ for (int j = i; j < int(in_a.size()); j++)
+ shifted_a.at(j) = in_a.at(j-i);
+ if (port.do_subtract)
+ tmp = ez->vec_ite(in_b.at(i), ez->vec_sub(tmp, shifted_a), tmp);
+ else
+ tmp = ez->vec_ite(in_b.at(i), ez->vec_add(tmp, shifted_a), tmp);
+ }
+ }
+ else
+ {
+ if (port.do_subtract)
+ tmp = ez->vec_sub(tmp, in_a);
+ else
+ tmp = ez->vec_add(tmp, in_a);
+ }
+ }
+
+ for (int i = 0; i < GetSize(b); i++) {
+ std::vector<int> val(GetSize(y), ez->CONST_FALSE);
+ val.at(0) = b.at(i);
+ tmp = ez->vec_add(tmp, val);
+ }
+
+ if (model_undef)
+ {
+ std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
+
+ int undef_any_a = ez->expression(ezSAT::OpOr, undef_a);
+ int undef_any_b = ez->expression(ezSAT::OpOr, undef_b);
+
+ std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+ ez->assume(ez->vec_eq(undef_y, std::vector<int>(GetSize(y), ez->OR(undef_any_a, undef_any_b))));
+
+ undefGating(y, tmp, undef_y);
+ }
+ else
+ ez->assume(ez->vec_eq(y, tmp));
+
+ return true;
+ }
+
+ if (cell->type.in(ID($div), ID($mod), ID($divfloor), ID($modfloor)))
+ {
+ std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
+ std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
+ extendSignalWidth(a, b, y, cell);
+
+ std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
+
+ std::vector<int> a_u, b_u;
+ if (cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool()) {
+ a_u = ez->vec_ite(a.back(), ez->vec_neg(a), a);
+ b_u = ez->vec_ite(b.back(), ez->vec_neg(b), b);
+ } else {
+ a_u = a;
+ b_u = b;
+ }
+
+ std::vector<int> chain_buf = a_u;
+ std::vector<int> y_u(a_u.size(), ez->CONST_FALSE);
+ for (int i = int(a.size())-1; i >= 0; i--)
+ {
+ chain_buf.insert(chain_buf.end(), chain_buf.size(), ez->CONST_FALSE);
+
+ std::vector<int> b_shl(i, ez->CONST_FALSE);
+ b_shl.insert(b_shl.end(), b_u.begin(), b_u.end());
+ b_shl.insert(b_shl.end(), chain_buf.size()-b_shl.size(), ez->CONST_FALSE);
+
+ y_u.at(i) = ez->vec_ge_unsigned(chain_buf, b_shl);
+ chain_buf = ez->vec_ite(y_u.at(i), ez->vec_sub(chain_buf, b_shl), chain_buf);
+
+ chain_buf.erase(chain_buf.begin() + a_u.size(), chain_buf.end());
+ }
+
+ std::vector<int> y_tmp = ignore_div_by_zero ? yy : ez->vec_var(y.size());
+
+ // modulo calculation
+ std::vector<int> modulo_trunc;
+ int floored_eq_trunc;
+ if (cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool()) {
+ modulo_trunc = ez->vec_ite(a.back(), ez->vec_neg(chain_buf), chain_buf);
+ // floor == trunc when sgn(a) == sgn(b) or trunc == 0
+ floored_eq_trunc = ez->OR(ez->IFF(a.back(), b.back()), ez->NOT(ez->expression(ezSAT::OpOr, modulo_trunc)));
+ } else {
+ modulo_trunc = chain_buf;
+ floored_eq_trunc = ez->CONST_TRUE;
+ }
+
+ if (cell->type == ID($div)) {
+ if (cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool())
+ ez->assume(ez->vec_eq(y_tmp, ez->vec_ite(ez->XOR(a.back(), b.back()), ez->vec_neg(y_u), y_u)));
+ else
+ ez->assume(ez->vec_eq(y_tmp, y_u));
+ } else if (cell->type == ID($mod)) {
+ ez->assume(ez->vec_eq(y_tmp, modulo_trunc));
+ } else if (cell->type == ID($divfloor)) {
+ if (cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool())
+ ez->assume(ez->vec_eq(y_tmp, ez->vec_ite(
+ ez->XOR(a.back(), b.back()),
+ ez->vec_neg(ez->vec_ite(
+ ez->vec_reduce_or(modulo_trunc),
+ ez->vec_add(y_u, ez->vec_const_unsigned(1, y_u.size())),
+ y_u
+ )),
+ y_u
+ )));
+ else
+ ez->assume(ez->vec_eq(y_tmp, y_u));
+ } else if (cell->type == ID($modfloor)) {
+ ez->assume(ez->vec_eq(y_tmp, ez->vec_ite(floored_eq_trunc, modulo_trunc, ez->vec_add(modulo_trunc, b))));
+ }
+
+ if (ignore_div_by_zero) {
+ ez->assume(ez->expression(ezSAT::OpOr, b));
+ } else {
+ std::vector<int> div_zero_result;
+ if (cell->type.in(ID($div), ID($divfloor))) {
+ if (cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool()) {
+ std::vector<int> all_ones(y.size(), ez->CONST_TRUE);
+ std::vector<int> only_first_one(y.size(), ez->CONST_FALSE);
+ only_first_one.at(0) = ez->CONST_TRUE;
+ div_zero_result = ez->vec_ite(a.back(), only_first_one, all_ones);
+ } else {
+ div_zero_result.insert(div_zero_result.end(), cell->getPort(ID::A).size(), ez->CONST_TRUE);
+ div_zero_result.insert(div_zero_result.end(), y.size() - div_zero_result.size(), ez->CONST_FALSE);
+ }
+ } else if (cell->type.in(ID($mod), ID($modfloor))) {
+ // a mod 0 = a
+ int copy_a_bits = min(cell->getPort(ID::A).size(), cell->getPort(ID::B).size());
+ div_zero_result.insert(div_zero_result.end(), a.begin(), a.begin() + copy_a_bits);
+ if (cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool())
+ div_zero_result.insert(div_zero_result.end(), y.size() - div_zero_result.size(), div_zero_result.back());
+ else
+ div_zero_result.insert(div_zero_result.end(), y.size() - div_zero_result.size(), ez->CONST_FALSE);
+ }
+ ez->assume(ez->vec_eq(yy, ez->vec_ite(ez->expression(ezSAT::OpOr, b), y_tmp, div_zero_result)));
+ }
+
+ if (model_undef) {
+ log_assert(arith_undef_handled);
+ std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+ undefGating(y, yy, undef_y);
+ }
+ return true;
+ }
+
+ if (cell->type == ID($lut))
+ {
+ std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
+
+ std::vector<int> lut;
+ for (auto bit : cell->getParam(ID::LUT).bits)
+ lut.push_back(bit == State::S1 ? ez->CONST_TRUE : ez->CONST_FALSE);
+ while (GetSize(lut) < (1 << GetSize(a)))
+ lut.push_back(ez->CONST_FALSE);
+ lut.resize(1 << GetSize(a));
+
+ if (model_undef)
+ {
+ std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> t(lut), u(GetSize(t), ez->CONST_FALSE);
+
+ for (int i = GetSize(a)-1; i >= 0; i--)
+ {
+ std::vector<int> t0(t.begin(), t.begin() + GetSize(t)/2);
+ std::vector<int> t1(t.begin() + GetSize(t)/2, t.end());
+
+ std::vector<int> u0(u.begin(), u.begin() + GetSize(u)/2);
+ std::vector<int> u1(u.begin() + GetSize(u)/2, u.end());
+
+ t = ez->vec_ite(a[i], t1, t0);
+ u = ez->vec_ite(undef_a[i], ez->vec_or(ez->vec_xor(t0, t1), ez->vec_or(u0, u1)), ez->vec_ite(a[i], u1, u0));
+ }
+
+ log_assert(GetSize(t) == 1);
+ log_assert(GetSize(u) == 1);
+ undefGating(y, t, u);
+ ez->assume(ez->vec_eq(importUndefSigSpec(cell->getPort(ID::Y), timestep), u));
+ }
+ else
+ {
+ std::vector<int> t = lut;
+ for (int i = GetSize(a)-1; i >= 0; i--)
+ {
+ std::vector<int> t0(t.begin(), t.begin() + GetSize(t)/2);
+ std::vector<int> t1(t.begin() + GetSize(t)/2, t.end());
+ t = ez->vec_ite(a[i], t1, t0);
+ }
+
+ log_assert(GetSize(t) == 1);
+ ez->assume(ez->vec_eq(y, t));
+ }
+ return true;
+ }
+
+ if (cell->type == ID($sop))
+ {
+ std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
+ int y = importDefSigSpec(cell->getPort(ID::Y), timestep).at(0);
+
+ int width = cell->getParam(ID::WIDTH).as_int();
+ int depth = cell->getParam(ID::DEPTH).as_int();
+
+ vector<State> table_raw = cell->getParam(ID::TABLE).bits;
+ while (GetSize(table_raw) < 2*width*depth)
+ table_raw.push_back(State::S0);
+
+ vector<vector<int>> table(depth);
+
+ for (int i = 0; i < depth; i++)
+ for (int j = 0; j < width; j++)
+ {
+ bool pat0 = (table_raw[2*width*i + 2*j + 0] == State::S1);
+ bool pat1 = (table_raw[2*width*i + 2*j + 1] == State::S1);
+
+ if (pat0 && !pat1)
+ table.at(i).push_back(0);
+ else if (!pat0 && pat1)
+ table.at(i).push_back(1);
+ else
+ table.at(i).push_back(-1);
+ }
+
+ if (model_undef)
+ {
+ std::vector<int> products, undef_products;
+ std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
+ int undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep).at(0);
+
+ for (int i = 0; i < depth; i++)
+ {
+ std::vector<int> cmp_a, cmp_ua, cmp_b;
+
+ for (int j = 0; j < width; j++)
+ if (table.at(i).at(j) >= 0) {
+ cmp_a.push_back(a.at(j));
+ cmp_ua.push_back(undef_a.at(j));
+ cmp_b.push_back(table.at(i).at(j) ? ez->CONST_TRUE : ez->CONST_FALSE);
+ }
+
+ std::vector<int> masked_a = ez->vec_or(cmp_a, cmp_ua);
+ std::vector<int> masked_b = ez->vec_or(cmp_b, cmp_ua);
+
+ int masked_eq = ez->vec_eq(masked_a, masked_b);
+ int any_undef = ez->expression(ezSAT::OpOr, cmp_ua);
+
+ undef_products.push_back(ez->AND(any_undef, masked_eq));
+ products.push_back(ez->AND(ez->NOT(any_undef), masked_eq));
+ }
+
+ int yy = ez->expression(ezSAT::OpOr, products);
+ ez->SET(undef_y, ez->AND(ez->NOT(yy), ez->expression(ezSAT::OpOr, undef_products)));
+ undefGating(y, yy, undef_y);
+ }
+ else
+ {
+ std::vector<int> products;
+
+ for (int i = 0; i < depth; i++)
+ {
+ std::vector<int> cmp_a, cmp_b;
+
+ for (int j = 0; j < width; j++)
+ if (table.at(i).at(j) >= 0) {
+ cmp_a.push_back(a.at(j));
+ cmp_b.push_back(table.at(i).at(j) ? ez->CONST_TRUE : ez->CONST_FALSE);
+ }
+
+ products.push_back(ez->vec_eq(cmp_a, cmp_b));
+ }
+
+ ez->SET(y, ez->expression(ezSAT::OpOr, products));
+ }
+
+ return true;
+ }
+
+ if (cell->type == ID($fa))
+ {
+ std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
+ std::vector<int> c = importDefSigSpec(cell->getPort(ID::C), timestep);
+ std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
+ std::vector<int> x = importDefSigSpec(cell->getPort(ID::X), timestep);
+
+ std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
+ std::vector<int> xx = model_undef ? ez->vec_var(x.size()) : x;
+
+ std::vector<int> t1 = ez->vec_xor(a, b);
+ ez->assume(ez->vec_eq(yy, ez->vec_xor(t1, c)));
+
+ std::vector<int> t2 = ez->vec_and(a, b);
+ std::vector<int> t3 = ez->vec_and(c, t1);
+ ez->assume(ez->vec_eq(xx, ez->vec_or(t2, t3)));
+
+ if (model_undef)
+ {
+ std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
+ std::vector<int> undef_c = importUndefSigSpec(cell->getPort(ID::C), timestep);
+
+ std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+ std::vector<int> undef_x = importUndefSigSpec(cell->getPort(ID::X), timestep);
+
+ ez->assume(ez->vec_eq(undef_y, ez->vec_or(ez->vec_or(undef_a, undef_b), undef_c)));
+ ez->assume(ez->vec_eq(undef_x, undef_y));
+
+ undefGating(y, yy, undef_y);
+ undefGating(x, xx, undef_x);
+ }
+ return true;
+ }
+
+ if (cell->type == ID($lcu))
+ {
+ std::vector<int> p = importDefSigSpec(cell->getPort(ID::P), timestep);
+ std::vector<int> g = importDefSigSpec(cell->getPort(ID::G), timestep);
+ std::vector<int> ci = importDefSigSpec(cell->getPort(ID::CI), timestep);
+ std::vector<int> co = importDefSigSpec(cell->getPort(ID::CO), timestep);
+
+ std::vector<int> yy = model_undef ? ez->vec_var(co.size()) : co;
+
+ for (int i = 0; i < GetSize(co); i++)
+ ez->SET(yy[i], ez->OR(g[i], ez->AND(p[i], i ? yy[i-1] : ci[0])));
+
+ if (model_undef)
+ {
+ std::vector<int> undef_p = importUndefSigSpec(cell->getPort(ID::P), timestep);
+ std::vector<int> undef_g = importUndefSigSpec(cell->getPort(ID::G), timestep);
+ std::vector<int> undef_ci = importUndefSigSpec(cell->getPort(ID::CI), timestep);
+ std::vector<int> undef_co = importUndefSigSpec(cell->getPort(ID::CO), timestep);
+
+ int undef_any_p = ez->expression(ezSAT::OpOr, undef_p);
+ int undef_any_g = ez->expression(ezSAT::OpOr, undef_g);
+ int undef_any_ci = ez->expression(ezSAT::OpOr, undef_ci);
+ int undef_co_bit = ez->OR(undef_any_p, undef_any_g, undef_any_ci);
+
+ std::vector<int> undef_co_bits(undef_co.size(), undef_co_bit);
+ ez->assume(ez->vec_eq(undef_co_bits, undef_co));
+
+ undefGating(co, yy, undef_co);
+ }
+ return true;
+ }
+
+ if (cell->type == ID($alu))
+ {
+ std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
+ std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
+ std::vector<int> x = importDefSigSpec(cell->getPort(ID::X), timestep);
+ std::vector<int> ci = importDefSigSpec(cell->getPort(ID::CI), timestep);
+ std::vector<int> bi = importDefSigSpec(cell->getPort(ID::BI), timestep);
+ std::vector<int> co = importDefSigSpec(cell->getPort(ID::CO), timestep);
+
+ extendSignalWidth(a, b, y, cell);
+ extendSignalWidth(a, b, x, cell);
+ extendSignalWidth(a, b, co, cell);
+
+ std::vector<int> def_y = model_undef ? ez->vec_var(y.size()) : y;
+ std::vector<int> def_x = model_undef ? ez->vec_var(x.size()) : x;
+ std::vector<int> def_co = model_undef ? ez->vec_var(co.size()) : co;
+
+ log_assert(GetSize(y) == GetSize(x));
+ log_assert(GetSize(y) == GetSize(co));
+ log_assert(GetSize(ci) == 1);
+ log_assert(GetSize(bi) == 1);
+
+ for (int i = 0; i < GetSize(y); i++)
+ {
+ int s1 = a.at(i), s2 = ez->XOR(b.at(i), bi.at(0)), s3 = i ? co.at(i-1) : ci.at(0);
+ ez->SET(def_x.at(i), ez->XOR(s1, s2));
+ ez->SET(def_y.at(i), ez->XOR(def_x.at(i), s3));
+ ez->SET(def_co.at(i), ez->OR(ez->AND(s1, s2), ez->AND(s1, s3), ez->AND(s2, s3)));
+ }
+
+ if (model_undef)
+ {
+ std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
+ std::vector<int> undef_ci = importUndefSigSpec(cell->getPort(ID::CI), timestep);
+ std::vector<int> undef_bi = importUndefSigSpec(cell->getPort(ID::BI), timestep);
+
+ std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+ std::vector<int> undef_x = importUndefSigSpec(cell->getPort(ID::X), timestep);
+ std::vector<int> undef_co = importUndefSigSpec(cell->getPort(ID::CO), timestep);
+
+ extendSignalWidth(undef_a, undef_b, undef_y, cell);
+ extendSignalWidth(undef_a, undef_b, undef_x, cell);
+ extendSignalWidth(undef_a, undef_b, undef_co, cell);
+
+ std::vector<int> all_inputs_undef;
+ all_inputs_undef.insert(all_inputs_undef.end(), undef_a.begin(), undef_a.end());
+ all_inputs_undef.insert(all_inputs_undef.end(), undef_b.begin(), undef_b.end());
+ all_inputs_undef.insert(all_inputs_undef.end(), undef_ci.begin(), undef_ci.end());
+ all_inputs_undef.insert(all_inputs_undef.end(), undef_bi.begin(), undef_bi.end());
+ int undef_any = ez->expression(ezSAT::OpOr, all_inputs_undef);
+
+ for (int i = 0; i < GetSize(undef_y); i++) {
+ ez->SET(undef_y.at(i), undef_any);
+ ez->SET(undef_x.at(i), ez->OR(undef_a.at(i), undef_b.at(i), undef_bi.at(0)));
+ ez->SET(undef_co.at(i), undef_any);
+ }
+
+ undefGating(y, def_y, undef_y);
+ undefGating(x, def_x, undef_x);
+ undefGating(co, def_co, undef_co);
+ }
+ return true;
+ }
+
+ if (cell->type == ID($slice))
+ {
+ RTLIL::SigSpec a = cell->getPort(ID::A);
+ RTLIL::SigSpec y = cell->getPort(ID::Y);
+ ez->assume(signals_eq(a.extract(cell->parameters.at(ID::OFFSET).as_int(), y.size()), y, timestep));
+ return true;
+ }
+
+ if (cell->type == ID($concat))
+ {
+ RTLIL::SigSpec a = cell->getPort(ID::A);
+ RTLIL::SigSpec b = cell->getPort(ID::B);
+ RTLIL::SigSpec y = cell->getPort(ID::Y);
+
+ RTLIL::SigSpec ab = a;
+ ab.append(b);
+
+ ez->assume(signals_eq(ab, y, timestep));
+ return true;
+ }
+
+ if (timestep > 0 && RTLIL::builtin_ff_cell_types().count(cell->type))
+ {
+ FfData ff(nullptr, cell);
+
+ // Latches and FFs with async inputs are not supported — use clk2fflogic or async2sync first.
+ if (ff.has_aload || ff.has_arst || ff.has_sr)
+ return false;
+
+ if (timestep == 1)
+ {
+ initial_state.add((*sigmap)(cell->getPort(ID::Q)));
+ }
+ else
+ {
+ std::vector<int> d = importDefSigSpec(cell->getPort(ID::D), timestep-1);
+ std::vector<int> undef_d;
+ if (model_undef)
+ undef_d = importUndefSigSpec(cell->getPort(ID::D), timestep-1);
+ 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;
+ std::vector<int> undef_rval;
+ if (model_undef) {
+ undef_srst = importUndefSigSpec(ff.sig_srst, timestep-1).at(0);
+ undef_rval = importUndefSigSpec(ff.val_srst, timestep-1);
+ }
+ if (ff.pol_srst)
+ std::tie(d, undef_d) = mux(srst, undef_srst, d, undef_d, rval, undef_rval);
+ else
+ std::tie(d, undef_d) = mux(srst, undef_srst, rval, undef_rval, d, undef_d);
+ }
+ 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_ce;
+ std::vector<int> undef_old_q;
+ if (model_undef) {
+ undef_ce = importUndefSigSpec(ff.sig_ce, timestep-1).at(0);
+ undef_old_q = importUndefSigSpec(ff.sig_q, timestep-1);
+ }
+ 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(ce, undef_ce, d, undef_d, old_q, undef_old_q);
+ }
+ 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;
+ std::vector<int> undef_rval;
+ if (model_undef) {
+ undef_srst = importUndefSigSpec(ff.sig_srst, timestep-1).at(0);
+ undef_rval = importUndefSigSpec(ff.val_srst, timestep-1);
+ }
+ if (ff.pol_srst)
+ std::tie(d, undef_d) = mux(srst, undef_srst, d, undef_d, rval, undef_rval);
+ else
+ std::tie(d, undef_d) = mux(srst, undef_srst, rval, undef_rval, d, undef_d);
+ }
+ std::vector<int> q = importDefSigSpec(cell->getPort(ID::Q), timestep);
+
+ std::vector<int> qq = model_undef ? ez->vec_var(q.size()) : q;
+ ez->assume(ez->vec_eq(d, qq));
+
+ if (model_undef)
+ {
+ std::vector<int> undef_q = importUndefSigSpec(cell->getPort(ID::Q), timestep);
+
+ ez->assume(ez->vec_eq(undef_d, undef_q));
+ undefGating(q, qq, undef_q);
+ }
+ }
+ return true;
+ }
+
+ if (cell->type == ID($anyconst))
+ {
+ if (timestep < 2)
+ return true;
+
+ std::vector<int> d = importDefSigSpec(cell->getPort(ID::Y), timestep-1);
+ std::vector<int> q = importDefSigSpec(cell->getPort(ID::Y), timestep);
+
+ std::vector<int> qq = model_undef ? ez->vec_var(q.size()) : q;
+ ez->assume(ez->vec_eq(d, qq));
+
+ if (model_undef)
+ {
+ std::vector<int> undef_d = importUndefSigSpec(cell->getPort(ID::Y), timestep-1);
+ std::vector<int> undef_q = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+
+ ez->assume(ez->vec_eq(undef_d, undef_q));
+ undefGating(q, qq, undef_q);
+ }
+ return true;
+ }
+
+ if (cell->type == ID($anyseq))
+ {
+ return true;
+ }
+
+ if (cell->type.in(ID($_BUF_), ID($equiv)))
+ {
+ std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
+ extendSignalWidthUnary(a, y, cell);
+
+ std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
+ ez->assume(ez->vec_eq(a, yy));
+
+ if (model_undef) {
+ std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+ extendSignalWidthUnary(undef_a, undef_y, cell, false);
+ ez->assume(ez->vec_eq(undef_a, undef_y));
+ undefGating(y, yy, undef_y);
+ }
+ return true;
+ }
+
+ if (cell->type == ID($initstate))
+ {
+ auto key = make_pair(prefix, timestep);
+ if (initstates.count(key) == 0)
+ initstates[key] = false;
+
+ std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
+ log_assert(GetSize(y) == 1);
+ ez->SET(y[0], initstates[key] ? ez->CONST_TRUE : ez->CONST_FALSE);
+
+ if (model_undef) {
+ std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+ log_assert(GetSize(undef_y) == 1);
+ ez->SET(undef_y[0], ez->CONST_FALSE);
+ }
+
+ return true;
+ }
+
+ if (cell->type == ID($assert))
+ {
+ std::string pf = prefix + (timestep == -1 ? "" : stringf("@%d:", timestep));
+ asserts_a[pf].append((*sigmap)(cell->getPort(ID::A)));
+ asserts_en[pf].append((*sigmap)(cell->getPort(ID::EN)));
+ return true;
+ }
+
+ if (cell->type == ID($assume))
+ {
+ std::string pf = prefix + (timestep == -1 ? "" : stringf("@%d:", timestep));
+ assumes_a[pf].append((*sigmap)(cell->getPort(ID::A)));
+ assumes_en[pf].append((*sigmap)(cell->getPort(ID::EN)));
+ return true;
+ }
+
+ // Unsupported internal cell types: $pow $fsm $mem*
+ // .. and all sequential cells with asynchronous inputs
+ return false;
+}
diff --git a/kernel/satgen.h b/kernel/satgen.h
index 3929a8708..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
@@ -262,6 +262,18 @@ struct SatGen
}
}
+ std::pair<std::vector<int>, std::vector<int>> mux(int s, int undef_s, const std::vector<int> &a, const std::vector<int> &undef_a, const std::vector<int> &b, const std::vector<int> &undef_b) {
+ std::vector<int> res;
+ std::vector<int> undef_res;
+ res = ez->vec_ite(s, b, a);
+ if (model_undef) {
+ std::vector<int> unequal_ab = ez->vec_not(ez->vec_iff(a, b));
+ std::vector<int> undef_ab = ez->vec_or(unequal_ab, ez->vec_or(undef_a, undef_b));
+ undef_res = ez->vec_ite(undef_s, undef_ab, ez->vec_ite(s, undef_b, undef_a));
+ }
+ return std::make_pair(res, undef_res);
+ }
+
void undefGating(int y, int yy, int undef)
{
ez->assume(ez->OR(undef, ez->IFF(y, yy)));
@@ -274,1171 +286,7 @@ struct SatGen
initstates[key] = true;
}
- bool importCell(RTLIL::Cell *cell, int timestep = -1)
- {
- bool arith_undef_handled = false;
- bool is_arith_compare = cell->type.in(ID($lt), ID($le), ID($ge), ID($gt));
-
- if (model_undef && (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($divfloor), ID($modfloor)) || is_arith_compare))
- {
- std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
- std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
- if (is_arith_compare)
- extendSignalWidth(undef_a, undef_b, cell, true);
- else
- extendSignalWidth(undef_a, undef_b, undef_y, cell, true);
-
- int undef_any_a = ez->expression(ezSAT::OpOr, undef_a);
- int undef_any_b = ez->expression(ezSAT::OpOr, undef_b);
- int undef_y_bit = ez->OR(undef_any_a, undef_any_b);
-
- if (cell->type.in(ID($div), ID($mod), ID($divfloor), ID($modfloor))) {
- std::vector<int> b = importSigSpec(cell->getPort(ID::B), timestep);
- undef_y_bit = ez->OR(undef_y_bit, ez->NOT(ez->expression(ezSAT::OpOr, b)));
- }
-
- if (is_arith_compare) {
- for (size_t i = 1; i < undef_y.size(); i++)
- ez->SET(ez->CONST_FALSE, undef_y.at(i));
- ez->SET(undef_y_bit, undef_y.at(0));
- } else {
- std::vector<int> undef_y_bits(undef_y.size(), undef_y_bit);
- ez->assume(ez->vec_eq(undef_y_bits, undef_y));
- }
-
- arith_undef_handled = true;
- }
-
- if (cell->type.in(ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_),
- ID($and), ID($or), ID($xor), ID($xnor), ID($add), ID($sub)))
- {
- std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
- std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
- extendSignalWidth(a, b, y, cell);
-
- std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
-
- if (cell->type.in(ID($and), ID($_AND_)))
- ez->assume(ez->vec_eq(ez->vec_and(a, b), yy));
- if (cell->type == ID($_NAND_))
- ez->assume(ez->vec_eq(ez->vec_not(ez->vec_and(a, b)), yy));
- if (cell->type.in(ID($or), ID($_OR_)))
- ez->assume(ez->vec_eq(ez->vec_or(a, b), yy));
- if (cell->type == ID($_NOR_))
- ez->assume(ez->vec_eq(ez->vec_not(ez->vec_or(a, b)), yy));
- if (cell->type.in(ID($xor), ID($_XOR_)))
- ez->assume(ez->vec_eq(ez->vec_xor(a, b), yy));
- if (cell->type.in(ID($xnor), ID($_XNOR_)))
- ez->assume(ez->vec_eq(ez->vec_not(ez->vec_xor(a, b)), yy));
- if (cell->type == ID($_ANDNOT_))
- ez->assume(ez->vec_eq(ez->vec_and(a, ez->vec_not(b)), yy));
- if (cell->type == ID($_ORNOT_))
- ez->assume(ez->vec_eq(ez->vec_or(a, ez->vec_not(b)), yy));
- if (cell->type == ID($add))
- ez->assume(ez->vec_eq(ez->vec_add(a, b), yy));
- if (cell->type == ID($sub))
- ez->assume(ez->vec_eq(ez->vec_sub(a, b), yy));
-
- if (model_undef && !arith_undef_handled)
- {
- std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
- std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
- extendSignalWidth(undef_a, undef_b, undef_y, cell, false);
-
- if (cell->type.in(ID($and), ID($_AND_), ID($_NAND_))) {
- std::vector<int> a0 = ez->vec_and(ez->vec_not(a), ez->vec_not(undef_a));
- std::vector<int> b0 = ez->vec_and(ez->vec_not(b), ez->vec_not(undef_b));
- std::vector<int> yX = ez->vec_and(ez->vec_or(undef_a, undef_b), ez->vec_not(ez->vec_or(a0, b0)));
- ez->assume(ez->vec_eq(yX, undef_y));
- }
- else if (cell->type.in(ID($or), ID($_OR_), ID($_NOR_))) {
- std::vector<int> a1 = ez->vec_and(a, ez->vec_not(undef_a));
- std::vector<int> b1 = ez->vec_and(b, ez->vec_not(undef_b));
- std::vector<int> yX = ez->vec_and(ez->vec_or(undef_a, undef_b), ez->vec_not(ez->vec_or(a1, b1)));
- ez->assume(ez->vec_eq(yX, undef_y));
- }
- else if (cell->type.in(ID($xor), ID($xnor), ID($_XOR_), ID($_XNOR_))) {
- std::vector<int> yX = ez->vec_or(undef_a, undef_b);
- ez->assume(ez->vec_eq(yX, undef_y));
- }
- else if (cell->type == ID($_ANDNOT_)) {
- std::vector<int> a0 = ez->vec_and(ez->vec_not(a), ez->vec_not(undef_a));
- std::vector<int> b1 = ez->vec_and(b, ez->vec_not(undef_b));
- std::vector<int> yX = ez->vec_and(ez->vec_or(undef_a, undef_b), ez->vec_not(ez->vec_or(a0, b1)));
- ez->assume(ez->vec_eq(yX, undef_y));
- }
-
- else if (cell->type == ID($_ORNOT_)) {
- std::vector<int> a1 = ez->vec_and(a, ez->vec_not(undef_a));
- std::vector<int> b0 = ez->vec_and(ez->vec_not(b), ez->vec_not(undef_b));
- std::vector<int> yX = ez->vec_and(ez->vec_or(undef_a, undef_b), ez->vec_not(ez->vec_or(a1, b0)));
- ez->assume(ez->vec_eq(yX, undef_y));
- }
- else
- log_abort();
-
- undefGating(y, yy, undef_y);
- }
- else if (model_undef)
- {
- std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
- undefGating(y, yy, undef_y);
- }
- return true;
- }
-
- if (cell->type.in(ID($_AOI3_), ID($_OAI3_), ID($_AOI4_), ID($_OAI4_)))
- {
- bool aoi_mode = cell->type.in(ID($_AOI3_), ID($_AOI4_));
- bool three_mode = cell->type.in(ID($_AOI3_), ID($_OAI3_));
-
- int a = importDefSigSpec(cell->getPort(ID::A), timestep).at(0);
- int b = importDefSigSpec(cell->getPort(ID::B), timestep).at(0);
- int c = importDefSigSpec(cell->getPort(ID::C), timestep).at(0);
- int d = three_mode ? (aoi_mode ? ez->CONST_TRUE : ez->CONST_FALSE) : importDefSigSpec(cell->getPort(ID::D), timestep).at(0);
- int y = importDefSigSpec(cell->getPort(ID::Y), timestep).at(0);
- int yy = model_undef ? ez->literal() : y;
-
- if (cell->type.in(ID($_AOI3_), ID($_AOI4_)))
- ez->assume(ez->IFF(ez->NOT(ez->OR(ez->AND(a, b), ez->AND(c, d))), yy));
- else
- ez->assume(ez->IFF(ez->NOT(ez->AND(ez->OR(a, b), ez->OR(c, d))), yy));
-
- if (model_undef)
- {
- int undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep).at(0);
- int undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep).at(0);
- int undef_c = importUndefSigSpec(cell->getPort(ID::C), timestep).at(0);
- int undef_d = three_mode ? ez->CONST_FALSE : importUndefSigSpec(cell->getPort(ID::D), timestep).at(0);
- int undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep).at(0);
-
- if (aoi_mode)
- {
- int a0 = ez->AND(ez->NOT(a), ez->NOT(undef_a));
- int b0 = ez->AND(ez->NOT(b), ez->NOT(undef_b));
- int c0 = ez->AND(ez->NOT(c), ez->NOT(undef_c));
- int d0 = ez->AND(ez->NOT(d), ez->NOT(undef_d));
-
- int ab = ez->AND(a, b), cd = ez->AND(c, d);
- int undef_ab = ez->AND(ez->OR(undef_a, undef_b), ez->NOT(ez->OR(a0, b0)));
- int undef_cd = ez->AND(ez->OR(undef_c, undef_d), ez->NOT(ez->OR(c0, d0)));
-
- int ab1 = ez->AND(ab, ez->NOT(undef_ab));
- int cd1 = ez->AND(cd, ez->NOT(undef_cd));
- int yX = ez->AND(ez->OR(undef_ab, undef_cd), ez->NOT(ez->OR(ab1, cd1)));
-
- ez->assume(ez->IFF(yX, undef_y));
- }
- else
- {
- int a1 = ez->AND(a, ez->NOT(undef_a));
- int b1 = ez->AND(b, ez->NOT(undef_b));
- int c1 = ez->AND(c, ez->NOT(undef_c));
- int d1 = ez->AND(d, ez->NOT(undef_d));
-
- int ab = ez->OR(a, b), cd = ez->OR(c, d);
- int undef_ab = ez->AND(ez->OR(undef_a, undef_b), ez->NOT(ez->OR(a1, b1)));
- int undef_cd = ez->AND(ez->OR(undef_c, undef_d), ez->NOT(ez->OR(c1, d1)));
-
- int ab0 = ez->AND(ez->NOT(ab), ez->NOT(undef_ab));
- int cd0 = ez->AND(ez->NOT(cd), ez->NOT(undef_cd));
- int yX = ez->AND(ez->OR(undef_ab, undef_cd), ez->NOT(ez->OR(ab0, cd0)));
-
- ez->assume(ez->IFF(yX, undef_y));
- }
-
- undefGating(y, yy, undef_y);
- }
-
- return true;
- }
-
- if (cell->type.in(ID($_NOT_), ID($not)))
- {
- std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
- extendSignalWidthUnary(a, y, cell);
-
- std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
- ez->assume(ez->vec_eq(ez->vec_not(a), yy));
-
- if (model_undef) {
- std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
- extendSignalWidthUnary(undef_a, undef_y, cell, false);
- ez->assume(ez->vec_eq(undef_a, undef_y));
- undefGating(y, yy, undef_y);
- }
- return true;
- }
-
- if (cell->type.in(ID($_MUX_), ID($mux), ID($_NMUX_)))
- {
- std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), 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;
- if (cell->type == ID($_NMUX_))
- ez->assume(ez->vec_eq(ez->vec_not(ez->vec_ite(s.at(0), b, a)), yy));
- else
- ez->assume(ez->vec_eq(ez->vec_ite(s.at(0), b, a), yy));
-
- if (model_undef)
- {
- std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
- std::vector<int> undef_s = importUndefSigSpec(cell->getPort(ID::S), timestep);
- std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
-
- std::vector<int> unequal_ab = ez->vec_not(ez->vec_iff(a, b));
- std::vector<int> undef_ab = ez->vec_or(unequal_ab, ez->vec_or(undef_a, undef_b));
- std::vector<int> yX = ez->vec_ite(undef_s.at(0), undef_ab, ez->vec_ite(s.at(0), undef_b, undef_a));
- ez->assume(ez->vec_eq(yX, undef_y));
- undefGating(y, yy, undef_y);
- }
- return true;
- }
-
- if (cell->type == ID($pmux))
- {
- std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), 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> tmp = a;
- for (size_t i = 0; i < s.size(); i++) {
- std::vector<int> part_of_b(b.begin()+i*a.size(), b.begin()+(i+1)*a.size());
- tmp = ez->vec_ite(s.at(i), part_of_b, tmp);
- }
- ez->assume(ez->vec_eq(tmp, yy));
-
- if (model_undef)
- {
- std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
- std::vector<int> undef_s = importUndefSigSpec(cell->getPort(ID::S), timestep);
- std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
-
- int maybe_a = ez->CONST_TRUE;
-
- std::vector<int> bits_set = std::vector<int>(undef_y.size(), ez->CONST_FALSE);
- std::vector<int> bits_clr = std::vector<int>(undef_y.size(), ez->CONST_FALSE);
-
- for (size_t i = 0; i < s.size(); i++)
- {
- std::vector<int> part_of_b(b.begin()+i*a.size(), b.begin()+(i+1)*a.size());
- std::vector<int> part_of_undef_b(undef_b.begin()+i*a.size(), undef_b.begin()+(i+1)*a.size());
-
- int maybe_s = ez->OR(s.at(i), undef_s.at(i));
- int sure_s = ez->AND(s.at(i), ez->NOT(undef_s.at(i)));
-
- maybe_a = ez->AND(maybe_a, ez->NOT(sure_s));
-
- bits_set = ez->vec_ite(maybe_s, ez->vec_or(bits_set, ez->vec_or(part_of_b, part_of_undef_b)), bits_set);
- bits_clr = ez->vec_ite(maybe_s, ez->vec_or(bits_clr, ez->vec_or(ez->vec_not(part_of_b), part_of_undef_b)), bits_clr);
- }
-
- bits_set = ez->vec_ite(maybe_a, ez->vec_or(bits_set, ez->vec_or(bits_set, ez->vec_or(a, undef_a))), bits_set);
- bits_clr = ez->vec_ite(maybe_a, ez->vec_or(bits_clr, ez->vec_or(bits_clr, ez->vec_or(ez->vec_not(a), undef_a))), bits_clr);
-
- ez->assume(ez->vec_eq(ez->vec_not(ez->vec_xor(bits_set, bits_clr)), undef_y));
- undefGating(y, yy, undef_y);
- }
- return true;
- }
-
- if (cell->type.in(ID($pos), ID($neg)))
- {
- std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
- extendSignalWidthUnary(a, y, cell);
-
- std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
-
- if (cell->type == ID($pos)) {
- ez->assume(ez->vec_eq(a, yy));
- } else {
- std::vector<int> zero(a.size(), ez->CONST_FALSE);
- ez->assume(ez->vec_eq(ez->vec_sub(zero, a), yy));
- }
-
- if (model_undef)
- {
- std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
- extendSignalWidthUnary(undef_a, undef_y, cell);
-
- if (cell->type == ID($pos)) {
- ez->assume(ez->vec_eq(undef_a, undef_y));
- } else {
- int undef_any_a = ez->expression(ezSAT::OpOr, undef_a);
- std::vector<int> undef_y_bits(undef_y.size(), undef_any_a);
- ez->assume(ez->vec_eq(undef_y_bits, undef_y));
- }
-
- undefGating(y, yy, undef_y);
- }
- return true;
- }
-
- if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool), ID($logic_not)))
- {
- std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
-
- std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
-
- if (cell->type == ID($reduce_and))
- ez->SET(ez->expression(ez->OpAnd, a), yy.at(0));
- if (cell->type.in(ID($reduce_or), ID($reduce_bool)))
- ez->SET(ez->expression(ez->OpOr, a), yy.at(0));
- if (cell->type == ID($reduce_xor))
- ez->SET(ez->expression(ez->OpXor, a), yy.at(0));
- if (cell->type == ID($reduce_xnor))
- ez->SET(ez->NOT(ez->expression(ez->OpXor, a)), yy.at(0));
- if (cell->type == ID($logic_not))
- ez->SET(ez->NOT(ez->expression(ez->OpOr, a)), yy.at(0));
- for (size_t i = 1; i < y.size(); i++)
- ez->SET(ez->CONST_FALSE, yy.at(i));
-
- if (model_undef)
- {
- std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
- int aX = ez->expression(ezSAT::OpOr, undef_a);
-
- if (cell->type == ID($reduce_and)) {
- int a0 = ez->expression(ezSAT::OpOr, ez->vec_and(ez->vec_not(a), ez->vec_not(undef_a)));
- ez->assume(ez->IFF(ez->AND(ez->NOT(a0), aX), undef_y.at(0)));
- }
- else if (cell->type.in(ID($reduce_or), ID($reduce_bool), ID($logic_not))) {
- int a1 = ez->expression(ezSAT::OpOr, ez->vec_and(a, ez->vec_not(undef_a)));
- ez->assume(ez->IFF(ez->AND(ez->NOT(a1), aX), undef_y.at(0)));
- }
- else if (cell->type.in(ID($reduce_xor), ID($reduce_xnor))) {
- ez->assume(ez->IFF(aX, undef_y.at(0)));
- } else
- log_abort();
-
- for (size_t i = 1; i < undef_y.size(); i++)
- ez->SET(ez->CONST_FALSE, undef_y.at(i));
-
- undefGating(y, yy, undef_y);
- }
- return true;
- }
-
- if (cell->type.in(ID($logic_and), ID($logic_or)))
- {
- std::vector<int> vec_a = importDefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> vec_b = importDefSigSpec(cell->getPort(ID::B), timestep);
-
- int a = ez->expression(ez->OpOr, vec_a);
- int b = ez->expression(ez->OpOr, vec_b);
- std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
-
- std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
-
- if (cell->type == ID($logic_and))
- ez->SET(ez->expression(ez->OpAnd, a, b), yy.at(0));
- else
- ez->SET(ez->expression(ez->OpOr, a, b), yy.at(0));
- for (size_t i = 1; i < y.size(); i++)
- ez->SET(ez->CONST_FALSE, yy.at(i));
-
- if (model_undef)
- {
- std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
- std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
-
- int a0 = ez->NOT(ez->OR(ez->expression(ezSAT::OpOr, vec_a), ez->expression(ezSAT::OpOr, undef_a)));
- int b0 = ez->NOT(ez->OR(ez->expression(ezSAT::OpOr, vec_b), ez->expression(ezSAT::OpOr, undef_b)));
- int a1 = ez->expression(ezSAT::OpOr, ez->vec_and(vec_a, ez->vec_not(undef_a)));
- int b1 = ez->expression(ezSAT::OpOr, ez->vec_and(vec_b, ez->vec_not(undef_b)));
- int aX = ez->expression(ezSAT::OpOr, undef_a);
- int bX = ez->expression(ezSAT::OpOr, undef_b);
-
- if (cell->type == ID($logic_and))
- ez->SET(ez->AND(ez->OR(aX, bX), ez->NOT(ez->AND(a1, b1)), ez->NOT(a0), ez->NOT(b0)), undef_y.at(0));
- else if (cell->type == ID($logic_or))
- ez->SET(ez->AND(ez->OR(aX, bX), ez->NOT(ez->AND(a0, b0)), ez->NOT(a1), ez->NOT(b1)), undef_y.at(0));
- else
- log_abort();
-
- for (size_t i = 1; i < undef_y.size(); i++)
- ez->SET(ez->CONST_FALSE, undef_y.at(i));
-
- undefGating(y, yy, undef_y);
- }
- return true;
- }
-
- if (cell->type.in(ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt)))
- {
- bool is_signed = cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool();
- std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
- std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
- extendSignalWidth(a, b, cell);
-
- std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
-
- if (model_undef && cell->type.in(ID($eqx), ID($nex))) {
- std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
- extendSignalWidth(undef_a, undef_b, cell, true);
- a = ez->vec_or(a, undef_a);
- b = ez->vec_or(b, undef_b);
- }
-
- if (cell->type == ID($lt))
- ez->SET(is_signed ? ez->vec_lt_signed(a, b) : ez->vec_lt_unsigned(a, b), yy.at(0));
- if (cell->type == ID($le))
- ez->SET(is_signed ? ez->vec_le_signed(a, b) : ez->vec_le_unsigned(a, b), yy.at(0));
- if (cell->type.in(ID($eq), ID($eqx)))
- ez->SET(ez->vec_eq(a, b), yy.at(0));
- if (cell->type.in(ID($ne), ID($nex)))
- ez->SET(ez->vec_ne(a, b), yy.at(0));
- if (cell->type == ID($ge))
- ez->SET(is_signed ? ez->vec_ge_signed(a, b) : ez->vec_ge_unsigned(a, b), yy.at(0));
- if (cell->type == ID($gt))
- ez->SET(is_signed ? ez->vec_gt_signed(a, b) : ez->vec_gt_unsigned(a, b), yy.at(0));
- for (size_t i = 1; i < y.size(); i++)
- ez->SET(ez->CONST_FALSE, yy.at(i));
-
- if (model_undef && cell->type.in(ID($eqx), ID($nex)))
- {
- std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
- std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
- extendSignalWidth(undef_a, undef_b, cell, true);
-
- if (cell->type == ID($eqx))
- yy.at(0) = ez->AND(yy.at(0), ez->vec_eq(undef_a, undef_b));
- else
- yy.at(0) = ez->OR(yy.at(0), ez->vec_ne(undef_a, undef_b));
-
- for (size_t i = 0; i < y.size(); i++)
- ez->SET(ez->CONST_FALSE, undef_y.at(i));
-
- ez->assume(ez->vec_eq(y, yy));
- }
- else if (model_undef && cell->type.in(ID($eq), ID($ne)))
- {
- std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
- std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
- extendSignalWidth(undef_a, undef_b, cell, true);
-
- int undef_any_a = ez->expression(ezSAT::OpOr, undef_a);
- int undef_any_b = ez->expression(ezSAT::OpOr, undef_b);
- int undef_any = ez->OR(undef_any_a, undef_any_b);
-
- std::vector<int> masked_a_bits = ez->vec_or(a, ez->vec_or(undef_a, undef_b));
- std::vector<int> masked_b_bits = ez->vec_or(b, ez->vec_or(undef_a, undef_b));
-
- int masked_ne = ez->vec_ne(masked_a_bits, masked_b_bits);
- int undef_y_bit = ez->AND(undef_any, ez->NOT(masked_ne));
-
- for (size_t i = 1; i < undef_y.size(); i++)
- ez->SET(ez->CONST_FALSE, undef_y.at(i));
- ez->SET(undef_y_bit, undef_y.at(0));
-
- undefGating(y, yy, undef_y);
- }
- else
- {
- if (model_undef) {
- std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
- undefGating(y, yy, undef_y);
- }
- log_assert(!model_undef || arith_undef_handled);
- }
- return true;
- }
-
- if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)))
- {
- std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
- std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
-
- int extend_bit = ez->CONST_FALSE;
-
- if (!cell->type.in(ID($shift), ID($shiftx)) && cell->parameters[ID::A_SIGNED].as_bool())
- extend_bit = a.back();
-
- while (y.size() < a.size())
- y.push_back(ez->literal());
- while (y.size() > a.size())
- a.push_back(extend_bit);
-
- std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
- std::vector<int> shifted_a;
-
- if (cell->type.in( ID($shl), ID($sshl)))
- shifted_a = ez->vec_shift_left(a, b, false, ez->CONST_FALSE, ez->CONST_FALSE);
-
- if (cell->type == ID($shr))
- shifted_a = ez->vec_shift_right(a, b, false, ez->CONST_FALSE, ez->CONST_FALSE);
-
- if (cell->type == ID($sshr))
- shifted_a = ez->vec_shift_right(a, b, false, cell->parameters[ID::A_SIGNED].as_bool() ? a.back() : ez->CONST_FALSE, ez->CONST_FALSE);
-
- if (cell->type.in(ID($shift), ID($shiftx)))
- shifted_a = ez->vec_shift_right(a, b, cell->parameters[ID::B_SIGNED].as_bool(), ez->CONST_FALSE, ez->CONST_FALSE);
-
- ez->assume(ez->vec_eq(shifted_a, yy));
-
- if (model_undef)
- {
- std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
- std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
- std::vector<int> undef_a_shifted;
-
- extend_bit = cell->type == ID($shiftx) ? ez->CONST_TRUE : ez->CONST_FALSE;
- if (!cell->type.in(ID($shift), ID($shiftx)) && cell->parameters[ID::A_SIGNED].as_bool())
- extend_bit = undef_a.back();
-
- while (undef_y.size() < undef_a.size())
- undef_y.push_back(ez->literal());
- while (undef_y.size() > undef_a.size())
- undef_a.push_back(extend_bit);
-
- if (cell->type.in(ID($shl), ID($sshl)))
- undef_a_shifted = ez->vec_shift_left(undef_a, b, false, ez->CONST_FALSE, ez->CONST_FALSE);
-
- if (cell->type == ID($shr))
- undef_a_shifted = ez->vec_shift_right(undef_a, b, false, ez->CONST_FALSE, ez->CONST_FALSE);
-
- if (cell->type == ID($sshr))
- undef_a_shifted = ez->vec_shift_right(undef_a, b, false, cell->parameters[ID::A_SIGNED].as_bool() ? undef_a.back() : ez->CONST_FALSE, ez->CONST_FALSE);
-
- if (cell->type == ID($shift))
- undef_a_shifted = ez->vec_shift_right(undef_a, b, cell->parameters[ID::B_SIGNED].as_bool(), ez->CONST_FALSE, ez->CONST_FALSE);
-
- if (cell->type == ID($shiftx))
- undef_a_shifted = ez->vec_shift_right(undef_a, b, cell->parameters[ID::B_SIGNED].as_bool(), ez->CONST_TRUE, ez->CONST_TRUE);
-
- int undef_any_b = ez->expression(ezSAT::OpOr, undef_b);
- std::vector<int> undef_all_y_bits(undef_y.size(), undef_any_b);
- ez->assume(ez->vec_eq(ez->vec_or(undef_a_shifted, undef_all_y_bits), undef_y));
- undefGating(y, yy, undef_y);
- }
- return true;
- }
-
- if (cell->type == ID($mul))
- {
- std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
- std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
- extendSignalWidth(a, b, y, cell);
-
- std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
-
- std::vector<int> tmp(a.size(), ez->CONST_FALSE);
- for (int i = 0; i < int(a.size()); i++)
- {
- std::vector<int> shifted_a(a.size(), ez->CONST_FALSE);
- for (int j = i; j < int(a.size()); j++)
- shifted_a.at(j) = a.at(j-i);
- tmp = ez->vec_ite(b.at(i), ez->vec_add(tmp, shifted_a), tmp);
- }
- ez->assume(ez->vec_eq(tmp, yy));
-
- if (model_undef) {
- log_assert(arith_undef_handled);
- std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
- undefGating(y, yy, undef_y);
- }
- return true;
- }
-
- if (cell->type == ID($macc))
- {
- std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
- std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
-
- Macc macc;
- macc.from_cell(cell);
-
- std::vector<int> tmp(GetSize(y), ez->CONST_FALSE);
-
- for (auto &port : macc.ports)
- {
- std::vector<int> in_a = importDefSigSpec(port.in_a, timestep);
- std::vector<int> in_b = importDefSigSpec(port.in_b, timestep);
-
- while (GetSize(in_a) < GetSize(y))
- in_a.push_back(port.is_signed && !in_a.empty() ? in_a.back() : ez->CONST_FALSE);
- in_a.resize(GetSize(y));
-
- if (GetSize(in_b))
- {
- while (GetSize(in_b) < GetSize(y))
- in_b.push_back(port.is_signed && !in_b.empty() ? in_b.back() : ez->CONST_FALSE);
- in_b.resize(GetSize(y));
-
- for (int i = 0; i < GetSize(in_b); i++) {
- std::vector<int> shifted_a(in_a.size(), ez->CONST_FALSE);
- for (int j = i; j < int(in_a.size()); j++)
- shifted_a.at(j) = in_a.at(j-i);
- if (port.do_subtract)
- tmp = ez->vec_ite(in_b.at(i), ez->vec_sub(tmp, shifted_a), tmp);
- else
- tmp = ez->vec_ite(in_b.at(i), ez->vec_add(tmp, shifted_a), tmp);
- }
- }
- else
- {
- if (port.do_subtract)
- tmp = ez->vec_sub(tmp, in_a);
- else
- tmp = ez->vec_add(tmp, in_a);
- }
- }
-
- for (int i = 0; i < GetSize(b); i++) {
- std::vector<int> val(GetSize(y), ez->CONST_FALSE);
- val.at(0) = b.at(i);
- tmp = ez->vec_add(tmp, val);
- }
-
- if (model_undef)
- {
- std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
-
- int undef_any_a = ez->expression(ezSAT::OpOr, undef_a);
- int undef_any_b = ez->expression(ezSAT::OpOr, undef_b);
-
- std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
- ez->assume(ez->vec_eq(undef_y, std::vector<int>(GetSize(y), ez->OR(undef_any_a, undef_any_b))));
-
- undefGating(y, tmp, undef_y);
- }
- else
- ez->assume(ez->vec_eq(y, tmp));
-
- return true;
- }
-
- if (cell->type.in(ID($div), ID($mod), ID($divfloor), ID($modfloor)))
- {
- std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
- std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
- extendSignalWidth(a, b, y, cell);
-
- std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
-
- std::vector<int> a_u, b_u;
- if (cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool()) {
- a_u = ez->vec_ite(a.back(), ez->vec_neg(a), a);
- b_u = ez->vec_ite(b.back(), ez->vec_neg(b), b);
- } else {
- a_u = a;
- b_u = b;
- }
-
- std::vector<int> chain_buf = a_u;
- std::vector<int> y_u(a_u.size(), ez->CONST_FALSE);
- for (int i = int(a.size())-1; i >= 0; i--)
- {
- chain_buf.insert(chain_buf.end(), chain_buf.size(), ez->CONST_FALSE);
-
- std::vector<int> b_shl(i, ez->CONST_FALSE);
- b_shl.insert(b_shl.end(), b_u.begin(), b_u.end());
- b_shl.insert(b_shl.end(), chain_buf.size()-b_shl.size(), ez->CONST_FALSE);
-
- y_u.at(i) = ez->vec_ge_unsigned(chain_buf, b_shl);
- chain_buf = ez->vec_ite(y_u.at(i), ez->vec_sub(chain_buf, b_shl), chain_buf);
-
- chain_buf.erase(chain_buf.begin() + a_u.size(), chain_buf.end());
- }
-
- std::vector<int> y_tmp = ignore_div_by_zero ? yy : ez->vec_var(y.size());
-
- // modulo calculation
- std::vector<int> modulo_trunc;
- int floored_eq_trunc;
- if (cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool()) {
- modulo_trunc = ez->vec_ite(a.back(), ez->vec_neg(chain_buf), chain_buf);
- // floor == trunc when sgn(a) == sgn(b) or trunc == 0
- floored_eq_trunc = ez->OR(ez->IFF(a.back(), b.back()), ez->NOT(ez->expression(ezSAT::OpOr, modulo_trunc)));
- } else {
- modulo_trunc = chain_buf;
- floored_eq_trunc = ez->CONST_TRUE;
- }
-
- if (cell->type == ID($div)) {
- if (cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool())
- ez->assume(ez->vec_eq(y_tmp, ez->vec_ite(ez->XOR(a.back(), b.back()), ez->vec_neg(y_u), y_u)));
- else
- ez->assume(ez->vec_eq(y_tmp, y_u));
- } else if (cell->type == ID($mod)) {
- ez->assume(ez->vec_eq(y_tmp, modulo_trunc));
- } else if (cell->type == ID($divfloor)) {
- if (cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool())
- ez->assume(ez->vec_eq(y_tmp, ez->vec_ite(
- ez->XOR(a.back(), b.back()),
- ez->vec_neg(ez->vec_ite(
- ez->vec_reduce_or(modulo_trunc),
- ez->vec_add(y_u, ez->vec_const_unsigned(1, y_u.size())),
- y_u
- )),
- y_u
- )));
- else
- ez->assume(ez->vec_eq(y_tmp, y_u));
- } else if (cell->type == ID($modfloor)) {
- ez->assume(ez->vec_eq(y_tmp, ez->vec_ite(floored_eq_trunc, modulo_trunc, ez->vec_add(modulo_trunc, b))));
- }
-
- if (ignore_div_by_zero) {
- ez->assume(ez->expression(ezSAT::OpOr, b));
- } else {
- std::vector<int> div_zero_result;
- if (cell->type.in(ID($div), ID($divfloor))) {
- if (cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool()) {
- std::vector<int> all_ones(y.size(), ez->CONST_TRUE);
- std::vector<int> only_first_one(y.size(), ez->CONST_FALSE);
- only_first_one.at(0) = ez->CONST_TRUE;
- div_zero_result = ez->vec_ite(a.back(), only_first_one, all_ones);
- } else {
- div_zero_result.insert(div_zero_result.end(), cell->getPort(ID::A).size(), ez->CONST_TRUE);
- div_zero_result.insert(div_zero_result.end(), y.size() - div_zero_result.size(), ez->CONST_FALSE);
- }
- } else if (cell->type.in(ID($mod), ID($modfloor))) {
- // a mod 0 = a
- int copy_a_bits = min(cell->getPort(ID::A).size(), cell->getPort(ID::B).size());
- div_zero_result.insert(div_zero_result.end(), a.begin(), a.begin() + copy_a_bits);
- if (cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool())
- div_zero_result.insert(div_zero_result.end(), y.size() - div_zero_result.size(), div_zero_result.back());
- else
- div_zero_result.insert(div_zero_result.end(), y.size() - div_zero_result.size(), ez->CONST_FALSE);
- }
- ez->assume(ez->vec_eq(yy, ez->vec_ite(ez->expression(ezSAT::OpOr, b), y_tmp, div_zero_result)));
- }
-
- if (model_undef) {
- log_assert(arith_undef_handled);
- std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
- undefGating(y, yy, undef_y);
- }
- return true;
- }
-
- if (cell->type == ID($lut))
- {
- std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
-
- std::vector<int> lut;
- for (auto bit : cell->getParam(ID::LUT).bits)
- lut.push_back(bit == State::S1 ? ez->CONST_TRUE : ez->CONST_FALSE);
- while (GetSize(lut) < (1 << GetSize(a)))
- lut.push_back(ez->CONST_FALSE);
- lut.resize(1 << GetSize(a));
-
- if (model_undef)
- {
- std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> t(lut), u(GetSize(t), ez->CONST_FALSE);
-
- for (int i = GetSize(a)-1; i >= 0; i--)
- {
- std::vector<int> t0(t.begin(), t.begin() + GetSize(t)/2);
- std::vector<int> t1(t.begin() + GetSize(t)/2, t.end());
-
- std::vector<int> u0(u.begin(), u.begin() + GetSize(u)/2);
- std::vector<int> u1(u.begin() + GetSize(u)/2, u.end());
-
- t = ez->vec_ite(a[i], t1, t0);
- u = ez->vec_ite(undef_a[i], ez->vec_or(ez->vec_xor(t0, t1), ez->vec_or(u0, u1)), ez->vec_ite(a[i], u1, u0));
- }
-
- log_assert(GetSize(t) == 1);
- log_assert(GetSize(u) == 1);
- undefGating(y, t, u);
- ez->assume(ez->vec_eq(importUndefSigSpec(cell->getPort(ID::Y), timestep), u));
- }
- else
- {
- std::vector<int> t = lut;
- for (int i = GetSize(a)-1; i >= 0; i--)
- {
- std::vector<int> t0(t.begin(), t.begin() + GetSize(t)/2);
- std::vector<int> t1(t.begin() + GetSize(t)/2, t.end());
- t = ez->vec_ite(a[i], t1, t0);
- }
-
- log_assert(GetSize(t) == 1);
- ez->assume(ez->vec_eq(y, t));
- }
- return true;
- }
-
- if (cell->type == ID($sop))
- {
- std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
- int y = importDefSigSpec(cell->getPort(ID::Y), timestep).at(0);
-
- int width = cell->getParam(ID::WIDTH).as_int();
- int depth = cell->getParam(ID::DEPTH).as_int();
-
- vector<State> table_raw = cell->getParam(ID::TABLE).bits;
- while (GetSize(table_raw) < 2*width*depth)
- table_raw.push_back(State::S0);
-
- vector<vector<int>> table(depth);
-
- for (int i = 0; i < depth; i++)
- for (int j = 0; j < width; j++)
- {
- bool pat0 = (table_raw[2*width*i + 2*j + 0] == State::S1);
- bool pat1 = (table_raw[2*width*i + 2*j + 1] == State::S1);
-
- if (pat0 && !pat1)
- table.at(i).push_back(0);
- else if (!pat0 && pat1)
- table.at(i).push_back(1);
- else
- table.at(i).push_back(-1);
- }
-
- if (model_undef)
- {
- std::vector<int> products, undef_products;
- std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
- int undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep).at(0);
-
- for (int i = 0; i < depth; i++)
- {
- std::vector<int> cmp_a, cmp_ua, cmp_b;
-
- for (int j = 0; j < width; j++)
- if (table.at(i).at(j) >= 0) {
- cmp_a.push_back(a.at(j));
- cmp_ua.push_back(undef_a.at(j));
- cmp_b.push_back(table.at(i).at(j) ? ez->CONST_TRUE : ez->CONST_FALSE);
- }
-
- std::vector<int> masked_a = ez->vec_or(cmp_a, cmp_ua);
- std::vector<int> masked_b = ez->vec_or(cmp_b, cmp_ua);
-
- int masked_eq = ez->vec_eq(masked_a, masked_b);
- int any_undef = ez->expression(ezSAT::OpOr, cmp_ua);
-
- undef_products.push_back(ez->AND(any_undef, masked_eq));
- products.push_back(ez->AND(ez->NOT(any_undef), masked_eq));
- }
-
- int yy = ez->expression(ezSAT::OpOr, products);
- ez->SET(undef_y, ez->AND(ez->NOT(yy), ez->expression(ezSAT::OpOr, undef_products)));
- undefGating(y, yy, undef_y);
- }
- else
- {
- std::vector<int> products;
-
- for (int i = 0; i < depth; i++)
- {
- std::vector<int> cmp_a, cmp_b;
-
- for (int j = 0; j < width; j++)
- if (table.at(i).at(j) >= 0) {
- cmp_a.push_back(a.at(j));
- cmp_b.push_back(table.at(i).at(j) ? ez->CONST_TRUE : ez->CONST_FALSE);
- }
-
- products.push_back(ez->vec_eq(cmp_a, cmp_b));
- }
-
- ez->SET(y, ez->expression(ezSAT::OpOr, products));
- }
-
- return true;
- }
-
- if (cell->type == ID($fa))
- {
- std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
- std::vector<int> c = importDefSigSpec(cell->getPort(ID::C), timestep);
- std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
- std::vector<int> x = importDefSigSpec(cell->getPort(ID::X), timestep);
-
- std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
- std::vector<int> xx = model_undef ? ez->vec_var(x.size()) : x;
-
- std::vector<int> t1 = ez->vec_xor(a, b);
- ez->assume(ez->vec_eq(yy, ez->vec_xor(t1, c)));
-
- std::vector<int> t2 = ez->vec_and(a, b);
- std::vector<int> t3 = ez->vec_and(c, t1);
- ez->assume(ez->vec_eq(xx, ez->vec_or(t2, t3)));
-
- if (model_undef)
- {
- std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
- std::vector<int> undef_c = importUndefSigSpec(cell->getPort(ID::C), timestep);
-
- std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
- std::vector<int> undef_x = importUndefSigSpec(cell->getPort(ID::X), timestep);
-
- ez->assume(ez->vec_eq(undef_y, ez->vec_or(ez->vec_or(undef_a, undef_b), undef_c)));
- ez->assume(ez->vec_eq(undef_x, undef_y));
-
- undefGating(y, yy, undef_y);
- undefGating(x, xx, undef_x);
- }
- return true;
- }
-
- if (cell->type == ID($lcu))
- {
- std::vector<int> p = importDefSigSpec(cell->getPort(ID::P), timestep);
- std::vector<int> g = importDefSigSpec(cell->getPort(ID::G), timestep);
- std::vector<int> ci = importDefSigSpec(cell->getPort(ID::CI), timestep);
- std::vector<int> co = importDefSigSpec(cell->getPort(ID::CO), timestep);
-
- std::vector<int> yy = model_undef ? ez->vec_var(co.size()) : co;
-
- for (int i = 0; i < GetSize(co); i++)
- ez->SET(yy[i], ez->OR(g[i], ez->AND(p[i], i ? yy[i-1] : ci[0])));
-
- if (model_undef)
- {
- std::vector<int> undef_p = importUndefSigSpec(cell->getPort(ID::P), timestep);
- std::vector<int> undef_g = importUndefSigSpec(cell->getPort(ID::G), timestep);
- std::vector<int> undef_ci = importUndefSigSpec(cell->getPort(ID::CI), timestep);
- std::vector<int> undef_co = importUndefSigSpec(cell->getPort(ID::CO), timestep);
-
- int undef_any_p = ez->expression(ezSAT::OpOr, undef_p);
- int undef_any_g = ez->expression(ezSAT::OpOr, undef_g);
- int undef_any_ci = ez->expression(ezSAT::OpOr, undef_ci);
- int undef_co_bit = ez->OR(undef_any_p, undef_any_g, undef_any_ci);
-
- std::vector<int> undef_co_bits(undef_co.size(), undef_co_bit);
- ez->assume(ez->vec_eq(undef_co_bits, undef_co));
-
- undefGating(co, yy, undef_co);
- }
- return true;
- }
-
- if (cell->type == ID($alu))
- {
- std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
- std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
- std::vector<int> x = importDefSigSpec(cell->getPort(ID::X), timestep);
- std::vector<int> ci = importDefSigSpec(cell->getPort(ID::CI), timestep);
- std::vector<int> bi = importDefSigSpec(cell->getPort(ID::BI), timestep);
- std::vector<int> co = importDefSigSpec(cell->getPort(ID::CO), timestep);
-
- extendSignalWidth(a, b, y, cell);
- extendSignalWidth(a, b, x, cell);
- extendSignalWidth(a, b, co, cell);
-
- std::vector<int> def_y = model_undef ? ez->vec_var(y.size()) : y;
- std::vector<int> def_x = model_undef ? ez->vec_var(x.size()) : x;
- std::vector<int> def_co = model_undef ? ez->vec_var(co.size()) : co;
-
- log_assert(GetSize(y) == GetSize(x));
- log_assert(GetSize(y) == GetSize(co));
- log_assert(GetSize(ci) == 1);
- log_assert(GetSize(bi) == 1);
-
- for (int i = 0; i < GetSize(y); i++)
- {
- int s1 = a.at(i), s2 = ez->XOR(b.at(i), bi.at(0)), s3 = i ? co.at(i-1) : ci.at(0);
- ez->SET(def_x.at(i), ez->XOR(s1, s2));
- ez->SET(def_y.at(i), ez->XOR(def_x.at(i), s3));
- ez->SET(def_co.at(i), ez->OR(ez->AND(s1, s2), ez->AND(s1, s3), ez->AND(s2, s3)));
- }
-
- if (model_undef)
- {
- std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep);
- std::vector<int> undef_ci = importUndefSigSpec(cell->getPort(ID::CI), timestep);
- std::vector<int> undef_bi = importUndefSigSpec(cell->getPort(ID::BI), timestep);
-
- std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
- std::vector<int> undef_x = importUndefSigSpec(cell->getPort(ID::X), timestep);
- std::vector<int> undef_co = importUndefSigSpec(cell->getPort(ID::CO), timestep);
-
- extendSignalWidth(undef_a, undef_b, undef_y, cell);
- extendSignalWidth(undef_a, undef_b, undef_x, cell);
- extendSignalWidth(undef_a, undef_b, undef_co, cell);
-
- std::vector<int> all_inputs_undef;
- all_inputs_undef.insert(all_inputs_undef.end(), undef_a.begin(), undef_a.end());
- all_inputs_undef.insert(all_inputs_undef.end(), undef_b.begin(), undef_b.end());
- all_inputs_undef.insert(all_inputs_undef.end(), undef_ci.begin(), undef_ci.end());
- all_inputs_undef.insert(all_inputs_undef.end(), undef_bi.begin(), undef_bi.end());
- int undef_any = ez->expression(ezSAT::OpOr, all_inputs_undef);
-
- for (int i = 0; i < GetSize(undef_y); i++) {
- ez->SET(undef_y.at(i), undef_any);
- ez->SET(undef_x.at(i), ez->OR(undef_a.at(i), undef_b.at(i), undef_bi.at(0)));
- ez->SET(undef_co.at(i), undef_any);
- }
-
- undefGating(y, def_y, undef_y);
- undefGating(x, def_x, undef_x);
- undefGating(co, def_co, undef_co);
- }
- return true;
- }
-
- if (cell->type == ID($slice))
- {
- RTLIL::SigSpec a = cell->getPort(ID::A);
- RTLIL::SigSpec y = cell->getPort(ID::Y);
- ez->assume(signals_eq(a.extract(cell->parameters.at(ID::OFFSET).as_int(), y.size()), y, timestep));
- return true;
- }
-
- if (cell->type == ID($concat))
- {
- RTLIL::SigSpec a = cell->getPort(ID::A);
- RTLIL::SigSpec b = cell->getPort(ID::B);
- RTLIL::SigSpec y = cell->getPort(ID::Y);
-
- RTLIL::SigSpec ab = a;
- ab.append(b);
-
- ez->assume(signals_eq(ab, y, timestep));
- return true;
- }
-
- if (timestep > 0 && cell->type.in(ID($ff), ID($dff), ID($_FF_), ID($_DFF_N_), ID($_DFF_P_)))
- {
- if (timestep == 1)
- {
- initial_state.add((*sigmap)(cell->getPort(ID::Q)));
- }
- else
- {
- std::vector<int> d = importDefSigSpec(cell->getPort(ID::D), timestep-1);
- std::vector<int> q = importDefSigSpec(cell->getPort(ID::Q), timestep);
-
- std::vector<int> qq = model_undef ? ez->vec_var(q.size()) : q;
- ez->assume(ez->vec_eq(d, qq));
-
- if (model_undef)
- {
- std::vector<int> undef_d = importUndefSigSpec(cell->getPort(ID::D), timestep-1);
- std::vector<int> undef_q = importUndefSigSpec(cell->getPort(ID::Q), timestep);
-
- ez->assume(ez->vec_eq(undef_d, undef_q));
- undefGating(q, qq, undef_q);
- }
- }
- return true;
- }
-
- if (cell->type == ID($anyconst))
- {
- if (timestep < 2)
- return true;
-
- std::vector<int> d = importDefSigSpec(cell->getPort(ID::Y), timestep-1);
- std::vector<int> q = importDefSigSpec(cell->getPort(ID::Y), timestep);
-
- std::vector<int> qq = model_undef ? ez->vec_var(q.size()) : q;
- ez->assume(ez->vec_eq(d, qq));
-
- if (model_undef)
- {
- std::vector<int> undef_d = importUndefSigSpec(cell->getPort(ID::Y), timestep-1);
- std::vector<int> undef_q = importUndefSigSpec(cell->getPort(ID::Y), timestep);
-
- ez->assume(ez->vec_eq(undef_d, undef_q));
- undefGating(q, qq, undef_q);
- }
- return true;
- }
-
- if (cell->type == ID($anyseq))
- {
- return true;
- }
-
- if (cell->type.in(ID($_BUF_), ID($equiv)))
- {
- std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
- extendSignalWidthUnary(a, y, cell);
-
- std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
- ez->assume(ez->vec_eq(a, yy));
-
- if (model_undef) {
- std::vector<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
- std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
- extendSignalWidthUnary(undef_a, undef_y, cell, false);
- ez->assume(ez->vec_eq(undef_a, undef_y));
- undefGating(y, yy, undef_y);
- }
- return true;
- }
-
- if (cell->type == ID($initstate))
- {
- auto key = make_pair(prefix, timestep);
- if (initstates.count(key) == 0)
- initstates[key] = false;
-
- std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
- log_assert(GetSize(y) == 1);
- ez->SET(y[0], initstates[key] ? ez->CONST_TRUE : ez->CONST_FALSE);
-
- if (model_undef) {
- std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
- log_assert(GetSize(undef_y) == 1);
- ez->SET(undef_y[0], ez->CONST_FALSE);
- }
-
- return true;
- }
-
- if (cell->type == ID($assert))
- {
- std::string pf = prefix + (timestep == -1 ? "" : stringf("@%d:", timestep));
- asserts_a[pf].append((*sigmap)(cell->getPort(ID::A)));
- asserts_en[pf].append((*sigmap)(cell->getPort(ID::EN)));
- return true;
- }
-
- if (cell->type == ID($assume))
- {
- std::string pf = prefix + (timestep == -1 ? "" : stringf("@%d:", timestep));
- assumes_a[pf].append((*sigmap)(cell->getPort(ID::A)));
- assumes_en[pf].append((*sigmap)(cell->getPort(ID::EN)));
- return true;
- }
-
- // Unsupported internal cell types: $pow $lut
- // .. and all sequential cells except $dff and $_DFF_[NP]_
- return false;
- }
+ bool importCell(RTLIL::Cell *cell, int timestep = -1);
};
YOSYS_NAMESPACE_END
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 d818e580b..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;
@@ -88,10 +88,10 @@ struct TimingInfo
auto src = cell->getPort(ID::SRC);
auto dst = cell->getPort(ID::DST);
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_output)
+ if (!c.wire || !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));
int rise_max = cell->getParam(ID::T_RISE_MAX).as_int();
int fall_max = cell->getParam(ID::T_FALL_MAX).as_int();
@@ -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 7e9f320e0..102f9e737 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>
@@ -89,6 +90,12 @@ bool memhasher_active = false;
uint32_t memhasher_rng = 123456;
std::vector<void*> memhasher_store;
+std::string yosys_share_dirname;
+std::string yosys_abc_executable;
+
+void init_share_dirname();
+void init_abc_executable_name();
+
void memhasher_on()
{
#if defined(__linux__) || defined(__FreeBSD__)
@@ -131,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");
@@ -523,6 +530,8 @@ void yosys_setup()
if(already_setup)
return;
already_setup = true;
+ init_share_dirname();
+ init_abc_executable_name();
#define X(_id) RTLIL::ID::_id = "\\" # _id;
#include "kernel/constids.inc"
@@ -532,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();
@@ -789,7 +799,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()
@@ -825,38 +837,74 @@ std::string proc_self_dirname()
#endif
#if defined(EMSCRIPTEN) || defined(__wasm)
-std::string proc_share_dirname()
+void init_share_dirname()
{
- return "/share/";
+ yosys_share_dirname = "/share/";
}
#else
-std::string proc_share_dirname()
+void init_share_dirname()
{
std::string proc_self_path = proc_self_dirname();
# if defined(_WIN32) && !defined(YOSYS_WIN32_UNIX_DIR)
std::string proc_share_path = proc_self_path + "share\\";
- if (check_file_exists(proc_share_path, true))
- return proc_share_path;
+ if (check_file_exists(proc_share_path, true)) {
+ yosys_share_dirname = proc_share_path;
+ return;
+ }
proc_share_path = proc_self_path + "..\\share\\";
- if (check_file_exists(proc_share_path, true))
- return proc_share_path;
+ if (check_file_exists(proc_share_path, true)) {
+ yosys_share_dirname = proc_share_path;
+ return;
+ }
# else
std::string proc_share_path = proc_self_path + "share/";
- if (check_file_exists(proc_share_path, true))
- return proc_share_path;
+ if (check_file_exists(proc_share_path, true)) {
+ yosys_share_dirname = proc_share_path;
+ return;
+ }
proc_share_path = proc_self_path + "../share/" + proc_program_prefix()+ "yosys/";
- if (check_file_exists(proc_share_path, true))
- return proc_share_path;
+ if (check_file_exists(proc_share_path, true)) {
+ yosys_share_dirname = proc_share_path;
+ return;
+ }
# ifdef YOSYS_DATDIR
proc_share_path = YOSYS_DATDIR "/";
- if (check_file_exists(proc_share_path, true))
- return proc_share_path;
+ if (check_file_exists(proc_share_path, true)) {
+ yosys_share_dirname = proc_share_path;
+ return;
+ }
# endif
# endif
- log_error("proc_share_dirname: unable to determine share/ directory!\n");
}
#endif
+void init_abc_executable_name()
+{
+#ifdef ABCEXTERNAL
+ std::string exe_file;
+ if (std::getenv("ABC")) {
+ yosys_abc_executable = std::getenv("ABC");
+ } else {
+ yosys_abc_executable = ABCEXTERNAL;
+ }
+#else
+ yosys_abc_executable = proc_self_dirname() + proc_program_prefix()+ "yosys-abc";
+#endif
+#ifdef _WIN32
+#ifndef ABCEXTERNAL
+ if (!check_file_exists(yosys_abc_executable + ".exe") && check_file_exists(proc_self_dirname() + "..\\" + proc_program_prefix() + "yosys-abc.exe"))
+ yosys_abc_executable = proc_self_dirname() + "..\\" + proc_program_prefix() + "yosys-abc";
+#endif
+#endif
+}
+
+std::string proc_share_dirname()
+{
+ if (yosys_share_dirname.empty())
+ log_error("init_share_dirname: unable to determine share/ directory!\n");
+ return yosys_share_dirname;
+}
+
std::string proc_program_prefix()
{
std::string program_prefix;
@@ -908,7 +956,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;
@@ -918,11 +966,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)
@@ -930,7 +978,7 @@ void run_frontend(std::string filename, std::string command, std::string *backen
else if (filename_trim.size() > 4 && filename_trim.compare(filename_trim.size()-5, std::string::npos, ".json") == 0)
command = "json";
else if (filename_trim.size() > 3 && filename_trim.compare(filename_trim.size()-3, std::string::npos, ".il") == 0)
- command = "ilang";
+ command = "rtlil";
else if (filename_trim.size() > 3 && filename_trim.compare(filename_trim.size()-3, std::string::npos, ".ys") == 0)
command = "script";
else if (filename_trim.size() > 3 && filename_trim.compare(filename_trim.size()-4, std::string::npos, ".tcl") == 0)
@@ -1008,10 +1056,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 == "-") {
@@ -1020,16 +1070,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)
@@ -1050,8 +1099,10 @@ void run_backend(std::string filename, std::string command, RTLIL::Design *desig
if (command == "auto") {
if (filename.size() > 2 && filename.compare(filename.size()-2, std::string::npos, ".v") == 0)
command = "verilog";
+ else if (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".sv") == 0)
+ command = "verilog -sv";
else if (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".il") == 0)
- command = "ilang";
+ command = "rtlil";
else if (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".cc") == 0)
command = "cxxrtl";
else if (filename.size() > 4 && filename.compare(filename.size()-4, std::string::npos, ".aig") == 0)
@@ -1063,7 +1114,7 @@ void run_backend(std::string filename, std::string command, RTLIL::Design *desig
else if (filename.size() > 5 && filename.compare(filename.size()-5, std::string::npos, ".json") == 0)
command = "json";
else if (filename == "-")
- command = "ilang";
+ command = "rtlil";
else if (filename.empty())
return;
else
@@ -1341,7 +1392,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 f1646d6bc..091e2282f 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
@@ -93,6 +93,8 @@ extern Tcl_Obj *Tcl_NewIntObj(int intValue);
extern Tcl_Obj *Tcl_NewListObj(int objc, Tcl_Obj *const objv[]);
extern Tcl_Obj *Tcl_ObjSetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, int flags);
# endif
+# undef CONST
+# undef INLINE
#endif
#ifdef _WIN32
@@ -119,8 +121,9 @@ extern Tcl_Obj *Tcl_ObjSetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *p
# define fileno _fileno
# endif
-// mingw and msvc include `wingdi.h` which defines a TRANSPARENT macro
-// that conflicts with X(TRANSPARENT) entry in kernel/constids.inc
+// The following defines conflict with our identifiers:
+# undef CONST
+// `wingdi.h` defines a TRANSPARENT macro that conflicts with X(TRANSPARENT) entry in kernel/constids.inc
# undef TRANSPARENT
#endif
@@ -144,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
@@ -219,6 +220,7 @@ namespace RTLIL {
struct Wire;
struct Cell;
struct Memory;
+ struct Process;
struct Module;
struct Design;
struct Monitor;
@@ -242,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 {};
@@ -250,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 {};
@@ -343,8 +347,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);
@@ -366,6 +369,9 @@ extern std::map<std::string, void*> loaded_python_plugins;
extern std::map<std::string, std::string> loaded_plugin_aliases;
void load_plugin(std::string filename, std::vector<std::string> aliases);
+extern std::string yosys_share_dirname;
+extern std::string yosys_abc_executable;
+
YOSYS_NAMESPACE_END
#endif
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 25adcda86..3c9fb31cc 100644
--- a/manual/CHAPTER_CellLib.tex
+++ b/manual/CHAPTER_CellLib.tex
@@ -221,6 +221,26 @@ calculated signal and a constant zero with an {\tt \$and} gate).
\subsection{Registers}
+SR-type latches are represented by {\tt \$sr} cells. These cells have input ports
+\B{SET} and \B{CLR} and an output port \B{Q}. They have the following parameters:
+
+\begin{itemize}
+\item \B{WIDTH} \\
+The width of inputs \B{SET} and \B{CLR} and output \B{Q}.
+
+\item \B{SET\_POLARITY} \\
+The set input bits are active-high if this parameter has the value {\tt 1'b1} and active-low
+if this parameter is {\tt 1'b0}.
+
+\item \B{CLR\_POLARITY} \\
+The reset input bits are active-high if this parameter has the value {\tt 1'b1} and active-low
+if this parameter is {\tt 1'b0}.
+\end{itemize}
+
+Both set and reset inputs have separate bits for every output bit.
+When both the set and reset inputs of an {\tt \$sr} cell are active for a given bit
+index, the reset input takes precedence.
+
D-type flip-flops are represented by {\tt \$dff} cells. These cells have a clock port \B{CLK},
an input port \B{D} and an output port \B{Q}. The following parameters are available for {\tt \$dff}
cells:
@@ -267,26 +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 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
-a single-bit \B{SET} input port for the set pin, a single-bit \B{CLR} input port for the reset pin,
-and the following two parameters:
+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{SET\_POLARITY} \\
-The set input is active-high if this parameter has the value {\tt 1'b1} and active-low
-if this parameter is {\tt 1'b0}.
-
-\item \B{CLR\_POLARITY} \\
-The reset input is active-high if this parameter has the value {\tt 1'b1} and active-low
+\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}
-When both the set and reset inputs of a {\tt \$dffsr} cell are active, the reset input takes
-precedence.
+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:
@@ -297,27 +315,53 @@ The enable input is active-high if this parameter has the value {\tt 1'b1} and a
if this parameter is {\tt 1'b0}.
\end{itemize}
-\begin{fixme}
-Add information about {\tt \$sr} cells (set-reset flip-flops), {\tt \$dlatch} cells (d-type latches),
-{\tt \$adlatch} and {\tt \$dlatchsr} cells (d-type latches with set/reset).
-\end{fixme}
+D-type latches are represented by {\tt \$dlatch} cells. These cells have an enable port \B{EN},
+an input port \B{D}, and an output port \B{Q}. The following parameters are available for {\tt \$dlatch} cells:
+
+\begin{itemize}
+\item \B{WIDTH} \\
+The width of input \B{D} and output \B{Q}.
+
+\item \B{EN\_POLARITY} \\
+The enable input is active-high if this parameter has the value {\tt 1'b1} and active-low
+if this parameter is {\tt 1'b0}.
+\end{itemize}
+
+The latch is transparent when the \B{EN} input is active.
+
+D-type latches with reset are represented by {\tt \$adlatch} cells. In addition to {\tt \$dlatch}
+ports and parameters, they also have a single-bit \B{ARST} input port for the reset pin and the following additional parameters:
+
+\begin{itemize}
+\item \B{ARST\_POLARITY} \\
+The asynchronous reset is active-high if this parameter has the value {\tt 1'b1} and active-low
+if this parameter is {\tt 1'b0}.
+
+\item \B{ARST\_VALUE} \\
+The state of \B{Q} will be set to this value when the reset is active.
+\end{itemize}
+
+D-type latches with set and reset are represented by {\tt \$dlatchsr} cells.
+In addition to {\tt \$dlatch} ports and parameters, they also have multi-bit
+\B{SET} and \B{CLR} input ports and the corresponding polarity parameters, like
+{\tt \$sr} cells.
\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} \\
@@ -327,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
@@ -337,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:
@@ -354,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
@@ -364,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}
@@ -390,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.
@@ -417,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} \\
@@ -451,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.
@@ -464,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}
@@ -476,6 +593,23 @@ The {\tt memory\_map} pass can be used to implement {\tt \$mem} cells as basic l
Add a brief description of the {\tt \$fsm} cell type.
\end{fixme}
+\subsection{Specify rules}
+
+\begin{fixme}
+Add information about {\tt \$specify2}, {\tt \$specify3}, and {\tt \$specrule} cells.
+\end{fixme}
+
+\subsection{Formal verification cells}
+
+\begin{fixme}
+Add information about {\tt \$assert}, {\tt \$assume}, {\tt \$live}, {\tt \$fair}, {\tt \$cover}, {\tt \$equiv},
+{\tt \$initstate}, {\tt \$anyconst}, {\tt \$anyseq}, {\tt \$allconst}, {\tt \$allseq} cells.
+\end{fixme}
+
+\begin{fixme}
+Add information about {\tt \$ff} and {\tt \$\_FF\_} cells.
+\end{fixme}
+
\section{Gates}
\label{sec:celllib_gates}
@@ -490,6 +624,7 @@ source tree.
\begin{tabular}[t]{ll}
Verilog & Cell Type \\
\hline
+\lstinline[language=Verilog]; Y = A; & {\tt \$\_BUF\_} \\
\lstinline[language=Verilog]; Y = ~A; & {\tt \$\_NOT\_} \\
\lstinline[language=Verilog]; Y = A & B; & {\tt \$\_AND\_} \\
\lstinline[language=Verilog]; Y = ~(A & B); & {\tt \$\_NAND\_} \\
@@ -499,11 +634,21 @@ Verilog & Cell Type \\
\lstinline[language=Verilog]; Y = A | ~B; & {\tt \$\_ORNOT\_} \\
\lstinline[language=Verilog]; Y = A ^ B; & {\tt \$\_XOR\_} \\
\lstinline[language=Verilog]; Y = ~(A ^ B); & {\tt \$\_XNOR\_} \\
+\lstinline[language=Verilog]; Y = ~((A & B) | C); & {\tt \$\_AOI3\_} \\
+\lstinline[language=Verilog]; Y = ~((A | B) & C); & {\tt \$\_OAI3\_} \\
+\lstinline[language=Verilog]; Y = ~((A & B) | (C & D)); & {\tt \$\_AOI4\_} \\
+\lstinline[language=Verilog]; Y = ~((A | B) & (C | D)); & {\tt \$\_OAI4\_} \\
\lstinline[language=Verilog]; Y = S ? B : A; & {\tt \$\_MUX\_} \\
-\lstinline[language=Verilog]; Y = EN ? A : 'bz; & {\tt \$\_TBUF\_} \\
+\lstinline[language=Verilog]; Y = ~(S ? B : A); & {\tt \$\_NMUX\_} \\
+(see below) & {\tt \$\_MUX4\_} \\
+(see below) & {\tt \$\_MUX8\_} \\
+(see below) & {\tt \$\_MUX16\_} \\
+\lstinline[language=Verilog]; Y = EN ? A : 1'bz; & {\tt \$\_TBUF\_} \\
\hline
\lstinline[language=Verilog]; always @(negedge C) Q <= D; & {\tt \$\_DFF\_N\_} \\
\lstinline[language=Verilog]; always @(posedge C) Q <= D; & {\tt \$\_DFF\_P\_} \\
+\lstinline[language=Verilog]; always @* if (!E) Q <= D; & {\tt \$\_DLATCH\_N\_} \\
+\lstinline[language=Verilog]; always @* if (E) Q <= D; & {\tt \$\_DLATCH\_P\_} \\
\end{tabular}
\caption{Cell types for gate level logic networks (main list)}
\label{tab:CellLib_gates}
@@ -610,14 +755,88 @@ $ClkEdge$ & $SetLvl$ & $RstLvl$ & $EnLvl$ & Cell Type \\
\label{tab:CellLib_gates_dffsre}
\end{table}
-Tables~\ref{tab:CellLib_gates}, \ref{tab:CellLib_gates_dffe}, \ref{tab:CellLib_gates_adff}, \ref{tab:CellLib_gates_adffe}, \ref{tab:CellLib_gates_dffsr} and \ref{tab:CellLib_gates_dffsre} list all cell types used for gate level logic. The cell types
-{\tt \$\_NOT\_}, {\tt \$\_AND\_}, {\tt \$\_NAND\_}, {\tt \$\_ANDNOT\_}, {\tt \$\_OR\_}, {\tt \$\_NOR\_},
-{\tt \$\_ORNOT\_}, {\tt \$\_XOR\_}, {\tt \$\_XNOR\_} and {\tt \$\_MUX\_} are used to model combinatorial logic.
+\begin{table}[t]
+\hfil
+\begin{tabular}[t]{llll}
+$EnLvl$ & $RstLvl$ & $RstVal$ & Cell Type \\
+\hline
+\lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & {\tt \$\_DLATCH\_NN0\_} \\
+\lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & {\tt \$\_DLATCH\_NN1\_} \\
+\lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & {\tt \$\_DLATCH\_NP0\_} \\
+\lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & {\tt \$\_DLATCH\_NP1\_} \\
+\lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & {\tt \$\_DLATCH\_PN0\_} \\
+\lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & {\tt \$\_DLATCH\_PN1\_} \\
+\lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & {\tt \$\_DLATCH\_PP0\_} \\
+\lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & {\tt \$\_DLATCH\_PP1\_} \\
+\end{tabular}
+\caption{Cell types for gate level logic networks (latches with reset)}
+\label{tab:CellLib_gates_adlatch}
+\end{table}
+
+\begin{table}[t]
+\hfil
+\begin{tabular}[t]{llll}
+$EnLvl$ & $SetLvl$ & $RstLvl$ & Cell Type \\
+\hline
+\lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & {\tt \$\_DLATCHSR\_NNN\_} \\
+\lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & {\tt \$\_DLATCHSR\_NNP\_} \\
+\lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & {\tt \$\_DLATCHSR\_NPN\_} \\
+\lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & {\tt \$\_DLATCHSR\_NPP\_} \\
+\lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & {\tt \$\_DLATCHSR\_PNN\_} \\
+\lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & {\tt \$\_DLATCHSR\_PNP\_} \\
+\lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & {\tt \$\_DLATCHSR\_PPN\_} \\
+\lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & {\tt \$\_DLATCHSR\_PPP\_} \\
+\end{tabular}
+\caption{Cell types for gate level logic networks (latches with set and reset)}
+\label{tab:CellLib_gates_dlatchsr}
+\end{table}
+
+\begin{table}[t]
+\hfil
+\begin{tabular}[t]{llll}
+$SetLvl$ & $RstLvl$ & Cell Type \\
+\hline
+\lstinline[language=Verilog];0; & \lstinline[language=Verilog];0; & {\tt \$\_SR\_NN\_} \\
+\lstinline[language=Verilog];0; & \lstinline[language=Verilog];1; & {\tt \$\_SR\_NP\_} \\
+\lstinline[language=Verilog];1; & \lstinline[language=Verilog];0; & {\tt \$\_SR\_PN\_} \\
+\lstinline[language=Verilog];1; & \lstinline[language=Verilog];1; & {\tt \$\_SR\_PP\_} \\
+\end{tabular}
+\caption{Cell types for gate level logic networks (SR latches)}
+\label{tab:CellLib_gates_sr}
+\end{table}
+
+Tables~\ref{tab:CellLib_gates}, \ref{tab:CellLib_gates_dffe}, \ref{tab:CellLib_gates_adff}, \ref{tab:CellLib_gates_adffe}, \ref{tab:CellLib_gates_dffsr}, \ref{tab:CellLib_gates_dffsre}, \ref{tab:CellLib_gates_adlatch}, \ref{tab:CellLib_gates_dlatchsr} and \ref{tab:CellLib_gates_sr} list all cell types used for gate level logic. The cell types
+{\tt \$\_BUF\_}, {\tt \$\_NOT\_}, {\tt \$\_AND\_}, {\tt \$\_NAND\_}, {\tt \$\_ANDNOT\_},
+{\tt \$\_OR\_}, {\tt \$\_NOR\_}, {\tt \$\_ORNOT\_}, {\tt \$\_XOR\_}, {\tt \$\_XNOR\_},
+{\tt \$\_AOI3\_}, {\tt \$\_OAI3\_}, {\tt \$\_AOI4\_}, {\tt \$\_OAI4\_},
+{\tt \$\_MUX\_}, {\tt \$\_MUX4\_}, {\tt \$\_MUX8\_}, {\tt \$\_MUX16\_} and {\tt \$\_NMUX\_} are used to model combinatorial logic.
The cell type {\tt \$\_TBUF\_} is used to model tristate logic.
+The {\tt \$\_MUX4\_}, {\tt \$\_MUX8\_} and {\tt \$\_MUX16\_} cells are used to model wide muxes, and correspond to the following Verilog code:
+
+\begin{lstlisting}[language=Verilog]
+// $_MUX4_
+assign Y = T ? (S ? D : C) :
+ (S ? B : A);
+// $_MUX8_
+assign Y = U ? T ? (S ? H : G) :
+ (S ? F : E) :
+ T ? (S ? D : C) :
+ (S ? B : A);
+// $_MUX16_
+assign Y = V ? U ? T ? (S ? P : O) :
+ (S ? N : M) :
+ T ? (S ? L : K) :
+ (S ? J : I) :
+ U ? T ? (S ? H : G) :
+ (S ? F : E) :
+ T ? (S ? D : C) :
+ (S ? B : A);
+\end{lstlisting}
+
The cell types {\tt \$\_DFF\_N\_} and {\tt \$\_DFF\_P\_} represent d-type flip-flops.
-The cell types {\tt \$\_DFFE\_NN\_}, {\tt \$\_DFFE\_NP\_}, {\tt \$\_DFFE\_PN\_} and {\tt \$\_DFFE\_PP\_}
+The cell types {\tt \$\_DFFE\_[NP][NP]\_}
implement d-type flip-flops with enable. The values in the table for these cell types relate to the
following Verilog code template.
@@ -627,8 +846,7 @@ following Verilog code template.
Q <= D;
\end{lstlisting}
-The cell types {\tt \$\_DFF\_NN0\_}, {\tt \$\_DFF\_NN1\_}, {\tt \$\_DFF\_NP0\_}, {\tt \$\_DFF\_NP1\_},
-{\tt \$\_DFF\_PN0\_}, {\tt \$\_DFF\_PN1\_}, {\tt \$\_DFF\_PP0\_} and {\tt \$\_DFF\_PP1\_} implement
+The cell types {\tt \$\_DFF\_[NP][NP][01]\_} implement
d-type flip-flops with asynchronous reset. The values in the table for these cell types relate to the
following Verilog code template, where \lstinline[mathescape,language=Verilog];$RstEdge$; is \lstinline[language=Verilog];posedge;
if \lstinline[mathescape,language=Verilog];$RstLvl$; if \lstinline[language=Verilog];1;, and \lstinline[language=Verilog];negedge;
@@ -642,8 +860,7 @@ otherwise.
Q <= D;
\end{lstlisting}
-The cell types {\tt \$\_SDFF\_NN0\_}, {\tt \$\_SDFF\_NN1\_}, {\tt \$\_SDFF\_NP0\_}, {\tt \$\_SDFF\_NP1\_},
-{\tt \$\_SDFF\_PN0\_}, {\tt \$\_SDFF\_PN1\_}, {\tt \$\_SDFF\_PP0\_} and {\tt \$\_SDFF\_PP1\_} implement
+The cell types {\tt \$\_SDFF\_[NP][NP][01]\_} implement
d-type flip-flops with synchronous reset. The values in the table for these cell types relate to the
following Verilog code template:
@@ -732,21 +949,52 @@ otherwise.
Q <= D;
\end{lstlisting}
+The cell types {\tt \$\_DLATCH\_N\_} and {\tt \$\_DLATCH\_P\_} represent d-type latches.
+
+The cell types {\tt \$\_DLATCH\_[NP][NP][01]\_} implement
+d-type latches with reset. The values in the table for these cell types relate to the
+following Verilog code template:
+
+\begin{lstlisting}[mathescape,language=Verilog]
+ always @*
+ if (R == $RstLvl$)
+ Q <= $RstVal$;
+ else if (E == $EnLvl$)
+ Q <= D;
+\end{lstlisting}
+
+The cell types {\tt \$\_DLATCHSR\_[NP][NP][NP]\_} implement
+d-type latches with set and reset. The values in the table for these cell types relate to the
+following Verilog code template:
+
+\begin{lstlisting}[mathescape,language=Verilog]
+ always @*
+ if (R == $RstLvl$)
+ Q <= 0;
+ else if (S == $SetLvl$)
+ Q <= 1;
+ else if (E == $EnLvl$)
+ Q <= D;
+\end{lstlisting}
+
+The cell types {\tt \$\_SR\_[NP][NP]\_} implement
+sr-type latches. The values in the table for these cell types relate to the
+following Verilog code template:
+
+\begin{lstlisting}[mathescape,language=Verilog]
+ always @*
+ if (R == $RstLvl$)
+ Q <= 0;
+ else if (S == $SetLvl$)
+ Q <= 1;
+\end{lstlisting}
+
In most cases gate level logic networks are created from RTL networks using the {\tt techmap} pass. The flip-flop cells
from the gate level logic network can be mapped to physical flip-flop cells from a Liberty file using the {\tt dfflibmap}
pass. The combinatorial logic cells can be mapped to physical cells from a Liberty file via ABC \citeweblink{ABC}
using the {\tt abc} pass.
\begin{fixme}
-Add information about {\tt \$assert}, {\tt \$assume}, {\tt \$live}, {\tt \$fair}, {\tt \$cover}, {\tt \$equiv},
-{\tt \$initstate}, {\tt \$anyconst}, {\tt \$anyseq}, {\tt \$allconst}, {\tt \$allseq} cells.
-\end{fixme}
-
-\begin{fixme}
-Add information about {\tt \$specify2}, {\tt \$specify3}, and {\tt \$specrule} cells.
-\end{fixme}
-
-\begin{fixme}
Add information about {\tt \$slice} and {\tt \$concat} cells.
\end{fixme}
@@ -757,16 +1005,3 @@ Add information about {\tt \$lut} and {\tt \$sop} cells.
\begin{fixme}
Add information about {\tt \$alu}, {\tt \$macc}, {\tt \$fa}, and {\tt \$lcu} cells.
\end{fixme}
-
-\begin{fixme}
-Add information about {\tt \$ff} and {\tt \$\_FF\_} cells.
-\end{fixme}
-
-\begin{fixme}
-Add information about {\tt \$\_DLATCH\_?\_}, and {\tt \$\_DLATCHSR\_???\_} cells.
-\end{fixme}
-
-\begin{fixme}
-Add information about {\tt \$\_AOI3\_}, {\tt \$\_OAI3\_}, {\tt \$\_AOI4\_}, {\tt \$\_OAI4\_}, and {\tt \$\_NMUX\_} cells.
-\end{fixme}
-
diff --git a/manual/CHAPTER_Overview.tex b/manual/CHAPTER_Overview.tex
index 83cfa5cc4..50a56137c 100644
--- a/manual/CHAPTER_Overview.tex
+++ b/manual/CHAPTER_Overview.tex
@@ -39,15 +39,15 @@ the RTL Intermediate Language (RTLIL). A more detailed description of this forma
is given in the next section.
There is also a text representation of the RTLIL data structure that can be
-parsed using the ILANG Frontend.
+parsed using the RTLIL Frontend.
The design data may then be transformed using a series of passes that all
operate on the RTLIL representation of the design.
Finally the design in RTLIL representation is converted back to text by one
of the backends, namely the Verilog Backend for generating Verilog netlists
-and the ILANG Backend for writing the RTLIL data in the same format that is
-understood by the ILANG Frontend.
+and the RTLIL Backend for writing the RTLIL data in the same format that is
+understood by the RTLIL Frontend.
With the exception of the AST Frontend, which is called by the high-level HDL
frontends and can't be called directly by the user, all program modules are
@@ -67,13 +67,13 @@ in different stages of the synthesis.
\tikzstyle{data} = [draw, fill=blue!10, ellipse, minimum height=3em, minimum width=7em, node distance=15em]
\node[process] (vlog) {Verilog Frontend};
\node[process, dashed, fill=green!5] (vhdl) [right of=vlog] {VHDL Frontend};
- \node[process] (ilang) [right of=vhdl] {ILANG Frontend};
+ \node[process] (ilang) [right of=vhdl] {RTLIL Frontend};
\node[data] (ast) [below of=vlog, node distance=5em, xshift=7.5em] {AST};
\node[process] (astfe) [below of=ast, node distance=5em] {AST Frontend};
\node[data] (rtlil) [below of=astfe, node distance=5em, xshift=7.5em] {RTLIL};
\node[process] (pass) [right of=rtlil, node distance=5em, xshift=7.5em] {Passes};
\node[process] (vlbe) [below of=rtlil, node distance=7em, xshift=-13em] {Verilog Backend};
- \node[process] (ilangbe) [below of=rtlil, node distance=7em, xshift=0em] {ILANG Backend};
+ \node[process] (ilangbe) [below of=rtlil, node distance=7em, xshift=0em] {RTLIL Backend};
\node[process, dashed, fill=green!5] (otherbe) [below of=rtlil, node distance=7em, xshift=+13em] {Other Backends};
\draw[-latex] (vlog) -- (ast);
@@ -92,8 +92,7 @@ in different stages of the synthesis.
\section{The RTL Intermediate Language}
-All frontends, passes and backends in Yosys operate on a design in RTLIL\footnote{The {\it Language} in {\it RTL Intermediate Language}
-refers to the fact, that RTLIL also has a text representation, usually referred to as {\it Intermediate Language} (ILANG).} representation.
+All frontends, passes and backends in Yosys operate on a design in RTLIL representation.
The only exception are the high-level frontends that use the AST representation as an intermediate step before generating RTLIL
data.
@@ -231,6 +230,7 @@ generated twice. For modules with only a few parameters, a name directly contain
is generated instead of a hash string.)
\subsection{RTLIL::Cell and RTLIL::Wire}
+\label{sec:rtlil_cell_wire}
A module contains zero to many RTLIL::Cell and RTLIL::Wire objects. Objects of
these types are used to model netlists. Usually the goal of all synthesis efforts is to convert
@@ -276,6 +276,7 @@ The connections of ports to wires are coded by assigning an RTLIL::SigSpec
to each cell port. The RTLIL::SigSpec data type is described in the next section.
\subsection{RTLIL::SigSpec}
+\label{sec:rtlil_sigspec}
A ``signal'' is everything that can be applied to a cell port. I.e.
@@ -296,6 +297,7 @@ RTLIL::SigSpec objects. Such pairs are needed in different locations. Therefore
the type name RTLIL::SigSig was defined for such a pair.
\subsection{RTLIL::Process}
+\label{sec:rtlil_process}
When a high-level HDL frontend processes behavioural code it splits it up into
data path logic (e.g.~the expression {\tt a + b} is replaced by the output of an
@@ -316,7 +318,7 @@ endmodule
In this example there is no data path and therefore the RTLIL::Module generated by
the frontend only contains a few RTLIL::Wire objects and an RTLIL::Process.
-The RTLIL::Process in ILANG syntax:
+The RTLIL::Process in RTLIL syntax:
\begin{lstlisting}[numbers=left,frame=single,language=rtlil]
process $proc$ff_with_en_and_async_reset.v:4$1
@@ -348,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)
@@ -362,7 +365,7 @@ also contains an RTLIL::SwitchRule object (lines $3 \dots 12$). Such an object i
statement as it uses a control signal ({\tt \textbackslash{}reset} in this case) to determine
which of its cases should be active. The RTLIL::SwitchRule object then contains one RTLIL::CaseRule
object per case. In this example there is a case\footnote{The
-syntax {\tt 1'1} in the ILANG code specifies a constant with a length of one bit (the first ``1''),
+syntax {\tt 1'1} in the RTLIL code specifies a constant with a length of one bit (the first ``1''),
and this bit is a one (the second ``1'').} for {\tt \textbackslash{}reset == 1} that causes
{\tt \$0\textbackslash{}q[0:0]} to be set (lines 4 and 5) and a default case that in turn contains a switch that
sets {\tt \$0\textbackslash{}q[0:0]} to the value of {\tt \textbackslash{}d} if {\tt
@@ -445,6 +448,7 @@ pass calls a series of other passes that together perform this conversion in a w
for most synthesis tasks.
\subsection{RTLIL::Memory}
+\label{sec:rtlil_memory}
For every array (memory) in the HDL code an RTLIL::Memory object is created. A
memory object has the following properties:
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
new file mode 100644
index 000000000..67eade8bf
--- /dev/null
+++ b/manual/CHAPTER_TextRtlil.tex
@@ -0,0 +1,299 @@
+\chapter{RTLIL Text Representation}
+\label{chapter:textrtlil}
+
+% Stolen from stackexchange: calculate indent based on given keyword,
+% with some nice hrules added in.
+\newlength{\myl}
+
+\newenvironment{indentgrammar}[1]
+ {\vspace{0.5cm}\hrule
+ \setlength{\myl}{\widthof{#1}+2em}
+ \grammarindent\the\myl
+ \begin{grammar}}
+ {\end{grammar}
+ \hrule}
+
+This appendix documents the text representation of RTLIL in extended Backus-Naur form (EBNF).
+
+The grammar is not meant to represent semantic limitations. That is, the grammar is ``permissive'', and later stages of processing perform more rigorous checks.
+
+The grammar is also not meant to represent the exact grammar used in the RTLIL frontend, since that grammar is specific to processing by lex and yacc, is even more permissive, and is somewhat less understandable than simple EBNF notation.
+
+Finally, note that all statements (rules ending in \texttt{-stmt}) terminate in an end-of-line. Because of this, a statement cannot be broken into multiple lines.
+
+\section{Lexical elements}
+
+\subsection{Characters}
+
+An RTLIL file is a stream of bytes. Strictly speaking, a ``character'' in an RTLIL file is a single byte. The lexer treats multi-byte encoded characters as consecutive single-byte characters. While other encodings \textit{may} work, UTF-8 is known to be safe to use. Byte order marks at the beginning of the file will cause an error.
+
+ASCII spaces (32) and tabs (9) separate lexer tokens.
+
+A \texttt{nonws} character, used in identifiers, is any character whose encoding consists solely of bytes above ASCII space (32).
+
+An \texttt{eol} is one or more consecutive ASCII newlines (10) and carriage returns (13).
+
+\subsection{Identifiers}
+
+There are two types of identifiers in RTLIL:
+
+\begin{itemize}
+ \item Publically visible identifiers
+ \item Auto-generated identifiers
+\end{itemize}
+
+\begin{indentgrammar}{<autogen-id>}
+<id> ::= <public-id> | <autogen-id>
+
+<public-id> ::= "\textbackslash" <nonws>$+$
+
+<autogen-id> ::= "\textdollar" <nonws>$+$
+\end{indentgrammar}
+
+\subsection{Values}
+
+A \textit{value} consists of a width in bits and a bit representation, most significant bit first. Bits may be any of:
+\begin{itemize}
+ \item \texttt{0}: A logic zero value
+ \item \texttt{1}: A logic one value
+ \item \texttt{x}: An unknown logic value (or don't care in case patterns)
+ \item \texttt{z}: A high-impedance value (or don't care in case patterns)
+ \item \texttt{m}: A marked bit (internal use only)
+ \item \texttt{-}: A don't care value
+\end{itemize}
+
+An \textit{integer} is simply a signed integer value in decimal format. \textbf{Warning:} Integer constants are limited to 32 bits. That is, they may only be in the range $[-2147483648, 2147483648)$. Integers outside this range will result in an error.
+
+\begin{indentgrammar}{<binary-digit>}
+<value> ::= <decimal-digit>$+$ \texttt{\textbf{'}} <binary-digit>$*$
+
+<decimal-digit> ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
+
+<binary-digit> ::= "0" | "1" | "x" | "z" | "m" | "-"
+
+<integer> ::= "-"$?$ <decimal-digit>$+$
+\end{indentgrammar}
+
+\subsection{Strings}
+
+A string is a series of characters delimited by double-quote characters. Within a string, any character except ASCII NUL (0) may be used. In addition, certain escapes can be used:
+
+\begin{itemize}
+ \item \texttt{\textbackslash n}: A newline
+ \item \texttt{\textbackslash t}: A tab
+ \item \texttt{\textbackslash \textit{ooo}}: A character specified as a one, two, or three digit octal value
+\end{itemize}
+
+All other characters may be escaped by a backslash, and become the following character. Thus:
+
+\begin{itemize}
+ \item \texttt{\textbackslash \textbackslash}: A backslash
+ \item \texttt{\textbackslash ''}: A double-quote
+ \item \texttt{\textbackslash r}: An 'r' character
+\end{itemize}
+
+\subsection{Comments}
+
+A comment starts with a \texttt{\textbf{\#}} character and proceeds to the end of the line. All comments are ignored.
+
+\section{File}
+
+A file consists of an optional autoindex statement followed by zero or more modules.
+
+\begin{indentgrammar}{<design>}
+<file> ::= <autoidx-stmt>$?$ <module>*
+\end{indentgrammar}
+
+\subsection{Autoindex statements}
+
+The autoindex statement sets the global autoindex value used by Yosys when it needs to generate a unique name, e.g. \texttt{\textdollar{}flatten\textdollar{}N}. The N part is filled with the value of the global autoindex value, which is subsequently incremented. This global has to be dumped into RTLIL, otherwise e.g. dumping and running a pass would have different properties than just running a pass on a warm design.
+
+\begin{indentgrammar}{<autoidx-stmt>}
+<autoidx-stmt> ::= "autoidx" <integer> <eol>
+\end{indentgrammar}
+
+\subsection{Modules}
+
+Declares a module, with zero or more attributes, consisting of zero or more wires, memories, cells, processes, and connections.
+
+\begin{indentgrammar}{<module-body-stmt>}
+<module> ::= <attr-stmt>$*$ <module-stmt> <module-body> <module-end-stmt>
+
+<module-stmt> ::= "module" <id> <eol>
+
+<module-body> ::=
+(<param-stmt>
+ \alt <wire>
+ \alt <memory>
+ \alt <cell>
+ \alt <process>
+ \alt <conn-stmt>)$*$
+
+<param-stmt> ::= "parameter" <id> <constant>$?$ <eol>
+
+<constant> ::= <value> | <integer> | <string>
+
+<module-end-stmt> ::= "end" <eol>
+\end{indentgrammar}
+
+\subsection{Attribute statements}
+
+Declares an attribute with the given identifier and value.
+
+\begin{indentgrammar}{<attr-stmt>}
+<attr-stmt> ::= "attribute" <id> <constant> <eol>
+\end{indentgrammar}
+
+\subsection{Signal specifications}
+
+A signal is anything that can be applied to a cell port, i.e. a constant value, all bits or a selection of bits from a wire, or concatenations of those.
+
+\textbf{Warning:} When an integer constant is a sigspec, it is always 32 bits wide, 2's complement. For example, a constant of $-1$ is the same as \texttt{32'11111111111111111111111111111111}, while a constant of $1$ is the same as \texttt{32'1}.
+
+See Sec.~\ref{sec:rtlil_sigspec} for an overview of signal specifications.
+
+\begin{indentgrammar}{<sigspec>}
+<sigspec> ::=
+<constant>
+ \alt <wire-id>
+ \alt <sigspec> "[" <integer> (":" <integer>)$?$ "]"
+ \alt "\{" <sigspec>$*$ "\}"
+\end{indentgrammar}
+
+\subsection{Connections}
+
+Declares a connection between the given signals.
+
+\begin{indentgrammar}{<conn-stmt>}
+<conn-stmt> ::= "connect" <sigspec> <sigspec> <eol>
+\end{indentgrammar}
+
+\subsection{Wires}
+
+Declares a wire, with zero or more attributes, with the given identifier and options in the enclosing module.
+
+See Sec.~\ref{sec:rtlil_cell_wire} for an overview of wires.
+
+\begin{indentgrammar}{<wire-option>}
+<wire> ::= <attr-stmt>$*$ <wire-stmt>
+
+<wire-stmt> ::= "wire" <wire-option>$*$ <wire-id> <eol>
+
+<wire-id> ::= <id>
+
+<wire-option> ::=
+"width" <integer>
+ \alt "offset" <integer>
+ \alt "input" <integer>
+ \alt "output" <integer>
+ \alt "inout" <integer>
+ \alt "upto"
+ \alt "signed"
+\end{indentgrammar}
+
+\subsection{Memories}
+
+Declares a memory, with zero or more attributes, with the given identifier and options in the enclosing module.
+
+See Sec.~\ref{sec:rtlil_memory} for an overview of memory cells, and Sec.~\ref{sec:memcells} for details about memory cell types.
+
+\begin{indentgrammar}{<memory-option>}
+<memory> ::= <attr-stmt>$*$ <memory-stmt>
+
+<memory-stmt> ::= "memory" <memory-option>$*$ <id> <eol>
+
+<memory-option> ::=
+"width" <integer>
+ \alt "size" <integer>
+ \alt "offset" <integer>
+\end{indentgrammar}
+
+\subsection{Cells}
+
+Declares a cell, with zero or more attributes, with the given identifier and type in the enclosing module.
+
+Cells perform functions on input signals. See Chap.~\ref{chapter:celllib} for a detailed list of cell types.
+
+\begin{indentgrammar}{<cell-body-stmt>}
+<cell> ::= <attr-stmt>$*$ <cell-stmt> <cell-body-stmt>$*$ <cell-end-stmt>
+
+<cell-stmt> ::= "cell" <cell-type> <cell-id> <eol>
+
+<cell-id> ::= <id>
+
+<cell-type> ::= <id>
+
+<cell-body-stmt> ::=
+"parameter" ("signed" | "real")$?$ <id> <constant> <eol>
+ \alt "connect" <id> <sigspec> <eol>
+
+<cell-end-stmt> ::= "end" <eol>
+\end{indentgrammar}
+
+\subsection{Processes}
+
+Declares a process, with zero or more attributes, with the given identifier in the enclosing module. The body of a process consists of zero or more assignments, exactly one switch, and zero or more syncs.
+
+See Sec.~\ref{sec:rtlil_process} for an overview of processes.
+
+\begin{indentgrammar}{<switch-end-stmt>}
+<process> ::= <attr-stmt>$*$ <proc-stmt> <process-body> <proc-end-stmt>
+
+<proc-stmt> ::= "process" <id> <eol>
+
+<process-body> ::= <assign-stmt>$*$ <switch>$?$ <assign-stmt>$*$ <sync>$*$
+
+<assign-stmt> ::= "assign" <dest-sigspec> <src-sigspec> <eol>
+
+<dest-sigspec> ::= <sigspec>
+
+<src-sigspec> ::= <sigspec>
+
+<proc-end-stmt> ::= "end" <eol>
+
+\end{indentgrammar}
+
+\subsection{Switches}
+
+Switches test a signal for equality against a list of cases. Each case specifies a comma-separated list of signals to check against. If there are no signals in the list, then the case is the default case. The body of a case consists of zero or more switches and assignments. Both switches and cases may have zero or more attributes.
+
+\begin{indentgrammar}{<switch-end-stmt>}
+<switch> ::= <switch-stmt> <case>$*$ <switch-end-stmt>
+
+<switch-stmt> := <attr-stmt>$*$ "switch" <sigspec> <eol>
+
+<case> ::= <attr-stmt>$*$ <case-stmt> <case-body>
+
+<case-stmt> ::= "case" <compare>$?$ <eol>
+
+<compare> ::= <sigspec> ("," <sigspec>)$*$
+
+<case-body> ::= (<switch> | <assign-stmt>)$*$
+
+<switch-end-stmt> ::= "end" <eol>
+\end{indentgrammar}
+
+\subsection{Syncs}
+
+Syncs update signals with other signals when an event happens. Such an event may be:
+
+\begin{itemize}
+ \item An edge or level on a signal
+ \item Global clock ticks
+ \item Initialization
+ \item Always
+\end{itemize}
+
+\begin{indentgrammar}{<dest-sigspec>}
+<sync> ::= <sync-stmt> <update-stmt>$*$
+
+<sync-stmt> ::=
+"sync" <sync-type> <sigspec> <eol>
+ \alt "sync" "global" <eol>
+ \alt "sync" "init" <eol>
+ \alt "sync" "always" <eol>
+
+<sync-type> ::= "low" | "high" | "posedge" | "negedge" | "edge"
+
+<update-stmt> ::= "update" <dest-sigspec> <src-sigspec> <eol>
+\end{indentgrammar}
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 555ec9175..1c3b79fa0 100644
--- a/manual/PRESENTATION_Intro.tex
+++ b/manual/PRESENTATION_Intro.tex
@@ -231,7 +231,7 @@ as Qflow\footnote[frame]{\url{http://opencircuitdesign.com/qflow/}} for ASIC des
\node[data] (rtlil) [below of=astfe, node distance=5em, xshift=7.5em] {RTLIL};
\node[process] (pass) [right of=rtlil, node distance=5em, xshift=7.5em] {Passes};
\node[process] (vlbe) [below of=rtlil, node distance=7em, xshift=-13em] {Verilog Backend};
- \node[process] (ilangbe) [below of=rtlil, node distance=7em, xshift=0em] {ILANG Backend};
+ \node[process] (ilangbe) [below of=rtlil, node distance=7em, xshift=0em] {RTLIL Backend};
\node[process, fill=green!5] (otherbe) [below of=rtlil, node distance=7em, xshift=+13em] {Other Backends};
\draw[-latex] (vlog) -- (ast);
@@ -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
@@ -484,7 +484,7 @@ Commands for design navigation and investigation:
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=ys]
cd # a shortcut for 'select -module <name>'
ls # list modules or objects in modules
- dump # print parts of the design in ilang format
+ dump # print parts of the design in RTLIL format
show # generate schematics using graphviz
select # modify and view the list of selected objects
\end{lstlisting}
@@ -502,7 +502,7 @@ Commands for executing scripts or entering interactive mode:
\begin{frame}[fragile]{\subsecname{} 2/3 \hspace{0pt plus 1 filll} (excerpt)}
Commands for reading and elaborating the design:
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=ys]
- read_ilang # read modules from ilang file
+ read_rtlil # read modules from RTLIL file
read_verilog # read modules from Verilog file
hierarchy # check, expand and clean up design hierarchy
\end{lstlisting}
@@ -534,7 +534,7 @@ Commands for writing the results:
write_blif # write design to BLIF file
write_btor # write design to BTOR file
write_edif # write design to EDIF netlist file
- write_ilang # write design to ilang file
+ write_rtlil # write design to RTLIL file
write_spice # write design to SPICE netlist file
write_verilog # write design to Verilog file
\end{lstlisting}
@@ -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 a9416f82a..b0390cb99 100644
--- a/manual/PRESENTATION_Prog.tex
+++ b/manual/PRESENTATION_Prog.tex
@@ -22,7 +22,7 @@
\node[data] (rtlil) [below of=astfe, node distance=5em, xshift=7.5em] {RTLIL};
\node[process] (pass) [right of=rtlil, node distance=5em, xshift=7.5em] {Passes};
\node[process] (vlbe) [below of=rtlil, node distance=7em, xshift=-13em] {Verilog Backend};
- \node[process] (ilangbe) [below of=rtlil, node distance=7em, xshift=0em] {ILANG Backend};
+ \node[process] (ilangbe) [below of=rtlil, node distance=7em, xshift=0em] {RTLIL Backend};
\node[process, fill=green!5] (otherbe) [below of=rtlil, node distance=7em, xshift=+13em] {Other Backends};
\draw[-latex] (vlog) -- (ast);
@@ -105,8 +105,7 @@ For simplicity we only discuss this version of RTLIL in this presentation.
\begin{frame}{\subsecname}
\begin{itemize}
-\item The {\tt dump} command prints the design (or parts of it) in ILANG format. This is
-a text representation of RTLIL.
+\item The {\tt dump} command prints the design (or parts of it) in the text representation of RTLIL.
\bigskip
\item The {\tt show} command visualizes how the components in the design are connected.
@@ -591,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 75f087eca..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,%
@@ -75,6 +75,9 @@ bookmarksopen=false%
\usetikzlibrary{through}
\usetikzlibrary{shapes.geometric}
+\usepackage{calc}
+\usepackage[nounderscore]{syntax}
+
\lstset{basicstyle=\ttfamily}
\def\B#1{{\tt\textbackslash{}#1}}
@@ -134,7 +137,7 @@ bookmarksopen=false%
\bf\Huge Yosys Manual
\bigskip
-\large Clifford Wolf
+\large Claire Xenia Wolf
\end{center}
\vfil\null
@@ -214,6 +217,7 @@ YOSYS & Yosys Open SYnthesis Suite \\
\label{commandref}
\input{command-reference-manual}
+\include{CHAPTER_TextRtlil}
\include{CHAPTER_Appnotes}
% \include{CHAPTER_StateOfTheArt}
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 5ec2fb6ad..16a38b511 100644
--- a/passes/cmds/Makefile.inc
+++ b/passes/cmds/Makefile.inc
@@ -41,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 98d42aa83..7b621504d 100644
--- a/passes/cmds/bugpoint.cc
+++ b/passes/cmds/bugpoint.cc
@@ -18,10 +18,10 @@
*/
#include "kernel/yosys.h"
-#include "backends/ilang/ilang_backend.h"
+#include "backends/rtlil/rtlil_backend.h"
USING_YOSYS_NAMESPACE
-using namespace ILANG_BACKEND;
+using namespace RTLIL_BACKEND;
PRIVATE_NAMESPACE_BEGIN
struct BugpointPass : public Pass {
@@ -30,7 +30,7 @@ struct BugpointPass : public Pass {
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
- log(" bugpoint [options] -script <filename>\n");
+ log(" bugpoint [options] [-script <filename> | -command \"<command>\"]\n");
log("\n");
log("This command minimizes the current design that is known to crash Yosys with the\n");
log("given script into a smaller testcase. It does this by removing an arbitrary part\n");
@@ -38,14 +38,16 @@ 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>\n");
- log(" use this script to crash Yosys. required.\n");
+ log(" -script <filename> | -command \"<command>\"\n");
+ log(" use this script file or command to crash Yosys. required.\n");
log("\n");
log(" -yosys <filename>\n");
log(" use this Yosys binary. if not specified, `yosys` is used.\n");
log("\n");
- log(" -grep <string>\n");
+ log(" -grep \"<string>\"\n");
log(" only consider crashes that place this string in the log file.\n");
log("\n");
log(" -fast\n");
@@ -77,23 +79,30 @@ struct BugpointPass : public Pass {
log(" -connections\n");
log(" try to reconnect ports to 'x.\n");
log("\n");
+ log(" -processes\n");
+ log(" try to remove processes. processes with a (* bugpoint_keep *) attribute\n");
+ log(" will be skipped.\n");
+ log("\n");
log(" -assigns\n");
log(" try to remove process assigns from cases.\n");
log("\n");
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 script)
+ bool run_yosys(RTLIL::Design *design, string runner, string yosys_cmd, string yosys_arg)
{
design->sort();
std::ofstream f("bugpoint-case.il");
- ILANG_BACKEND::dump_design(f, design, /*only_selected=*/false, /*flag_m=*/true, /*flag_n=*/false);
+ 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 %s bugpoint-case.il", yosys_cmd.c_str(), script.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;
}
@@ -102,6 +111,9 @@ struct BugpointPass : public Pass {
if (grep.empty())
return true;
+ if (grep.size() > 2 && grep.front() == '"' && grep.back() == '"')
+ grep = grep.substr(1, grep.size() - 2);
+
std::ifstream f("bugpoint-case.log");
while (!f.eof())
{
@@ -129,7 +141,7 @@ struct BugpointPass : public Pass {
return design_copy;
}
- RTLIL::Design *simplify_something(RTLIL::Design *design, int &seed, bool stage2, bool modules, bool ports, bool cells, bool connections, bool assigns, bool updates)
+ RTLIL::Design *simplify_something(RTLIL::Design *design, int &seed, bool stage2, bool modules, bool ports, bool cells, bool connections, bool processes, bool assigns, bool updates, bool wires)
{
RTLIL::Design *design_copy = new RTLIL::Design;
for (auto module : design->modules())
@@ -194,7 +206,6 @@ struct BugpointPass : public Pass {
if (mod->get_blackbox_attribute())
continue;
-
Cell *removed_cell = nullptr;
for (auto cell : mod->cells())
{
@@ -257,6 +268,32 @@ struct BugpointPass : public Pass {
}
}
}
+ if (processes)
+ {
+ for (auto mod : design_copy->modules())
+ {
+ if (mod->get_blackbox_attribute())
+ continue;
+
+ RTLIL::Process *removed_process = nullptr;
+ for (auto process : mod->processes)
+ {
+ if (process.second->get_bool_attribute(ID::bugpoint_keep))
+ continue;
+
+ if (index++ == seed)
+ {
+ log_header(design, "Trying to remove process %s.%s.\n", log_id(mod), log_id(process.first));
+ removed_process = process.second;
+ break;
+ }
+ }
+ if (removed_process) {
+ mod->remove(removed_process);
+ return design_copy;
+ }
+ }
+ }
if (assigns)
{
for (auto mod : design_copy->modules())
@@ -306,8 +343,54 @@ 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;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (wires)
+ {
+ for (auto mod : design_copy->modules())
+ {
+ if (mod->get_blackbox_attribute())
+ continue;
+
+ Wire *removed_wire = nullptr;
+ for (auto wire : mod->wires())
+ {
+ if (wire->get_bool_attribute(ID::bugpoint_keep))
+ continue;
+
+ if (wire->name.begins_with("$delete_wire") || wire->name.begins_with("$auto$bugpoint"))
+ continue;
+
+ if (index++ == seed)
+ {
+ log_header(design, "Trying to remove wire %s.%s.\n", log_id(mod), log_id(wire));
+ removed_wire = wire;
+ break;
}
}
+ if (removed_wire) {
+ mod->remove({removed_wire});
+ return design_copy;
+ }
}
}
return nullptr;
@@ -315,9 +398,9 @@ struct BugpointPass : public Pass {
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
- string yosys_cmd = "yosys", script, grep;
+ string yosys_cmd = "yosys", yosys_arg, grep, runner;
bool fast = false, clean = false;
- bool modules = false, ports = false, cells = false, connections = false, assigns = false, updates = false, has_part = false;
+ bool modules = false, ports = false, cells = false, connections = false, processes = false, assigns = false, updates = false, wires = false, has_part = false;
log_header(design, "Executing BUGPOINT pass (minimize testcases).\n");
log_push();
@@ -330,7 +413,15 @@ struct BugpointPass : public Pass {
continue;
}
if (args[argidx] == "-script" && argidx + 1 < args.size()) {
- script = args[++argidx];
+ if (!yosys_arg.empty())
+ log_cmd_error("A -script or -command option can be only provided once!\n");
+ yosys_arg = stringf("-s %s", args[++argidx].c_str());
+ continue;
+ }
+ if (args[argidx] == "-command" && argidx + 1 < args.size()) {
+ if (!yosys_arg.empty())
+ log_cmd_error("A -script or -command option can be only provided once!\n");
+ yosys_arg = stringf("-p %s", args[++argidx].c_str());
continue;
}
if (args[argidx] == "-grep" && argidx + 1 < args.size()) {
@@ -365,6 +456,11 @@ struct BugpointPass : public Pass {
has_part = true;
continue;
}
+ if (args[argidx] == "-processes") {
+ processes = true;
+ has_part = true;
+ continue;
+ }
if (args[argidx] == "-assigns") {
assigns = true;
has_part = true;
@@ -375,12 +471,25 @@ struct BugpointPass : public Pass {
has_part = true;
continue;
}
+ if (args[argidx] == "-wires") {
+ wires = true;
+ 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);
- if (script.empty())
- log_cmd_error("Missing -script option.\n");
+ if (yosys_arg.empty())
+ log_cmd_error("Missing -script or -command option.\n");
if (!has_part)
{
@@ -388,16 +497,18 @@ struct BugpointPass : public Pass {
ports = true;
cells = true;
connections = true;
+ processes = true;
assigns = true;
updates = true;
+ wires = true;
}
if (!design->full_selection())
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, script))
- log_cmd_error("The provided script file and Yosys binary do not crash on this design!\n");
+ 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");
@@ -405,7 +516,7 @@ struct BugpointPass : public Pass {
bool found_something = false, stage2 = false;
while (true)
{
- if (RTLIL::Design *simplified = simplify_something(crashing_design, seed, stage2, modules, ports, cells, connections, assigns, updates))
+ if (RTLIL::Design *simplified = simplify_something(crashing_design, seed, stage2, modules, ports, cells, connections, processes, assigns, updates, wires))
{
simplified = clean_design(simplified, fast, /*do_delete=*/true);
@@ -413,12 +524,12 @@ struct BugpointPass : public Pass {
if (clean)
{
RTLIL::Design *testcase = clean_design(simplified);
- crashes = !run_yosys(testcase, yosys_cmd, script);
+ crashes = !run_yosys(testcase, runner, yosys_cmd, yosys_arg);
delete testcase;
}
else
{
- crashes = !run_yosys(simplified, yosys_cmd, script);
+ 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 a8b5362b3..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
@@ -35,30 +35,28 @@ struct CheckPass : public Pass {
log("\n");
log("This pass identifies the following problems in the current design:\n");
log("\n");
- log(" - combinatorial loops\n");
- log("\n");
- log(" - two or more conflicting drivers for one wire\n");
- log("\n");
- log(" - used wires that do not have a driver\n");
+ log(" - combinatorial loops\n");
+ log(" - two or more conflicting drivers for one wire\n");
+ log(" - used wires that do not have a driver\n");
log("\n");
log("Options:\n");
log("\n");
- log(" -noinit\n");
- log(" Also check for wires which have the 'init' attribute set.\n");
+ log(" -noinit\n");
+ log(" also check for wires which have the 'init' attribute set\n");
log("\n");
- log(" -initdrv\n");
- log(" Also check for wires that have the 'init' attribute set and are not\n");
- log(" driven by an FF cell type.\n");
+ log(" -initdrv\n");
+ log(" also check for wires that have the 'init' attribute set and are not\n");
+ log(" driven by an FF cell type\n");
log("\n");
- log(" -mapped\n");
- log(" Also check for internal cells that have not been mapped to cells of the\n");
- log(" target architecture.\n");
+ log(" -mapped\n");
+ log(" also check for internal cells that have not been mapped to cells of the\n");
+ log(" target architecture\n");
log("\n");
- log(" -allow-tbuf\n");
- log(" Modify the -mapped behavior to still allow $_TBUF_ cells.\n");
+ log(" -allow-tbuf\n");
+ log(" modify the -mapped behavior to still allow $_TBUF_ cells\n");
log("\n");
- log(" -assert\n");
- log(" Produce a runtime error if any problems are found in the current design.\n");
+ log(" -assert\n");
+ log(" produce a runtime error if any problems are found in the current design\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
@@ -100,10 +98,7 @@ struct CheckPass : public Pass {
for (auto module : design->selected_whole_modules_warn())
{
- if (module->has_processes_warn())
- continue;
-
- log("checking module %s..\n", log_id(module));
+ log("Checking module %s...\n", log_id(module));
SigMap sigmap(module);
dict<SigBit, vector<string>> wire_drivers;
@@ -111,6 +106,52 @@ struct CheckPass : public Pass {
pool<SigBit> used_wires;
TopoSort<string> topo;
+ for (auto &proc_it : module->processes)
+ {
+ std::vector<RTLIL::CaseRule*> all_cases = {&proc_it.second->root_case};
+ for (size_t i = 0; i < all_cases.size(); i++) {
+ for (auto action : all_cases[i]->actions) {
+ for (auto bit : sigmap(action.first))
+ if (bit.wire) {
+ wire_drivers[bit].push_back(
+ stringf("action %s <= %s (case rule) in process %s",
+ log_signal(action.first), log_signal(action.second), log_id(proc_it.first)));
+ }
+ for (auto bit : sigmap(action.second))
+ if (bit.wire) used_wires.insert(bit);
+ }
+ for (auto switch_ : all_cases[i]->switches) {
+ for (auto case_ : switch_->cases) {
+ all_cases.push_back(case_);
+ for (auto compare : case_->compare)
+ for (auto bit : sigmap(compare))
+ if (bit.wire) used_wires.insert(bit);
+ }
+ }
+ }
+ for (auto &sync : proc_it.second->syncs) {
+ for (auto bit : sigmap(sync->signal))
+ if (bit.wire) used_wires.insert(bit);
+ for (auto action : sync->actions) {
+ for (auto bit : sigmap(action.first))
+ if (bit.wire)
+ wire_drivers[bit].push_back(
+ stringf("action %s <= %s (sync rule) in process %s",
+ log_signal(action.first), log_signal(action.second), log_id(proc_it.first)));
+ 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);
+ }
+ }
+ }
+
for (auto cell : module->cells())
{
if (mapped && cell->type.begins_with("$") && design->module(cell->type) == nullptr) {
@@ -216,7 +257,7 @@ struct CheckPass : public Pass {
}
}
- log("found and reported %d problems.\n", counter);
+ log("Found and reported %d problems.\n", counter);
if (assert_mode && counter > 0)
log_error("Found %d problems in 'check -assert'.\n", counter);
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/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 3ed19497d..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
@@ -93,7 +93,11 @@ void load_plugin(std::string filename, std::vector<std::string> aliases)
#else
void load_plugin(std::string, std::vector<std::string>)
{
- log_error("This version of yosys is built without plugin support.\n");
+ log_error(
+ "\n This version of Yosys cannot load plugins at runtime.\n"
+ " Some plugins may have been included at build time.\n"
+ " Use option `-H' to see the available built-in and plugin commands.\n"
+ );
}
#endif
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 6326b4b15..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
@@ -290,11 +290,11 @@ struct RenamePass : public Pass {
dict<RTLIL::Cell *, IdString> new_cell_names;
for (auto wire : module->selected_wires())
- if (wire->name[0] == '\\' && wire->port_id == 0)
+ if (wire->name.isPublic() && wire->port_id == 0)
new_wire_names[wire] = NEW_ID;
for (auto cell : module->selected_cells())
- if (cell->name[0] == '\\')
+ if (cell->name.isPublic())
new_cell_names[cell] = NEW_ID;
for (auto &it : new_wire_names)
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 8e7f3f990..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
@@ -37,7 +37,7 @@ struct SccWorker
RTLIL::Design *design;
RTLIL::Module *module;
SigMap sigmap;
- CellTypes ct;
+ CellTypes ct, specifyCells;
std::set<RTLIL::Cell*> workQueue;
std::map<RTLIL::Cell*, std::set<RTLIL::Cell*>> cellToNextCell;
@@ -100,7 +100,7 @@ struct SccWorker
}
}
- SccWorker(RTLIL::Design *design, RTLIL::Module *module, bool nofeedbackMode, bool allCellTypes, int maxDepth) :
+ SccWorker(RTLIL::Design *design, RTLIL::Module *module, bool nofeedbackMode, bool allCellTypes, bool specifyMode, int maxDepth) :
design(design), module(module), sigmap(module)
{
if (module->processes.size() > 0) {
@@ -115,6 +115,18 @@ struct SccWorker
ct.setup_stdcells();
}
+ // Discover boxes with specify rules in them, for special handling.
+ if (specifyMode) {
+ for (auto mod : design->modules())
+ if (mod->get_blackbox_attribute(false))
+ for (auto cell : mod->cells())
+ if (cell->type == ID($specify2))
+ {
+ specifyCells.setup_module(mod);
+ break;
+ }
+ }
+
SigPool selectedSignals;
SigSet<RTLIL::Cell*> sigToNextCells;
@@ -129,29 +141,52 @@ struct SccWorker
if (!design->selected(module, cell))
continue;
- if (!allCellTypes && !ct.cell_known(cell->type))
+ if (!allCellTypes && !ct.cell_known(cell->type) && !specifyCells.cell_known(cell->type))
continue;
workQueue.insert(cell);
RTLIL::SigSpec inputSignals, outputSignals;
- for (auto &conn : cell->connections())
- {
- bool isInput = true, isOutput = true;
+ if (specifyCells.cell_known(cell->type)) {
+ // Use specify rules of the type `(X => Y) = NN` to look for asynchronous paths in boxes.
+ for (auto subcell : design->module(cell->type)->cells())
+ {
+ if (subcell->type != ID($specify2))
+ continue;
- if (ct.cell_known(cell->type)) {
- isInput = ct.cell_input(cell->type, conn.first);
- isOutput = ct.cell_output(cell->type, conn.first);
+ for (auto bit : subcell->getPort(ID::SRC))
+ {
+ if (!bit.wire || !cell->hasPort(bit.wire->name))
+ continue;
+ inputSignals.append(sigmap(cell->getPort(bit.wire->name)));
+ }
+
+ for (auto bit : subcell->getPort(ID::DST))
+ {
+ if (!bit.wire || !cell->hasPort(bit.wire->name))
+ continue;
+ outputSignals.append(sigmap(cell->getPort(bit.wire->name)));
+ }
}
+ } else {
+ for (auto &conn : cell->connections())
+ {
+ bool isInput = true, isOutput = true;
+
+ if (ct.cell_known(cell->type)) {
+ isInput = ct.cell_input(cell->type, conn.first);
+ isOutput = ct.cell_output(cell->type, conn.first);
+ }
- RTLIL::SigSpec sig = selectedSignals.extract(sigmap(conn.second));
- sig.sort_and_unify();
+ RTLIL::SigSpec sig = selectedSignals.extract(sigmap(conn.second));
+ sig.sort_and_unify();
- if (isInput)
- inputSignals.append(sig);
- if (isOutput)
- outputSignals.append(sig);
+ if (isInput)
+ inputSignals.append(sig);
+ if (isOutput)
+ outputSignals.append(sig);
+ }
}
inputSignals.sort_and_unify();
@@ -228,7 +263,7 @@ struct SccPass : public Pass {
log("design.\n");
log("\n");
log(" -expect <num>\n");
- log(" expect to find exactly <num> SSCs. A different number of SSCs will\n");
+ log(" expect to find exactly <num> SCCs. A different number of SCCs will\n");
log(" produce an error.\n");
log("\n");
log(" -max_depth <num>\n");
@@ -254,6 +289,9 @@ struct SccPass : public Pass {
log(" replace the current selection with a selection of all cells and wires\n");
log(" that are part of a found logic loop\n");
log("\n");
+ log(" -specify\n");
+ log(" examine specify rules to detect logic loops in whitebox/blackbox cells\n");
+ log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
@@ -261,6 +299,7 @@ struct SccPass : public Pass {
bool allCellTypes = false;
bool selectMode = false;
bool nofeedbackMode = false;
+ bool specifyMode = false;
int maxDepth = -1;
int expect = -1;
@@ -293,6 +332,10 @@ struct SccPass : public Pass {
selectMode = true;
continue;
}
+ if (args[argidx] == "-specify") {
+ specifyMode = true;
+ continue;
+ }
break;
}
int origSelectPos = design->selection_stack.size() - 1;
@@ -303,7 +346,7 @@ struct SccPass : public Pass {
for (auto mod : design->selected_modules())
{
- SccWorker worker(design, mod, nofeedbackMode, allCellTypes, maxDepth);
+ SccWorker worker(design, mod, nofeedbackMode, allCellTypes, specifyMode, maxDepth);
if (!setAttr.empty())
{
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 cbed08a3f..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)
@@ -368,7 +386,7 @@ struct ShowWorker
const char *shape = "diamond";
if (wire->port_input || wire->port_output)
shape = "octagon";
- if (wire->name[0] == '\\') {
+ if (wire->name.isPublic()) {
fprintf(f, "n%d [ shape=%s, label=\"%s\", %s, fontcolor=\"black\" ];\n",
id2num(wire->name), shape, findLabel(wire->name.str()),
nextColor(RTLIL::SigSpec(wire), "color=\"black\"").c_str());
@@ -605,7 +623,7 @@ struct ShowPass : public Pass {
log(" generate a .dot file, or other <format> strings such as 'svg' or 'ps'\n");
log(" to generate files in other formats (this calls the 'dot' command).\n");
log("\n");
- log(" -lib <verilog_or_ilang_file>\n");
+ log(" -lib <verilog_or_rtlil_file>\n");
log(" Use the specified library file for determining whether cell ports are\n");
log(" inputs or outputs. This option can be used multiple times to specify\n");
log(" more than one library.\n");
@@ -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");
@@ -811,7 +829,7 @@ struct ShowPass : public Pass {
if (f.fail())
log_error("Can't open lib file `%s'.\n", filename.c_str());
RTLIL::Design *lib = new RTLIL::Design;
- Frontend::frontend_call(lib, &f, filename, (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".il") == 0 ? "ilang" : "verilog"));
+ Frontend::frontend_call(lib, &f, filename, (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".il") == 0 ? "rtlil" : "verilog"));
libs.push_back(lib);
}
diff --git a/passes/cmds/splice.cc b/passes/cmds/splice.cc
index 20627d601..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
@@ -211,7 +211,7 @@ struct SpliceWorker
std::vector<Wire*> mod_wires = module->wires();
for (auto wire : mod_wires)
- if ((!no_outputs && wire->port_output) || (do_wires && wire->name[0] == '\\')) {
+ if ((!no_outputs && wire->port_output) || (do_wires && wire->name.isPublic())) {
if (!design->selected(module, wire))
continue;
RTLIL::SigSpec sig = sigmap(wire);
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 ed51fdc24..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
@@ -81,7 +81,7 @@ struct statdata_t
for (auto wire : mod->selected_wires())
{
- if (wire->name[0] == '\\') {
+ if (wire->name.isPublic()) {
num_pub_wires++;
num_pub_wire_bits += wire->width;
}
@@ -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 596c938fc..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)) {
@@ -65,8 +68,10 @@ struct EquivInductWorker
int ez_a = satgen.importSigBit(bit_a, step);
int ez_b = satgen.importSigBit(bit_b, step);
int cond = ez->IFF(ez_a, ez_b);
- if (satgen.model_undef)
+ if (satgen.model_undef) {
+ cond = ez->AND(cond, ez->NOT(satgen.importUndefSigBit(bit_b, step)));
cond = ez->OR(cond, satgen.importUndefSigBit(bit_a, step));
+ }
ez_equal_terms.push_back(cond);
}
}
diff --git a/passes/equiv/equiv_make.cc b/passes/equiv/equiv_make.cc
index 51b4ad0f1..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
@@ -114,25 +114,25 @@ struct EquivMakeWorker
Module *gate_clone = gate_mod->clone();
for (auto it : gold_clone->wires().to_vector()) {
- if ((it->name[0] == '\\' || inames) && blacklist_names.count(it->name) == 0)
+ if ((it->name.isPublic() || inames) && blacklist_names.count(it->name) == 0)
wire_names.insert(it->name);
gold_clone->rename(it, it->name.str() + "_gold");
}
for (auto it : gold_clone->cells().to_vector()) {
- if ((it->name[0] == '\\' || inames) && blacklist_names.count(it->name) == 0)
+ if ((it->name.isPublic() || inames) && blacklist_names.count(it->name) == 0)
cell_names.insert(it->name);
gold_clone->rename(it, it->name.str() + "_gold");
}
for (auto it : gate_clone->wires().to_vector()) {
- if ((it->name[0] == '\\' || inames) && blacklist_names.count(it->name) == 0)
+ if ((it->name.isPublic() || inames) && blacklist_names.count(it->name) == 0)
wire_names.insert(it->name);
gate_clone->rename(it, it->name.str() + "_gate");
}
for (auto it : gate_clone->cells().to_vector()) {
- if ((it->name[0] == '\\' || inames) && blacklist_names.count(it->name) == 0)
+ if ((it->name.isPublic() || inames) && blacklist_names.count(it->name) == 0)
cell_names.insert(it->name);
gate_clone->rename(it, it->name.str() + "_gate");
}
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 d15c8d183..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
@@ -35,7 +35,7 @@ struct EquivPurgeWorker
{
if (sig.is_wire()) {
Wire *wire = sig.as_wire();
- if (wire->name[0] == '\\') {
+ if (wire->name.isPublic()) {
if (!wire->port_output) {
log(" Module output: %s (%s)\n", log_signal(wire), log_id(cellname));
wire->port_output = true;
@@ -62,7 +62,7 @@ struct EquivPurgeWorker
{
if (sig.is_wire()) {
Wire *wire = sig.as_wire();
- if (wire->name[0] == '\\') {
+ if (wire->name.isPublic()) {
if (!wire->port_output) {
log(" Module input: %s\n", log_signal(wire));
wire->port_input = true;
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 a2a428d15..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;
- }
-
- if (cell->type[0] == '$')
- continue;
-
- for (auto &dir : libdirs)
- {
- static const vector<pair<string, string>> extensions_list =
- {
- {".v", "verilog"},
- {".sv", "verilog -sv"},
- {".il", "ilang"}
- };
+ mod = get_module(*design, *cell, *module, flag_check || flag_simcheck, libdirs);
- 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));
- }
+ check_cell_connections(*module, *cell, *mod);
- }
- }
- RTLIL::Module *mod = design->module(cell->type);
-
- 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)
{
@@ -765,11 +923,13 @@ struct HierarchyPass : public Pass {
top_mod = design->module(top_name);
dict<RTLIL::IdString, RTLIL::Const> top_parameters;
- for (auto &para : parameters) {
- SigSpec sig_value;
- if (!RTLIL::SigSpec::parse(sig_value, NULL, para.second))
- log_cmd_error("Can't decode value '%s'!\n", para.second.c_str());
- top_parameters[RTLIL::escape_id(para.first)] = sig_value.as_const();
+ if ((top_mod == nullptr && design->module(abstract_id)) || top_mod != nullptr) {
+ for (auto &para : parameters) {
+ SigSpec sig_value;
+ if (!RTLIL::SigSpec::parse(sig_value, NULL, para.second))
+ log_cmd_error("Can't decode value '%s'!\n", para.second.c_str());
+ top_parameters[RTLIL::escape_id(para.first)] = sig_value.as_const();
+ }
}
if (top_mod == nullptr && design->module(abstract_id))
@@ -950,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));
@@ -978,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",
@@ -990,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;
}
}
@@ -1231,14 +1392,18 @@ struct HierarchyPass : public Pass {
{
int n = GetSize(conn.second) - GetSize(w);
if (!w->port_input && w->port_output)
- module->connect(sig.extract(GetSize(w), n), Const(0, n));
+ {
+ RTLIL::SigSpec out = sig.extract(0, GetSize(w));
+ out.extend_u0(GetSize(sig), w->is_signed);
+ module->connect(sig.extract(GetSize(w), n), out.extract(GetSize(w), n));
+ }
sig.remove(GetSize(w), n);
}
else
{
int n = GetSize(w) - GetSize(conn.second);
if (w->port_input && !w->port_output)
- sig.append(Const(0, n));
+ sig.extend_u0(GetSize(w), sig.is_wire() && sig.as_wire()->is_signed);
else
sig.append(module->addWire(NEW_ID, n));
}
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 3cb0728b7..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
@@ -18,6 +18,8 @@
*/
#include "kernel/yosys.h"
+#include "kernel/mem.h"
+#include "kernel/ffinit.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -28,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;
@@ -91,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;
@@ -400,17 +398,13 @@ struct rules_t
}
};
-bool replace_cell(Cell *cell, 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)
{
- Module *module = cell->module;
+ 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;
@@ -437,124 +431,33 @@ bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram,
log(" Mapping to bram type %s (variant %d):\n", log_id(bram.name), bram.variant);
// bram.dump_config();
- int mem_size = cell->getParam(ID::SIZE).as_int();
- int mem_abits = cell->getParam(ID::ABITS).as_int();
- int mem_width = cell->getParam(ID::WIDTH).as_int();
- // int mem_offset = cell->getParam(ID::OFFSET).as_int();
-
- bool cell_init = !SigSpec(cell->getParam(ID::INIT)).is_fully_undef();
- vector<Const> initdata;
-
- if (cell_init) {
- Const initparam = cell->getParam(ID::INIT);
- initdata.reserve(mem_size);
- for (int i=0; i < mem_size; i++)
- initdata.push_back(initparam.extract(mem_width*i, mem_width, State::Sx));
- }
-
- int wr_ports = cell->getParam(ID::WR_PORTS).as_int();
- auto wr_clken = SigSpec(cell->getParam(ID::WR_CLK_ENABLE));
- auto wr_clkpol = SigSpec(cell->getParam(ID::WR_CLK_POLARITY));
- wr_clken.extend_u0(wr_ports);
- wr_clkpol.extend_u0(wr_ports);
-
- SigSpec wr_en = cell->getPort(ID::WR_EN);
- SigSpec wr_clk = cell->getPort(ID::WR_CLK);
- SigSpec wr_data = cell->getPort(ID::WR_DATA);
- SigSpec wr_addr = cell->getPort(ID::WR_ADDR);
-
- int rd_ports = cell->getParam(ID::RD_PORTS).as_int();
- auto rd_clken = SigSpec(cell->getParam(ID::RD_CLK_ENABLE));
- auto rd_clkpol = SigSpec(cell->getParam(ID::RD_CLK_POLARITY));
- auto rd_transp = SigSpec(cell->getParam(ID::RD_TRANSPARENT));
- rd_clken.extend_u0(rd_ports);
- rd_clkpol.extend_u0(rd_ports);
- rd_transp.extend_u0(rd_ports);
-
- SigSpec rd_en = cell->getPort(ID::RD_EN);
- SigSpec rd_clk = cell->getPort(ID::RD_CLK);
- SigSpec rd_data = cell->getPort(ID::RD_DATA);
- SigSpec rd_addr = cell->getPort(ID::RD_ADDR);
-
- if (match.shuffle_enable && bram.dbits >= portinfos.at(match.shuffle_enable - 'A').enable*2 && portinfos.at(match.shuffle_enable - 'A').enable > 0 && wr_ports > 0)
+ 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 (int i = 0; i < wr_ports; i++) {
- old_wr_en.push_back(wr_en.extract(i*mem_width, mem_width));
- old_wr_data.push_back(wr_data.extract(i*mem_width, mem_width));
- }
-
- for (int i = 0; i < rd_ports; i++)
- old_rd_data.push_back(rd_data.extract(i*mem_width, mem_width));
-
// analyze enable structure
std::vector<SigSpec> en_order;
dict<SigSpec, vector<int>> bits_wr_en;
- for (int i = 0; i < mem_width; i++) {
+ for (int i = 0; i < mem.width; i++) {
SigSpec sig;
- for (int j = 0; j < wr_ports; j++)
- sig.append(old_wr_en[j][i]);
+ for (auto &port : mem.wr_ports)
+ sig.append(port.en[i]);
if (bits_wr_en.count(sig) == 0)
en_order.push_back(sig);
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 < 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 < 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 < wr_ports; j++) {
- new_wr_en[j].append(fillbit);
- new_wr_data[j].append(State::S0);
- }
- for (int j = 0; j < 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:");
@@ -563,53 +466,38 @@ bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram,
log("\n");
// update mem_*, wr_*, and rd_* variables
-
- mem_width = GetSize(new_wr_en.front());
- wr_en = SigSpec(0, wr_ports * mem_width);
- wr_data = SigSpec(0, wr_ports * mem_width);
- rd_data = SigSpec(0, rd_ports * mem_width);
-
- for (int i = 0; i < wr_ports; i++) {
- wr_en.replace(i*mem_width, new_wr_en[i]);
- wr_data.replace(i*mem_width, new_wr_data[i]);
- }
-
- for (int i = 0; i < rd_ports; i++)
- rd_data.replace(i*mem_width, 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 < wr_ports; cell_port_i++)
+ for (int cell_port_i = 0, bram_port_i = 0; cell_port_i < GetSize(mem.wr_ports); cell_port_i++)
{
- bool clken = wr_clken[cell_port_i] == State::S1;
- bool clkpol = wr_clkpol[cell_port_i] == State::S1;
- SigBit clksig = wr_clk[cell_port_i];
+ auto &port = mem.wr_ports[cell_port_i];
- pair<SigBit, bool> clkdom(clksig, clkpol);
- if (!clken)
+ pair<SigBit, bool> clkdom(port.clk, port.clk_polarity);
+ if (!port.clk_enable)
clkdom = pair<SigBit, bool>(State::S1, false);
wr_clkdom = clkdom;
log(" Write port #%d is in clock domain %s%s.\n",
cell_port_i, clkdom.second ? "" : "!",
- clken ? log_signal(clkdom.first) : "~async~");
+ port.clk_enable ? log_signal(clkdom.first) : "~async~");
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:
continue;
- if (clken) {
+ if (port.clk_enable) {
if (pi.clocks == 0) {
log(" Bram port %c%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1);
goto skip_bram_wport;
@@ -618,7 +506,7 @@ bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram,
log(" Bram port %c%d is in a different clock domain.\n", pi.group + 'A', pi.index + 1);
goto skip_bram_wport;
}
- if (clock_polarities.count(pi.clkpol) && clock_polarities.at(pi.clkpol) != clkpol) {
+ if (clock_polarities.count(pi.clkpol) && clock_polarities.at(pi.clkpol) != port.clk_polarity) {
log(" Bram port %c%d has incompatible clock polarity.\n", pi.group + 'A', pi.index + 1);
goto skip_bram_wport;
}
@@ -629,33 +517,36 @@ bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram,
}
}
- 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 = wr_en[i + cell_port_i*mem_width];
- sig_en.append(last_en_bit);
- }
- if (last_en_bit != wr_en[i + cell_port_i*mem_width]) {
- 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;
+ }
}
}
log(" Mapped to bram port %c%d.\n", pi.group + 'A', pi.index + 1);
pi.mapped_port = cell_port_i;
- if (clken) {
+ 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 = wr_addr.extract(cell_port_i*mem_abits, mem_abits);
- pi.sig_data = wr_data.extract(cell_port_i*mem_width, mem_width);
-
bram_port_i++;
goto mapped_wr_port;
}
@@ -678,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;
}
@@ -710,23 +597,27 @@ grow_read_ports:;
// assign read ports
- for (int cell_port_i = 0; cell_port_i < rd_ports; cell_port_i++)
+ for (int cell_port_i = 0; cell_port_i < GetSize(mem.rd_ports); cell_port_i++)
{
- bool clken = rd_clken[cell_port_i] == State::S1;
- bool clkpol = rd_clkpol[cell_port_i] == State::S1;
- bool transp = rd_transp[cell_port_i] == State::S1;
- SigBit clksig = rd_clk[cell_port_i];
-
- if (wr_ports == 0)
- transp = false;
+ auto &port = mem.rd_ports[cell_port_i];
+ 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(clksig, clkpol);
- if (!clken)
+ pair<SigBit, bool> clkdom(port.clk, port.clk_polarity);
+ if (!port.clk_enable)
clkdom = pair<SigBit, bool>(State::S1, false);
log(" Read port #%d is in clock domain %s%s.\n",
cell_port_i, clkdom.second ? "" : "!",
- clken ? log_signal(clkdom.first) : "~async~");
+ port.clk_enable ? log_signal(clkdom.first) : "~async~");
for (int bram_port_i = 0; bram_port_i < GetSize(portinfos); bram_port_i++)
{
@@ -736,7 +627,7 @@ grow_read_ports:;
skip_bram_rport:
continue;
- if (clken) {
+ if (port.clk_enable) {
if (pi.clocks == 0) {
if (match.make_outreg) {
pi.make_outreg = true;
@@ -749,25 +640,17 @@ grow_read_ports:;
log(" Bram port %c%d.%d is in a different clock domain.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
goto skip_bram_rport;
}
- if (clock_polarities.count(pi.clkpol) && clock_polarities.at(pi.clkpol) != clkpol) {
+ if (clock_polarities.count(pi.clkpol) && clock_polarities.at(pi.clkpol) != port.clk_polarity) {
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 (rd_en[cell_port_i] != 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 && 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 (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;
@@ -780,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 (clken) {
+ 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 = rd_en[cell_port_i];
- 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 = rd_addr.extract(cell_port_i*mem_abits, mem_abits);
- pi.sig_data = rd_data.extract(cell_port_i*mem_width, mem_width);
-
if (grow_read_ports_cursor < cell_port_i) {
grow_read_ports_cursor = cell_port_i;
try_growing_more_read_ports = true;
@@ -815,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"]);
@@ -857,8 +739,8 @@ grow_read_ports:;
bool exists = std::get<0>(term);
IdString key = std::get<1>(term);
const Const &value = std::get<2>(term);
- auto it = cell->attributes.find(key);
- if (it == cell->attributes.end()) {
+ auto it = mem.attributes.find(key);
+ if (it == mem.attributes.end()) {
if (exists)
continue;
found = true;
@@ -892,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;
@@ -902,42 +868,28 @@ 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", cell->name.c_str(), grid_d, grid_a, dupidx)), bram.name);
+ Cell *c = module->addCell(module->uniquify(stringf("%s.%d.%d.%d", mem.memid.c_str(), grid_d, grid_a, dupidx)), bram.name);
log(" Creating %s cell at grid position <%d %d %d>: %s\n", log_id(bram.name), grid_d, grid_a, dupidx, log_id(c));
for (auto &vp : variant_params)
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);
}
@@ -949,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);
+ }
}
}
}
@@ -1063,22 +998,23 @@ grow_read_ports:;
}
}
- module->remove(cell);
+ mem.remove();
return true;
}
-void handle_cell(Cell *cell, const rules_t &rules)
+void handle_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals)
{
- log("Processing %s.%s:\n", log_id(cell->module), log_id(cell));
+ log("Processing %s.%s:\n", log_id(mem.module), log_id(mem.memid));
+ mem.narrow();
- bool cell_init = !SigSpec(cell->getParam(ID::INIT)).is_fully_undef();
+ bool cell_init = !mem.inits.empty();
dict<string, int> match_properties;
- match_properties["words"] = cell->getParam(ID::SIZE).as_int();
- match_properties["abits"] = cell->getParam(ID::ABITS).as_int();
- match_properties["dbits"] = cell->getParam(ID::WIDTH).as_int();
- match_properties["wports"] = cell->getParam(ID::WR_PORTS).as_int();
- match_properties["rports"] = cell->getParam(ID::RD_PORTS).as_int();
+ match_properties["words"] = mem.size;
+ match_properties["abits"] = ceil_log2(mem.size);
+ match_properties["dbits"] = mem.width;
+ match_properties["wports"] = GetSize(mem.wr_ports);
+ match_properties["rports"] = GetSize(mem.rd_ports);
match_properties["bits"] = match_properties["words"] * match_properties["dbits"];
match_properties["ports"] = match_properties["wports"] + match_properties["rports"];
@@ -1181,8 +1117,8 @@ void handle_cell(Cell *cell, const rules_t &rules)
bool exists = std::get<0>(term);
IdString key = std::get<1>(term);
const Const &value = std::get<2>(term);
- auto it = cell->attributes.find(key);
- if (it == cell->attributes.end()) {
+ auto it = mem.attributes.find(key);
+ if (it == mem.attributes.end()) {
if (exists)
continue;
found = true;
@@ -1219,7 +1155,7 @@ void handle_cell(Cell *cell, 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_cell(cell, 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;
@@ -1246,12 +1182,12 @@ void handle_cell(Cell *cell, 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_cell(cell, 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_cell(cell, 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;
@@ -1383,10 +1319,12 @@ struct MemoryBramPass : public Pass {
}
extra_args(args, argidx, design);
- for (auto mod : design->selected_modules())
- for (auto cell : mod->selected_cells())
- if (cell->type == ID($mem))
- handle_cell(cell, 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 7e82f47dc..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
@@ -18,231 +18,11 @@
*/
#include "kernel/yosys.h"
-#include "kernel/sigtools.h"
+#include "kernel/mem.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-bool memcells_cmp(Cell *a, 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();
-}
-
-Cell *handle_memory(Module *module, RTLIL::Memory *memory)
-{
- log("Collecting $memrd, $memwr and $meminit for memory `%s' in module `%s':\n",
- memory->name.c_str(), module->name.c_str());
-
- Const init_data(State::Sx, memory->size * memory->width);
- SigMap sigmap(module);
-
- int wr_ports = 0;
- SigSpec sig_wr_clk;
- SigSpec sig_wr_clk_enable;
- SigSpec sig_wr_clk_polarity;
- SigSpec sig_wr_addr;
- SigSpec sig_wr_data;
- SigSpec sig_wr_en;
-
- int rd_ports = 0;
- SigSpec sig_rd_clk;
- SigSpec sig_rd_clk_enable;
- SigSpec sig_rd_clk_polarity;
- SigSpec sig_rd_transparent;
- SigSpec sig_rd_addr;
- SigSpec sig_rd_data;
- SigSpec sig_rd_en;
-
- int addr_bits = 0;
- std::vector<Cell*> memcells;
-
- for (auto cell : module->cells())
- if (cell->type.in(ID($memrd), ID($memwr), ID($meminit)) && memory->name == cell->parameters[ID::MEMID].decode_string()) {
- SigSpec addr = sigmap(cell->getPort(ID::ADDR));
- for (int i = 0; i < GetSize(addr); i++)
- if (addr[i] != State::S0)
- addr_bits = std::max(addr_bits, i+1);
- memcells.push_back(cell);
- }
-
- if (memory->start_offset == 0 && addr_bits < 30 && (1 << addr_bits) < memory->size)
- memory->size = 1 << addr_bits;
-
- if (memory->start_offset >= 0)
- addr_bits = std::min(addr_bits, ceil_log2(memory->size + memory->start_offset));
-
- addr_bits = std::max(addr_bits, 1);
-
- if (memcells.empty()) {
- log(" no cells found. removing memory.\n");
- return nullptr;
- }
-
- std::sort(memcells.begin(), memcells.end(), memcells_cmp);
-
- for (auto cell : memcells)
- {
- log(" %s (%s)\n", log_id(cell), log_id(cell->type));
-
- if (cell->type == ID($meminit))
- {
- SigSpec addr = sigmap(cell->getPort(ID::ADDR));
- SigSpec data = sigmap(cell->getPort(ID::DATA));
-
- if (!addr.is_fully_const())
- log_error("Non-constant address %s in memory initialization %s.\n", log_signal(addr), log_id(cell));
- if (!data.is_fully_const())
- log_error("Non-constant data %s in memory initialization %s.\n", log_signal(data), log_id(cell));
-
- int offset = (addr.as_int() - memory->start_offset) * memory->width;
-
- if (offset < 0 || offset + GetSize(data) > GetSize(init_data))
- log_warning("Address %s in memory initialization %s is out-of-bounds.\n", log_signal(addr), log_id(cell));
-
- for (int i = 0; i < GetSize(data); i++)
- if (0 <= i+offset && i+offset < GetSize(init_data))
- init_data.bits[i+offset] = data[i].data;
-
- continue;
- }
-
- if (cell->type == ID($memwr))
- {
- SigSpec clk = sigmap(cell->getPort(ID::CLK));
- SigSpec clk_enable = SigSpec(cell->parameters[ID::CLK_ENABLE]);
- SigSpec clk_polarity = SigSpec(cell->parameters[ID::CLK_POLARITY]);
- SigSpec addr = sigmap(cell->getPort(ID::ADDR));
- SigSpec data = sigmap(cell->getPort(ID::DATA));
- SigSpec en = sigmap(cell->getPort(ID::EN));
-
- if (!en.is_fully_zero())
- {
- clk.extend_u0(1, false);
- clk_enable.extend_u0(1, false);
- clk_polarity.extend_u0(1, false);
- addr.extend_u0(addr_bits, false);
- data.extend_u0(memory->width, false);
- en.extend_u0(memory->width, false);
-
- sig_wr_clk.append(clk);
- sig_wr_clk_enable.append(clk_enable);
- sig_wr_clk_polarity.append(clk_polarity);
- sig_wr_addr.append(addr);
- sig_wr_data.append(data);
- sig_wr_en.append(en);
-
- wr_ports++;
- }
- continue;
- }
-
- if (cell->type == ID($memrd))
- {
- SigSpec clk = sigmap(cell->getPort(ID::CLK));
- SigSpec clk_enable = SigSpec(cell->parameters[ID::CLK_ENABLE]);
- SigSpec clk_polarity = SigSpec(cell->parameters[ID::CLK_POLARITY]);
- SigSpec transparent = SigSpec(cell->parameters[ID::TRANSPARENT]);
- SigSpec addr = sigmap(cell->getPort(ID::ADDR));
- SigSpec data = sigmap(cell->getPort(ID::DATA));
- SigSpec en = sigmap(cell->getPort(ID::EN));
-
- if (!en.is_fully_zero())
- {
- clk.extend_u0(1, false);
- clk_enable.extend_u0(1, false);
- clk_polarity.extend_u0(1, false);
- transparent.extend_u0(1, false);
- addr.extend_u0(addr_bits, false);
- data.extend_u0(memory->width, false);
-
- sig_rd_clk.append(clk);
- sig_rd_clk_enable.append(clk_enable);
- sig_rd_clk_polarity.append(clk_polarity);
- sig_rd_transparent.append(transparent);
- sig_rd_addr.append(addr);
- sig_rd_data.append(data);
- sig_rd_en.append(en);
-
- rd_ports++;
- }
- continue;
- }
- }
-
- std::stringstream sstr;
- sstr << "$mem$" << memory->name.str() << "$" << (autoidx++);
-
- Cell *mem = module->addCell(sstr.str(), ID($mem));
- mem->parameters[ID::MEMID] = Const(memory->name.str());
- mem->parameters[ID::WIDTH] = Const(memory->width);
- mem->parameters[ID::OFFSET] = Const(memory->start_offset);
- mem->parameters[ID::SIZE] = Const(memory->size);
- mem->parameters[ID::ABITS] = Const(addr_bits);
- mem->parameters[ID::INIT] = init_data;
-
- log_assert(sig_wr_clk.size() == wr_ports);
- log_assert(sig_wr_clk_enable.size() == wr_ports && sig_wr_clk_enable.is_fully_const());
- log_assert(sig_wr_clk_polarity.size() == wr_ports && sig_wr_clk_polarity.is_fully_const());
- log_assert(sig_wr_addr.size() == wr_ports * addr_bits);
- log_assert(sig_wr_data.size() == wr_ports * memory->width);
- log_assert(sig_wr_en.size() == wr_ports * memory->width);
-
- mem->parameters[ID::WR_PORTS] = Const(wr_ports);
- mem->parameters[ID::WR_CLK_ENABLE] = wr_ports ? sig_wr_clk_enable.as_const() : State::S0;
- mem->parameters[ID::WR_CLK_POLARITY] = wr_ports ? sig_wr_clk_polarity.as_const() : State::S0;
-
- mem->setPort(ID::WR_CLK, sig_wr_clk);
- mem->setPort(ID::WR_ADDR, sig_wr_addr);
- mem->setPort(ID::WR_DATA, sig_wr_data);
- mem->setPort(ID::WR_EN, sig_wr_en);
-
- log_assert(sig_rd_clk.size() == rd_ports);
- log_assert(sig_rd_clk_enable.size() == rd_ports && sig_rd_clk_enable.is_fully_const());
- log_assert(sig_rd_clk_polarity.size() == rd_ports && sig_rd_clk_polarity.is_fully_const());
- log_assert(sig_rd_addr.size() == rd_ports * addr_bits);
- log_assert(sig_rd_data.size() == rd_ports * memory->width);
-
- mem->parameters[ID::RD_PORTS] = Const(rd_ports);
- mem->parameters[ID::RD_CLK_ENABLE] = rd_ports ? sig_rd_clk_enable.as_const() : State::S0;
- mem->parameters[ID::RD_CLK_POLARITY] = rd_ports ? sig_rd_clk_polarity.as_const() : State::S0;
- mem->parameters[ID::RD_TRANSPARENT] = rd_ports ? sig_rd_transparent.as_const() : State::S0;
-
- mem->setPort(ID::RD_CLK, sig_rd_clk);
- mem->setPort(ID::RD_ADDR, sig_rd_addr);
- mem->setPort(ID::RD_DATA, sig_rd_data);
- mem->setPort(ID::RD_EN, sig_rd_en);
-
- // Copy attributes from RTLIL memory to $mem
- for (auto attr : memory->attributes)
- mem->attributes[attr.first] = attr.second;
-
- for (auto c : memcells)
- module->remove(c);
-
- return mem;
-}
-
-static void handle_module(Design *design, Module *module)
-{
- std::vector<pair<Cell*, IdString>> finqueue;
-
- for (auto &mem_it : module->memories)
- if (design->selected(module, mem_it.second)) {
- Cell *c = handle_memory(module, mem_it.second);
- finqueue.push_back(pair<Cell*, IdString>(c, mem_it.first));
- }
- for (auto &it : finqueue) {
- delete module->memories.at(it.second);
- module->memories.erase(it.second);
- if (it.first)
- module->rename(it.first, it.second);
- }
-}
-
struct MemoryCollectPass : public Pass {
MemoryCollectPass() : Pass("memory_collect", "creating multi-port memory cells") { }
void help() override
@@ -258,8 +38,14 @@ struct MemoryCollectPass : public Pass {
void execute(std::vector<std::string> args, RTLIL::Design *design) override {
log_header(design, "Executing MEMORY_COLLECT pass (generating $mem cells).\n");
extra_args(args, 1, design);
- for (auto module : design->selected_modules())
- handle_module(design, module);
+ for (auto module : design->selected_modules()) {
+ for (auto &mem : Mem::get_selected_memories(module)) {
+ if (!mem.packed) {
+ mem.packed = true;
+ mem.emit();
+ }
+ }
+ }
}
} MemoryCollectPass;
diff --git a/passes/memory/memory_dff.cc b/passes/memory/memory_dff.cc
index 947cf7b35..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,313 +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
-{
- Module *module;
- SigMap sigmap;
+struct MuxData {
+ int base_idx;
+ int size;
+ bool is_b;
+ SigSpec sig_s;
+ std::vector<SigSpec> sig_other;
+};
- 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;
- pool<SigBit> init_bits;
+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;
+};
- MemoryDffWorker(Module *module) : module(module), sigmap(module)
- {
- for (auto wire : module->wires()) {
- if (wire->attributes.count(ID::init) == 0)
- continue;
- SigSpec sig = sigmap(wire);
- Const initval = wire->attributes.at(ID::init);
- for (int i = 0; i < GetSize(sig) && i < GetSize(initval); i++)
- if (initval[i] == State::S0 || initval[i] == State::S1)
- init_bits.insert(sig[i]);
+// 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
+{
+ 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;
}
- bool find_sig_before_dff(RTLIL::SigSpec &sig, RTLIL::SigSpec &clk, bool &clk_polarity, bool after = false)
- {
- sigmap.apply(sig);
-
- for (auto &bit : sig)
- {
- if (bit.wire == NULL)
- continue;
-
- if (!after && init_bits.count(sigmap(bit)))
- return false;
-
- for (auto cell : dff_cells)
- {
- if (after && forward_merged_dffs.count(cell))
- continue;
-
- SigSpec this_clk = cell->getPort(ID::CLK);
- bool this_clk_polarity = cell->parameters[ID::CLK_POLARITY].as_bool();
-
- if (invbits.count(this_clk)) {
- this_clk = invbits.at(this_clk);
- this_clk_polarity = !this_clk_polarity;
- }
-
- if (clk != RTLIL::SigSpec(RTLIL::State::Sx)) {
- if (this_clk != clk)
- continue;
- if (this_clk_polarity != clk_polarity)
- continue;
- }
+ // 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));
+ }
- RTLIL::SigSpec q_norm = cell->getPort(after ? ID::D : ID::Q);
- sigmap.apply(q_norm);
+ // 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;
+ }
- RTLIL::SigSpec d = q_norm.extract(bit, &cell->getPort(after ? ID::Q : ID::D));
- if (d.size() != 1)
- continue;
+ // 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;
+ }
- if (after && init_bits.count(d))
- return false;
+ // 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;
+ }
- bit = d;
- clk = this_clk;
- clk_polarity = this_clk_polarity;
- candidate_dffs.insert(cell);
- goto replaced_this_bit;
- }
+ // 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;
+ }
+ // 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;
- replaced_this_bit:;
+ 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;
+ }
- return true;
+ // 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);
}
+};
- void handle_wr_cell(RTLIL::Cell *cell)
+struct MemoryDffWorker
+{
+ Module *module;
+ ModWalker modwalker;
+ FfInitVals initvals;
+ FfMergeHelper merger;
+
+ MemoryDffWorker(Module *module) : module(module), modwalker(module->design)
{
- log("Checking cell `%s' in module `%s': ", cell->name.c_str(), module->name.c_str());
+ modwalker.setup(module);
+ initvals.set(&modwalker.sigmap, module);
+ merger.set(&initvals, module);
+ }
- RTLIL::SigSpec clk = RTLIL::SigSpec(RTLIL::State::Sx);
- bool clk_polarity = 0;
- candidate_dffs.clear();
+ // 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;
+ }
+ } else if (consumer.cell->type == ID($pmux)) {
+ if (consumer.port == ID::A) {
+ is_b = false;
+ } else {
+ continue;
+ }
+ } else {
+ continue;
+ }
+ 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);
+ }
+ 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);
+ }
+ prev_idx = i;
+ data[i] = ybit;
+ did_something = true;
+ }
+ } while (did_something);
+ return data;
+ }
- 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");
+ // 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)
+ {
+ 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;
}
-
- 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("output 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("output 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) {
+ // Latches and FFs with SR are not supported.
+ log("output FF has both set and 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 == ID($dff)) {
- RTLIL::SigSpec new_q = cell->getPort(ID::Q);
- new_q.replace(sig, new_sig);
- cell->setPort(ID::Q, new_q);
+ // 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;
+ }
+ }
}
- }
-
- 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;
-
- RTLIL::SigSpec clk_data = RTLIL::SigSpec(RTLIL::State::Sx);
- 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));
+ portdata.push_back(pd);
+ }
- for (auto bit : sig_data)
- if (sigbit_users_count[bit] > 1)
- goto skip_ff_after_read_merging;
+ // 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;
+ }
+ }
- if (find_sig_before_dff(sig_data, clk_data, clk_polarity, true) && clk_data != RTLIL::SigSpec(RTLIL::State::Sx) &&
- std::all_of(check_q.begin(), check_q.end(), [&](const SigSpec &cq) {return cq == sig_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");
+ // 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 (pd.transparency_mask[i])
+ trans = true;
+ else
+ non_trans = true;
+ }
+ 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;
}
+
+ // 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
- {
- if (find_sig_before_dff(sig_data, clk_data, clk_polarity, true) && clk_data != RTLIL::SigSpec(RTLIL::State::Sx))
- {
- disconnect_dff(sig_data);
- cell->setPort(ID::CLK, clk_data);
- cell->setPort(ID::EN, State::S1);
- 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");
- return;
+ 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();
+ }
- 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");
+ void handle_rd_port_addr(Mem &mem, int idx)
+ {
+ 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());
+
+ FfData ff;
+ pool<std::pair<Cell *, int>> bits;
+ if (!merger.find_input_ff(port.addr, ff, bits)) {
+ log("no address FF found.\n");
return;
}
-
- log("no (compatible) $dff found.\n");
+ if (!ff.has_clk) {
+ log("address latches are not supported.\n");
+ return;
+ }
+ if (ff.has_aload) {
+ log("address FF has async load, not supported.\n");
+ return;
+ }
+ if (ff.has_sr || ff.has_arst) {
+ log("address FF has async set and/or reset, not supported.\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;
+ }
+ 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;
+ }
+ }
+ // 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 == ID($dff))
- 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 80dd3957d..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
@@ -19,6 +19,7 @@
#include "kernel/register.h"
#include "kernel/log.h"
+#include "kernel/mem.h"
#include <sstream>
#include <set>
#include <stdlib.h>
@@ -33,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
{
@@ -97,35 +100,26 @@ struct MemoryMapWorker
return bit.wire;
}
- void handle_cell(RTLIL::Cell *cell)
+ void handle_memory(Mem &mem)
{
std::set<int> static_ports;
std::map<int, RTLIL::SigSpec> static_cells_map;
- int wr_ports = cell->parameters[ID::WR_PORTS].as_int();
- int rd_ports = cell->parameters[ID::RD_PORTS].as_int();
-
- int mem_size = cell->parameters[ID::SIZE].as_int();
- int mem_width = cell->parameters[ID::WIDTH].as_int();
- int mem_offset = cell->parameters[ID::OFFSET].as_int();
- int mem_abits = cell->parameters[ID::ABITS].as_int();
-
- SigSpec init_data = cell->getParam(ID::INIT);
- init_data.extend_u0(mem_size*mem_width, true);
+ SigSpec init_data = mem.get_init_data();
// delete unused memory cell
- if (wr_ports == 0 && rd_ports == 0) {
- module->remove(cell);
+ if (mem.rd_ports.empty()) {
+ mem.remove();
return;
}
- // check if attributes allow us to infer FFRAM for this cell
+ // check if attributes allow us to infer FFRAM for this memory
for (const auto &attr : attributes) {
- if (cell->attributes.count(attr.first)) {
- const auto &cell_attr = cell->attributes[attr.first];
+ if (mem.attributes.count(attr.first)) {
+ const auto &cell_attr = mem.attributes[attr.first];
if (attr.second.empty()) {
- log("Not mapping memory cell %s in module %s (attribute %s is set).\n",
- cell->name.c_str(), module->name.c_str(), attr.first.c_str());
+ log("Not mapping memory %s in module %s (attribute %s is set).\n",
+ mem.memid.c_str(), module->name.c_str(), attr.first.c_str());
return;
}
@@ -138,11 +132,11 @@ struct MemoryMapWorker
}
if (!found) {
if (cell_attr.flags & RTLIL::CONST_FLAG_STRING) {
- log("Not mapping memory cell %s in module %s (attribute %s is set to \"%s\").\n",
- cell->name.c_str(), module->name.c_str(), attr.first.c_str(), cell_attr.decode_string().c_str());
+ log("Not mapping memory %s in module %s (attribute %s is set to \"%s\").\n",
+ mem.memid.c_str(), module->name.c_str(), attr.first.c_str(), cell_attr.decode_string().c_str());
} else {
- log("Not mapping memory cell %s in module %s (attribute %s is set to %d).\n",
- cell->name.c_str(), module->name.c_str(), attr.first.c_str(), cell_attr.as_int());
+ log("Not mapping memory %s in module %s (attribute %s is set to %d).\n",
+ mem.memid.c_str(), module->name.c_str(), attr.first.c_str(), cell_attr.as_int());
}
return;
}
@@ -150,161 +144,113 @@ struct MemoryMapWorker
}
// all write ports must share the same clock
- RTLIL::SigSpec clocks = cell->getPort(ID::WR_CLK);
- RTLIL::Const clocks_pol = cell->parameters[ID::WR_CLK_POLARITY];
- RTLIL::Const clocks_en = cell->parameters[ID::WR_CLK_ENABLE];
- clocks_pol.bits.resize(wr_ports);
- clocks_en.bits.resize(wr_ports);
RTLIL::SigSpec refclock;
- RTLIL::State refclock_pol = RTLIL::State::Sx;
- for (int i = 0; i < clocks.size(); i++) {
- RTLIL::SigSpec wr_en = cell->getPort(ID::WR_EN).extract(i * mem_width, mem_width);
- if (wr_en.is_fully_const() && !wr_en.as_bool()) {
+ bool refclock_pol = false;
+ for (int i = 0; i < GetSize(mem.wr_ports); i++) {
+ auto &port = mem.wr_ports[i];
+ if (port.en.is_fully_const() && !port.en.as_bool()) {
static_ports.insert(i);
continue;
}
- if (clocks_en.bits[i] != RTLIL::State::S1) {
- RTLIL::SigSpec wr_addr = cell->getPort(ID::WR_ADDR).extract(i*mem_abits, mem_abits);
- RTLIL::SigSpec wr_data = cell->getPort(ID::WR_DATA).extract(i*mem_width, mem_width);
- if (wr_addr.is_fully_const()) {
- // FIXME: Actually we should check for wr_en.is_fully_const() also and
- // create a $adff cell with this ports wr_en input as reset pin when wr_en
- // is not a simple static 1.
- static_cells_map[wr_addr.as_int() - mem_offset] = wr_data;
+ if (!port.clk_enable) {
+ 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;
}
- log("Not mapping memory cell %s in module %s (write port %d has no clock).\n",
- cell->name.c_str(), module->name.c_str(), i);
+ log("Not mapping memory %s in module %s (write port %d has no clock).\n",
+ mem.memid.c_str(), module->name.c_str(), i);
return;
}
if (refclock.size() == 0) {
- refclock = clocks.extract(i, 1);
- refclock_pol = clocks_pol.bits[i];
+ refclock = port.clk;
+ refclock_pol = port.clk_polarity;
}
- if (clocks.extract(i, 1) != refclock || clocks_pol.bits[i] != refclock_pol) {
- log("Not mapping memory cell %s in module %s (write clock %d is incompatible with other clocks).\n",
- cell->name.c_str(), module->name.c_str(), i);
+ if (port.clk != refclock || port.clk_polarity != refclock_pol) {
+ log("Not mapping memory %s in module %s (write clock %d is incompatible with other clocks).\n",
+ mem.memid.c_str(), module->name.c_str(), i);
return;
}
}
- log("Mapping memory cell %s in module %s:\n", cell->name.c_str(), module->name.c_str());
+ 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++)
+ 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(cell->name, "", i), ID($dff));
- c->parameters[ID::WIDTH] = cell->parameters[ID::WIDTH];
- if (clocks_pol.bits.size() > 0) {
- c->parameters[ID::CLK_POLARITY] = RTLIL::Const(clocks_pol.bits[0]);
- c->setPort(ID::CLK, clocks.extract(0, 1));
+ 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);
+ c->setPort(ID::CLK, refclock);
} else {
c->parameters[ID::CLK_POLARITY] = RTLIL::Const(RTLIL::State::S1);
c->setPort(ID::CLK, RTLIL::SigSpec(RTLIL::State::S0));
}
- RTLIL::Wire *w_in = module->addWire(genid(cell->name, "", 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]", cell->parameters[ID::MEMID].decode_string().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(cell->name, "", 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);
+ RTLIL::Wire *w_out = module->addWire(w_out_name, mem.width);
+ SigSpec w_init = init_data.extract(i*mem.width, mem.width);
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);
}
}
- log(" created %d $dff cells and %d static cells of width %d.\n", mem_size-count_static, count_static, mem_width);
+ log(" created %d $dff cells and %d static cells of width %d.\n", mem.size-count_static, count_static, mem.width);
int count_dff = 0, count_mux = 0, count_wrmux = 0;
- for (int i = 0; i < cell->parameters[ID::RD_PORTS].as_int(); i++)
+ for (int i = 0; i < GetSize(mem.rd_ports); i++)
{
- RTLIL::SigSpec rd_addr = cell->getPort(ID::RD_ADDR).extract(i*mem_abits, mem_abits);
-
- if (mem_offset)
- rd_addr = module->Sub(NEW_ID, rd_addr, SigSpec(mem_offset, GetSize(rd_addr)));
+ auto &port = mem.rd_ports[i];
+ if (mem.extract_rdff(i, &initvals))
+ count_dff++;
+ RTLIL::SigSpec rd_addr = port.addr;
+ rd_addr.extend_u0(abits, false);
std::vector<RTLIL::SigSpec> rd_signals;
- rd_signals.push_back(cell->getPort(ID::RD_DATA).extract(i*mem_width, mem_width));
-
- if (cell->parameters[ID::RD_CLK_ENABLE].bits[i] == RTLIL::State::S1)
- {
- RTLIL::Cell *dff_cell = nullptr;
-
- if (cell->parameters[ID::RD_TRANSPARENT].bits[i] == RTLIL::State::S1)
- {
- dff_cell = module->addCell(genid(cell->name, "$rdreg", i), ID($dff));
- dff_cell->parameters[ID::WIDTH] = RTLIL::Const(mem_abits);
- dff_cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(cell->parameters[ID::RD_CLK_POLARITY].bits[i]);
- dff_cell->setPort(ID::CLK, cell->getPort(ID::RD_CLK).extract(i, 1));
- dff_cell->setPort(ID::D, rd_addr);
- count_dff++;
-
- RTLIL::Wire *w = module->addWire(genid(cell->name, "$rdreg", i, "$q"), mem_abits);
+ rd_signals.push_back(port.data);
- dff_cell->setPort(ID::Q, RTLIL::SigSpec(w));
- rd_addr = RTLIL::SigSpec(w);
- }
- else
- {
- dff_cell = module->addCell(genid(cell->name, "$rdreg", i), ID($dff));
- dff_cell->parameters[ID::WIDTH] = cell->parameters[ID::WIDTH];
- dff_cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(cell->parameters[ID::RD_CLK_POLARITY].bits[i]);
- dff_cell->setPort(ID::CLK, cell->getPort(ID::RD_CLK).extract(i, 1));
- dff_cell->setPort(ID::Q, rd_signals.back());
- count_dff++;
-
- RTLIL::Wire *w = module->addWire(genid(cell->name, "$rdreg", i, "$d"), mem_width);
-
- rd_signals.clear();
- rd_signals.push_back(RTLIL::SigSpec(w));
- dff_cell->setPort(ID::D, rd_signals.back());
- }
-
- SigBit en_bit = cell->getPort(ID::RD_EN).extract(i);
- if (en_bit != State::S1) {
- SigSpec new_d = module->Mux(genid(cell->name, "$rdenmux", i),
- dff_cell->getPort(ID::Q), dff_cell->getPort(ID::D), en_bit);
- dff_cell->setPort(ID::D, new_d);
- }
- }
-
- for (int j = 0; j < mem_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(cell->name, "$rdmux", i, "", j, "", k), ID($mux));
- c->parameters[ID::WIDTH] = cell->parameters[ID::WIDTH];
+ RTLIL::Cell *c = module->addCell(genid(mem.memid, "$rdmux", i, "", j, "", k), ID($mux));
+ c->parameters[ID::WIDTH] = GetSize(port.data);
c->setPort(ID::Y, rd_signals[k]);
- c->setPort(ID::S, rd_addr.extract(mem_abits-j-1, 1));
+ c->setPort(ID::S, rd_addr.extract(abits-j-1, 1));
count_mux++;
- c->setPort(ID::A, module->addWire(genid(cell->name, "$rdmux", i, "", j, "", k, "$a"), mem_width));
- c->setPort(ID::B, module->addWire(genid(cell->name, "$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));
@@ -313,38 +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++)
+ 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 < cell->parameters[ID::WR_PORTS].as_int(); j++)
+ for (int j = 0; j < GetSize(mem.wr_ports); j++)
{
- RTLIL::SigSpec wr_addr = cell->getPort(ID::WR_ADDR).extract(j*mem_abits, mem_abits);
- RTLIL::SigSpec wr_data = cell->getPort(ID::WR_DATA).extract(j*mem_width, mem_width);
- RTLIL::SigSpec wr_en = cell->getPort(ID::WR_EN).extract(j*mem_width, mem_width);
-
- if (mem_offset)
- wr_addr = module->Sub(NEW_ID, wr_addr, SigSpec(mem_offset, GetSize(wr_addr)));
+ auto &port = mem.wr_ports[j];
+ 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, mem_abits));
+ int sub = addr & ((1 << port.wide_log2) - 1);
int wr_offset = 0;
- while (wr_offset < wr_en.size())
+ while (wr_offset < mem.width)
{
int wr_width = 1;
- RTLIL::SigSpec wr_bit = wr_en.extract(wr_offset, 1);
+ RTLIL::SigSpec wr_bit = port.en.extract(wr_offset + sub * mem.width, 1);
- while (wr_offset + wr_width < wr_en.size()) {
- RTLIL::SigSpec next_wr_bit = wr_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++;
@@ -354,7 +300,7 @@ struct MemoryMapWorker
if (wr_bit != State::S1)
{
- RTLIL::Cell *c = module->addCell(genid(cell->name, "$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);
@@ -363,17 +309,17 @@ struct MemoryMapWorker
c->setPort(ID::A, w);
c->setPort(ID::B, wr_bit);
- w = module->addWire(genid(cell->name, "$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(cell->name, "$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, wr_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(cell->name, "$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);
@@ -382,22 +328,18 @@ 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);
- module->remove(cell);
+ mem.remove();
}
void run()
{
- std::vector<RTLIL::Cell*> cells;
- for (auto cell : module->selected_cells())
- if (cell->type == ID($mem))
- cells.push_back(cell);
- for (auto cell : cells)
- handle_cell(cell);
+ for (auto &mem : Mem::get_selected_memories(module))
+ handle_memory(mem);
}
};
@@ -430,7 +372,7 @@ struct MemoryMapPass : public Pass {
bool attr_icase = false;
dict<RTLIL::IdString, std::vector<RTLIL::Const>> attributes;
- log_header(design, "Executing MEMORY_MAP pass (converting $mem cells to logic and flip-flops).\n");
+ log_header(design, "Executing MEMORY_MAP pass (converting memories to logic and flip-flops).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
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 07bbd9fe8..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
@@ -19,6 +19,7 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
+#include "kernel/mem.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -32,12 +33,12 @@ 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
{
- log_header(design, "Executing MEMORY_NORDFF pass (extracting $dff cells from $mem).\n");
+ log_header(design, "Executing MEMORY_NORDFF pass (extracting $dff cells from memories).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
@@ -50,70 +51,22 @@ struct MemoryNordffPass : public Pass {
extra_args(args, argidx, design);
for (auto module : design->selected_modules())
- for (auto cell : vector<Cell*>(module->selected_cells()))
{
- if (cell->type != ID($mem))
- continue;
-
- int rd_ports = cell->getParam(ID::RD_PORTS).as_int();
- int abits = cell->getParam(ID::ABITS).as_int();
- int width = cell->getParam(ID::WIDTH).as_int();
-
- SigSpec rd_addr = cell->getPort(ID::RD_ADDR);
- SigSpec rd_data = cell->getPort(ID::RD_DATA);
- SigSpec rd_clk = cell->getPort(ID::RD_CLK);
- SigSpec rd_en = cell->getPort(ID::RD_EN);
- Const rd_clk_enable = cell->getParam(ID::RD_CLK_ENABLE);
- Const rd_clk_polarity = cell->getParam(ID::RD_CLK_POLARITY);
-
- for (int i = 0; i < rd_ports; i++)
+ SigMap sigmap(module);
+ FfInitVals initvals(&sigmap, module);
+ for (auto &mem : Mem::get_selected_memories(module))
{
- bool clk_enable = rd_clk_enable[i] == State::S1;
-
- if (clk_enable)
- {
- bool clk_polarity = cell->getParam(ID::RD_CLK_POLARITY)[i] == State::S1;
- bool transparent = cell->getParam(ID::RD_TRANSPARENT)[i] == State::S1;
-
- SigSpec clk = cell->getPort(ID::RD_CLK)[i] ;
- SigSpec en = cell->getPort(ID::RD_EN)[i];
- Cell *c;
-
- if (transparent)
- {
- SigSpec sig_q = module->addWire(NEW_ID, abits);
- SigSpec sig_d = rd_addr.extract(abits * i, abits);
- rd_addr.replace(abits * i, sig_q);
- if (en != State::S1)
- sig_d = module->Mux(NEW_ID, sig_q, sig_d, en);
- c = module->addDff(NEW_ID, clk, sig_d, sig_q, clk_polarity);
- }
- else
- {
- SigSpec sig_d = module->addWire(NEW_ID, width);
- SigSpec sig_q = rd_data.extract(width * i, width);
- rd_data.replace(width *i, sig_d);
- if (en != State::S1)
- sig_d = module->Mux(NEW_ID, sig_q, sig_d, en);
- c = module->addDff(NEW_ID, clk, sig_d, sig_q, clk_polarity);
+ 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;
}
-
- log("Extracted %s FF from read port %d of %s.%s: %s\n", transparent ? "addr" : "data",
- i, log_id(module), log_id(cell), log_id(c));
}
- rd_en[i] = State::S1;
- rd_clk[i] = State::S0;
- rd_clk_enable[i] = State::S0;
- rd_clk_polarity[i] = State::S1;
+ if (changed)
+ mem.emit();
}
-
- cell->setPort(ID::RD_ADDR, rd_addr);
- cell->setPort(ID::RD_DATA, rd_data);
- cell->setPort(ID::RD_CLK, rd_clk);
- cell->setPort(ID::RD_EN, rd_en);
- cell->setParam(ID::RD_CLK_ENABLE, rd_clk_enable);
- cell->setParam(ID::RD_CLK_POLARITY, rd_clk_polarity);
}
}
} 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 d04d4ba7a..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
@@ -17,114 +17,12 @@
*
*/
-#include "kernel/register.h"
-#include "kernel/log.h"
-#include <sstream>
-#include <algorithm>
-#include <stdlib.h>
+#include "kernel/yosys.h"
+#include "kernel/mem.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-void handle_memory(RTLIL::Module *module, RTLIL::Cell *memory)
-{
- log("Creating $memrd and $memwr for memory `%s' in module `%s':\n",
- memory->name.c_str(), module->name.c_str());
-
- RTLIL::IdString mem_name = RTLIL::escape_id(memory->parameters.at(ID::MEMID).decode_string());
-
- while (module->memories.count(mem_name) != 0)
- mem_name = mem_name.str() + stringf("_%d", autoidx++);
-
- RTLIL::Memory *mem = new RTLIL::Memory;
- mem->name = mem_name;
- mem->width = memory->parameters.at(ID::WIDTH).as_int();
- mem->start_offset = memory->parameters.at(ID::OFFSET).as_int();
- mem->size = memory->parameters.at(ID::SIZE).as_int();
- module->memories[mem_name] = mem;
-
- int abits = memory->parameters.at(ID::ABITS).as_int();
- int num_rd_ports = memory->parameters.at(ID::RD_PORTS).as_int();
- int num_wr_ports = memory->parameters.at(ID::WR_PORTS).as_int();
-
- for (int i = 0; i < num_rd_ports; i++)
- {
- RTLIL::Cell *cell = module->addCell(NEW_ID, ID($memrd));
- cell->parameters[ID::MEMID] = mem_name.str();
- cell->parameters[ID::ABITS] = memory->parameters.at(ID::ABITS);
- cell->parameters[ID::WIDTH] = memory->parameters.at(ID::WIDTH);
- cell->parameters[ID::CLK_ENABLE] = RTLIL::SigSpec(memory->parameters.at(ID::RD_CLK_ENABLE)).extract(i, 1).as_const();
- cell->parameters[ID::CLK_POLARITY] = RTLIL::SigSpec(memory->parameters.at(ID::RD_CLK_POLARITY)).extract(i, 1).as_const();
- cell->parameters[ID::TRANSPARENT] = RTLIL::SigSpec(memory->parameters.at(ID::RD_TRANSPARENT)).extract(i, 1).as_const();
- cell->setPort(ID::CLK, memory->getPort(ID::RD_CLK).extract(i, 1));
- cell->setPort(ID::EN, memory->getPort(ID::RD_EN).extract(i, 1));
- cell->setPort(ID::ADDR, memory->getPort(ID::RD_ADDR).extract(i*abits, abits));
- cell->setPort(ID::DATA, memory->getPort(ID::RD_DATA).extract(i*mem->width, mem->width));
- }
-
- for (int i = 0; i < num_wr_ports; i++)
- {
- RTLIL::Cell *cell = module->addCell(NEW_ID, ID($memwr));
- cell->parameters[ID::MEMID] = mem_name.str();
- cell->parameters[ID::ABITS] = memory->parameters.at(ID::ABITS);
- cell->parameters[ID::WIDTH] = memory->parameters.at(ID::WIDTH);
- cell->parameters[ID::CLK_ENABLE] = RTLIL::SigSpec(memory->parameters.at(ID::WR_CLK_ENABLE)).extract(i, 1).as_const();
- cell->parameters[ID::CLK_POLARITY] = RTLIL::SigSpec(memory->parameters.at(ID::WR_CLK_POLARITY)).extract(i, 1).as_const();
- cell->parameters[ID::PRIORITY] = i;
- cell->setPort(ID::CLK, memory->getPort(ID::WR_CLK).extract(i, 1));
- cell->setPort(ID::EN, memory->getPort(ID::WR_EN).extract(i*mem->width, mem->width));
- cell->setPort(ID::ADDR, memory->getPort(ID::WR_ADDR).extract(i*abits, abits));
- cell->setPort(ID::DATA, memory->getPort(ID::WR_DATA).extract(i*mem->width, mem->width));
- }
-
- Const initval = memory->parameters.at(ID::INIT);
- RTLIL::Cell *last_init_cell = nullptr;
- SigSpec last_init_data;
- int last_init_addr=0;
-
- for (int i = 0; i < GetSize(initval) && i/mem->width < (1 << abits); i += mem->width) {
- Const val = initval.extract(i, mem->width, State::Sx);
- for (auto bit : val.bits)
- if (bit != State::Sx)
- goto found_non_undef_initval;
- continue;
- found_non_undef_initval:
- if (last_init_cell && last_init_addr+1 == i/mem->width) {
- last_init_cell->parameters[ID::WORDS] = last_init_cell->parameters[ID::WORDS].as_int() + 1;
- last_init_data.append(val);
- last_init_addr++;
- } else {
- if (last_init_cell)
- last_init_cell->setPort(ID::DATA, last_init_data);
- RTLIL::Cell *cell = module->addCell(NEW_ID, ID($meminit));
- cell->parameters[ID::MEMID] = mem_name.str();
- cell->parameters[ID::ABITS] = memory->parameters.at(ID::ABITS);
- cell->parameters[ID::WIDTH] = memory->parameters.at(ID::WIDTH);
- cell->parameters[ID::WORDS] = 1;
- cell->parameters[ID::PRIORITY] = i/mem->width;
- cell->setPort(ID::ADDR, SigSpec(i/mem->width, abits));
- last_init_cell = cell;
- last_init_addr = i/mem->width;
- last_init_data = val;
- }
- }
-
- if (last_init_cell)
- last_init_cell->setPort(ID::DATA, last_init_data);
-
- module->remove(memory);
-}
-
-void handle_module(RTLIL::Design *design, RTLIL::Module *module)
-{
- std::vector<RTLIL::IdString> memcells;
- for (auto cell : module->cells())
- if (cell->type == ID($mem) && design->selected(module, cell))
- memcells.push_back(cell->name);
- for (auto &it : memcells)
- handle_memory(module, module->cell(it));
-}
-
struct MemoryUnpackPass : public Pass {
MemoryUnpackPass() : Pass("memory_unpack", "unpack multi-port memory cells") { }
void help() override
@@ -140,8 +38,14 @@ struct MemoryUnpackPass : public Pass {
void execute(std::vector<std::string> args, RTLIL::Design *design) override {
log_header(design, "Executing MEMORY_UNPACK pass (generating $memrd/$memwr cells form $mem cells).\n");
extra_args(args, 1, design);
- for (auto module : design->selected_modules())
- handle_module(design, module);
+ for (auto module : design->selected_modules()) {
+ for (auto &mem : Mem::get_selected_memories(module)) {
+ if (mem.packed) {
+ mem.packed = false;
+ mem.emit();
+ }
+ }
+ }
}
} MemoryUnpackPass;
diff --git a/passes/opt/Makefile.inc b/passes/opt/Makefile.inc
index 3133927bb..4e52ad8da 100644
--- a/passes/opt/Makefile.inc
+++ b/passes/opt/Makefile.inc
@@ -2,9 +2,12 @@
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_rmdff.o
+OBJS += passes/opt/opt_dff.o
OBJS += passes/opt/opt_share.o
OBJS += passes/opt/opt_clean.o
OBJS += passes/opt/opt_expr.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 8be94e345..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
@@ -37,7 +37,7 @@ struct OptPass : public Pass {
log("a series of trivial optimizations and cleanups. This pass executes the other\n");
log("passes in the following order:\n");
log("\n");
- log(" opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]\n");
+ log(" opt_expr [-mux_undef] [-mux_bool] [-undriven] [-noclkinv] [-fine] [-full] [-keepdc]\n");
log(" opt_merge [-share_all] -nomux\n");
log("\n");
log(" do\n");
@@ -45,19 +45,19 @@ struct OptPass : public Pass {
log(" opt_reduce [-fine] [-full]\n");
log(" opt_merge [-share_all]\n");
log(" opt_share (-full only)\n");
- log(" opt_rmdff [-keepdc] [-sat] (except when called with -noff)\n");
+ log(" opt_dff [-nodffe] [-nosdff] [-keepdc] [-sat] (except when called with -noff)\n");
log(" opt_clean [-purge]\n");
- log(" opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]\n");
+ log(" opt_expr [-mux_undef] [-mux_bool] [-undriven] [-noclkinv] [-fine] [-full] [-keepdc]\n");
log(" while <changed design>\n");
log("\n");
log("When called with -fast the following script is used instead:\n");
log("\n");
log(" do\n");
- log(" opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]\n");
+ log(" opt_expr [-mux_undef] [-mux_bool] [-undriven] [-noclkinv] [-fine] [-full] [-keepdc]\n");
log(" opt_merge [-share_all]\n");
- log(" opt_rmdff [-keepdc] [-sat] (except when called with -noff)\n");
+ log(" opt_dff [-nodffe] [-nosdff] [-keepdc] [-sat] (except when called with -noff)\n");
log(" opt_clean [-purge]\n");
- log(" while <changed design in opt_rmdff>\n");
+ log(" while <changed design in opt_dff>\n");
log("\n");
log("Note: Options in square brackets (such as [-keepdc]) are passed through to\n");
log("the opt_* commands when given to 'opt'.\n");
@@ -70,7 +70,7 @@ struct OptPass : public Pass {
std::string opt_expr_args;
std::string opt_reduce_args;
std::string opt_merge_args;
- std::string opt_rmdff_args;
+ std::string opt_dff_args;
bool opt_share = false;
bool fast_mode = false;
bool noff_mode = false;
@@ -96,8 +96,8 @@ struct OptPass : public Pass {
opt_expr_args += " -undriven";
continue;
}
- if (args[argidx] == "-clkinv") {
- opt_expr_args += " -clkinv";
+ if (args[argidx] == "-noclkinv") {
+ opt_expr_args += " -noclkinv";
continue;
}
if (args[argidx] == "-fine") {
@@ -113,11 +113,19 @@ struct OptPass : public Pass {
}
if (args[argidx] == "-keepdc") {
opt_expr_args += " -keepdc";
- opt_rmdff_args += " -keepdc";
+ opt_dff_args += " -keepdc";
+ continue;
+ }
+ if (args[argidx] == "-nodffe") {
+ opt_dff_args += " -nodffe";
+ continue;
+ }
+ if (args[argidx] == "-nosdff") {
+ opt_dff_args += " -nosdff";
continue;
}
if (args[argidx] == "-sat") {
- opt_rmdff_args += " -sat";
+ opt_dff_args += " -sat";
continue;
}
if (args[argidx] == "-share_all") {
@@ -143,7 +151,7 @@ struct OptPass : public Pass {
Pass::call(design, "opt_merge" + opt_merge_args);
design->scratchpad_unset("opt.did_something");
if (!noff_mode)
- Pass::call(design, "opt_rmdff" + opt_rmdff_args);
+ Pass::call(design, "opt_dff" + opt_dff_args);
if (design->scratchpad_get_bool("opt.did_something") == false)
break;
Pass::call(design, "opt_clean" + opt_clean_args);
@@ -163,7 +171,7 @@ struct OptPass : public Pass {
if (opt_share)
Pass::call(design, "opt_share");
if (!noff_mode)
- Pass::call(design, "opt_rmdff" + opt_rmdff_args);
+ Pass::call(design, "opt_dff" + opt_dff_args);
Pass::call(design, "opt_clean" + opt_clean_args);
Pass::call(design, "opt_expr" + opt_expr_args);
if (design->scratchpad_get_bool("opt.did_something") == false)
diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc
index 44de60b48..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>
@@ -59,6 +60,11 @@ struct keep_cache_t
found_keep = true;
break;
}
+ for (auto wire : module->wires())
+ if (wire->get_bool_attribute(ID::keep)) {
+ found_keep = true;
+ break;
+ }
cache[module] = found_keep;
}
@@ -67,7 +73,7 @@ struct keep_cache_t
bool query(Cell *cell, bool ignore_specify = false)
{
- if (cell->type.in(ID($memwr), ID($meminit), ID($assert), ID($assume), ID($live), ID($fair), ID($cover)))
+ if (cell->type.in(ID($assert), ID($assume), ID($live), ID($fair), ID($cover)))
return true;
if (!ignore_specify && cell->type.in(ID($specify2), ID($specify3), ID($specrule)))
@@ -90,10 +96,13 @@ int count_rm_cells, count_rm_wires;
void rmunused_module_cells(Module *module, bool verbose)
{
SigMap sigmap(module);
+ dict<IdString, pool<Cell*>> mem2cells;
+ pool<IdString> mem_unused;
pool<Cell*> queue, unused;
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_) {
@@ -103,6 +112,17 @@ void rmunused_module_cells(Module *module, bool verbose)
}
}
+ for (auto &it : module->memories) {
+ mem_unused.insert(it.first);
+ }
+
+ for (Cell *cell : module->cells()) {
+ 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);
+ }
+ }
+
for (auto &it : module->cells_) {
Cell *cell = it.second;
for (auto &it2 : cell->connections()) {
@@ -140,17 +160,33 @@ void rmunused_module_cells(Module *module, bool verbose)
while (!queue.empty())
{
pool<SigBit> bits;
- for (auto cell : queue)
- for (auto &it : cell->connections())
- if (!ct_all.cell_known(cell->type) || ct_all.cell_input(cell->type, it.first))
- for (auto bit : sigmap(it.second))
- bits.insert(bit);
+ pool<IdString> mems;
+ for (auto cell : queue) {
+ for (auto &it : cell->connections())
+ if (!ct_all.cell_known(cell->type) || ct_all.cell_input(cell->type, it.first))
+ for (auto bit : sigmap(it.second))
+ bits.insert(bit);
+
+ 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);
+ mems.insert(mem_id);
+ }
+ }
+ }
queue.clear();
+
for (auto bit : bits)
for (auto c : wire2driver[bit])
if (unused.count(c))
queue.insert(c), unused.erase(c);
+
+ for (auto mem : mems)
+ for (auto c : mem2cells[mem])
+ if (unused.count(c))
+ queue.insert(c), unused.erase(c);
}
unused.sort(RTLIL::sort_by_name_id<RTLIL::Cell>());
@@ -159,10 +195,20 @@ 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++;
}
+ for (auto it : mem_unused)
+ {
+ if (verbose)
+ log_debug(" removing unused memory `%s'.\n", it.c_str());
+ delete module->memories.at(it);
+ module->memories.erase(it);
+ }
+
for (auto &it : module->cells_) {
Cell *cell = it.second;
for (auto &it2 : cell->connections()) {
@@ -202,7 +248,7 @@ bool compare_signals(RTLIL::SigBit &s1, RTLIL::SigBit &s2, SigPool &regs, SigPoo
if ((w1->port_input && w1->port_output) != (w2->port_input && w2->port_output))
return !(w2->port_input && w2->port_output);
- if (w1->name[0] == '\\' && w2->name[0] == '\\') {
+ if (w1->name.isPublic() && w2->name.isPublic()) {
if (regs.check(s1) != regs.check(s2))
return regs.check(s2);
if (direct_wires.count(w1) != direct_wires.count(w2))
@@ -215,7 +261,7 @@ bool compare_signals(RTLIL::SigBit &s1, RTLIL::SigBit &s2, SigPool &regs, SigPoo
return w2->port_output;
if (w1->name[0] != w2->name[0])
- return w2->name[0] == '\\';
+ return w2->name.isPublic();
int attrs1 = count_nontrivial_wire_attrs(w1);
int attrs2 = count_nontrivial_wire_attrs(w2);
@@ -293,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) {
@@ -308,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
new file mode 100644
index 000000000..73d674c8d
--- /dev/null
+++ b/passes/opt/opt_dff.cc
@@ -0,0 +1,918 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * 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
+ * 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/log.h"
+#include "kernel/register.h"
+#include "kernel/rtlil.h"
+#include "kernel/qcsat.h"
+#include "kernel/modtools.h"
+#include "kernel/sigtools.h"
+#include "kernel/ffinit.h"
+#include "kernel/ff.h"
+#include "passes/techmap/simplemap.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct OptDffOptions
+{
+ bool nosdff;
+ bool nodffe;
+ bool simple_dffe;
+ bool sat;
+ bool keepdc;
+};
+
+struct OptDffWorker
+{
+ const OptDffOptions &opt;
+
+ Module *module;
+ typedef std::pair<RTLIL::Cell*, int> cell_int_t;
+ SigMap sigmap;
+ FfInitVals initvals;
+ dict<SigBit, int> bitusers;
+ dict<SigBit, cell_int_t> bit2mux;
+
+ 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;
+
+ // Used as a queue.
+ std::vector<Cell *> dff_cells;
+
+ 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
+
+ for (auto wire : module->wires())
+ {
+ if (wire->port_output)
+ for (auto bit : sigmap(wire))
+ bitusers[bit]++;
+ }
+
+ for (auto cell : module->cells()) {
+ if (cell->type.in(ID($mux), ID($pmux), ID($_MUX_))) {
+ RTLIL::SigSpec sig_y = sigmap(cell->getPort(ID::Y));
+ for (int i = 0; i < GetSize(sig_y); i++)
+ bit2mux[sig_y[i]] = cell_int_t(cell, i);
+ }
+
+ for (auto conn : cell->connections()) {
+ bool is_output = cell->output(conn.first);
+ if (!is_output || !cell->known()) {
+ for (auto bit : sigmap(conn.second))
+ bitusers[bit]++;
+ }
+ }
+
+ if (module->design->selected(module, cell) && RTLIL::builtin_ff_cell_types().count(cell->type))
+ dff_cells.push_back(cell);
+ }
+
+ }
+
+ State combine_const(State a, State b) {
+ if (a == State::Sx && !opt.keepdc)
+ return b;
+ if (b == State::Sx && !opt.keepdc)
+ return a;
+ if (a == b)
+ return a;
+ return State::Sm;
+ }
+
+ patterns_t find_muxtree_feedback_patterns(RTLIL::SigBit d, RTLIL::SigBit q, pattern_t path)
+ {
+ patterns_t ret;
+
+ if (d == q) {
+ ret.insert(path);
+ return ret;
+ }
+
+ if (bit2mux.count(d) == 0 || bitusers[d] > 1)
+ return ret;
+
+ cell_int_t mbit = bit2mux.at(d);
+ RTLIL::SigSpec sig_a = sigmap(mbit.first->getPort(ID::A));
+ RTLIL::SigSpec sig_b = sigmap(mbit.first->getPort(ID::B));
+ RTLIL::SigSpec sig_s = sigmap(mbit.first->getPort(ID::S));
+ int width = GetSize(sig_a), index = mbit.second;
+
+ for (int i = 0; i < GetSize(sig_s); i++)
+ if (path.count(sig_s[i]) && path.at(sig_s[i]))
+ {
+ ret = find_muxtree_feedback_patterns(sig_b[i*width + index], q, path);
+
+ if (sig_b[i*width + index] == q) {
+ RTLIL::SigSpec s = mbit.first->getPort(ID::B);
+ s[i*width + index] = RTLIL::Sx;
+ mbit.first->setPort(ID::B, s);
+ }
+
+ return ret;
+ }
+
+ pattern_t path_else = path;
+
+ for (int i = 0; i < GetSize(sig_s); i++)
+ {
+ if (path.count(sig_s[i]))
+ continue;
+
+ pattern_t path_this = path;
+ path_else[sig_s[i]] = false;
+ path_this[sig_s[i]] = true;
+
+ for (auto &pat : find_muxtree_feedback_patterns(sig_b[i*width + index], q, path_this))
+ ret.insert(pat);
+
+ if (sig_b[i*width + index] == q) {
+ RTLIL::SigSpec s = mbit.first->getPort(ID::B);
+ s[i*width + index] = RTLIL::Sx;
+ mbit.first->setPort(ID::B, s);
+ }
+ }
+
+ for (auto &pat : find_muxtree_feedback_patterns(sig_a[index], q, path_else))
+ ret.insert(pat);
+
+ if (sig_a[index] == q) {
+ RTLIL::SigSpec s = mbit.first->getPort(ID::A);
+ s[index] = RTLIL::Sx;
+ mbit.first->setPort(ID::A, s);
+ }
+
+ return ret;
+ }
+
+ void simplify_patterns(patterns_t&)
+ {
+ // TBD
+ }
+
+ ctrl_t make_patterns_logic(const patterns_t &patterns, const ctrls_t &ctrls, bool make_gates)
+ {
+ if (patterns.empty() && GetSize(ctrls) == 1) {
+ return *ctrls.begin();
+ }
+
+ RTLIL::SigSpec or_input;
+
+ for (auto pat : patterns)
+ {
+ RTLIL::SigSpec s1, s2;
+ for (auto it : pat) {
+ s1.append(it.first);
+ s2.append(it.second);
+ }
+
+ RTLIL::SigSpec y = module->addWire(NEW_ID);
+ RTLIL::Cell *c = module->addNe(NEW_ID, s1, s2, y);
+
+ if (make_gates) {
+ simplemap(module, c);
+ module->remove(c);
+ }
+
+ or_input.append(y);
+ }
+ for (auto item : ctrls) {
+ if (item.second)
+ or_input.append(item.first);
+ else if (make_gates)
+ or_input.append(module->NotGate(NEW_ID, item.first));
+ else
+ or_input.append(module->Not(NEW_ID, item.first));
+ }
+
+ if (GetSize(or_input) == 0)
+ return ctrl_t(State::S1, true);
+
+ if (GetSize(or_input) == 1)
+ return ctrl_t(or_input, true);
+
+ RTLIL::SigSpec y = module->addWire(NEW_ID);
+ RTLIL::Cell *c = module->addReduceAnd(NEW_ID, or_input, y);
+
+ if (make_gates) {
+ simplemap(module, c);
+ module->remove(c);
+ }
+
+ return ctrl_t(y, true);
+ }
+
+ ctrl_t combine_resets(const ctrls_t &ctrls, bool make_gates)
+ {
+ if (GetSize(ctrls) == 1) {
+ return *ctrls.begin();
+ }
+
+ RTLIL::SigSpec or_input;
+
+ bool final_pol = false;
+ for (auto item : ctrls) {
+ if (item.second)
+ final_pol = true;
+ }
+
+ for (auto item : ctrls) {
+ if (item.second == final_pol)
+ or_input.append(item.first);
+ else if (make_gates)
+ or_input.append(module->NotGate(NEW_ID, item.first));
+ else
+ or_input.append(module->Not(NEW_ID, item.first));
+ }
+
+ RTLIL::SigSpec y = module->addWire(NEW_ID);
+ RTLIL::Cell *c = final_pol ? module->addReduceOr(NEW_ID, or_input, y) : module->addReduceAnd(NEW_ID, or_input, y);
+
+ if (make_gates) {
+ simplemap(module, c);
+ module->remove(c);
+ }
+
+ return ctrl_t(y, final_pol);
+ }
+
+ bool run() {
+ // We have all the information we need, and the list of FFs to process as well. Do it.
+ bool did_something = false;
+ while (!dff_cells.empty()) {
+ Cell *cell = dff_cells.back();
+ dff_cells.pop_back();
+ // Break down the FF into pieces.
+ FfData ff(&initvals, cell);
+ bool changed = false;
+
+ if (!ff.width) {
+ ff.remove();
+ did_something = true;
+ continue;
+ }
+
+ if (ff.has_sr) {
+ bool sr_removed = false;
+ std::vector<int> keep_bits;
+ // Check for always-active S/R bits.
+ for (int i = 0; i < ff.width; i++) {
+ if (ff.sig_clr[i] == (ff.pol_clr ? State::S1 : State::S0) || (!opt.keepdc && ff.sig_clr[i] == State::Sx)) {
+ // Always-active clear — connect Q bit to 0.
+ initvals.remove_init(ff.sig_q[i]);
+ module->connect(ff.sig_q[i], State::S0);
+ log("Handling always-active CLR at position %d on %s (%s) from module %s (changing to const driver).\n",
+ i, log_id(cell), log_id(cell->type), log_id(module));
+ sr_removed = true;
+ } else if (ff.sig_set[i] == (ff.pol_set ? State::S1 : State::S0) || (!opt.keepdc && ff.sig_set[i] == State::Sx)) {
+ // Always-active set — connect Q bit to 1 if clear inactive, 0 if reset active.
+ initvals.remove_init(ff.sig_q[i]);
+ 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_clr[i], ff.sig_q[i]);
+ } else {
+ 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));
+ sr_removed = true;
+ } else {
+ keep_bits.push_back(i);
+ }
+ }
+ if (sr_removed) {
+ if (keep_bits.empty()) {
+ module->remove(cell);
+ did_something = true;
+ continue;
+ }
+ ff = ff.slice(keep_bits);
+ ff.cell = cell;
+ changed = true;
+ }
+
+ if (ff.pol_clr ? ff.sig_clr.is_fully_zero() : ff.sig_clr.is_fully_ones()) {
+ // CLR is useless, try to kill it.
+ bool failed = false;
+ for (int i = 0; i < ff.width; i++)
+ if (ff.sig_set[i] != ff.sig_set[0])
+ failed = true;
+ if (!failed) {
+ log("Removing never-active CLR on %s (%s) from module %s.\n",
+ log_id(cell), log_id(cell->type), log_id(module));
+ ff.has_sr = false;
+ ff.has_arst = true;
+ ff.pol_arst = ff.pol_set;
+ ff.sig_arst = ff.sig_set[0];
+ ff.val_arst = Const(State::S1, ff.width);
+ changed = true;
+ }
+ } else if (ff.pol_set ? ff.sig_set.is_fully_zero() : ff.sig_set.is_fully_ones()) {
+ // SET is useless, try to kill it.
+ bool failed = false;
+ for (int i = 0; i < ff.width; i++)
+ if (ff.sig_clr[i] != ff.sig_clr[0])
+ failed = true;
+ if (!failed) {
+ log("Removing never-active SET on %s (%s) from module %s.\n",
+ log_id(cell), log_id(cell->type), log_id(module));
+ ff.has_sr = false;
+ ff.has_arst = true;
+ ff.pol_arst = ff.pol_clr;
+ ff.sig_arst = ff.sig_clr[0];
+ ff.val_arst = Const(State::S0, ff.width);
+ changed = true;
+ }
+ } else if (ff.pol_clr == ff.pol_set) {
+ // Try a more complex conversion to plain async reset.
+ State val_neutral = ff.pol_set ? State::S0 : State::S1;
+ Const val_arst;
+ SigSpec sig_arst;
+ if (ff.sig_clr[0] == val_neutral)
+ sig_arst = ff.sig_set[0];
+ else
+ sig_arst = ff.sig_clr[0];
+ bool failed = false;
+ for (int i = 0; i < ff.width; i++) {
+ if (ff.sig_clr[i] == sig_arst && ff.sig_set[i] == val_neutral)
+ val_arst.bits.push_back(State::S0);
+ else if (ff.sig_set[i] == sig_arst && ff.sig_clr[i] == val_neutral)
+ val_arst.bits.push_back(State::S1);
+ else
+ failed = true;
+ }
+ if (!failed) {
+ log("Converting CLR/SET to ARST on %s (%s) from module %s.\n",
+ log_id(cell), log_id(cell->type), log_id(module));
+ ff.has_sr = false;
+ ff.has_arst = true;
+ ff.val_arst = val_arst;
+ ff.sig_arst = sig_arst;
+ ff.pol_arst = ff.pol_clr;
+ changed = true;
+ }
+ }
+ }
+
+ 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.
+ log("Removing never-active ARST on %s (%s) from module %s.\n",
+ log_id(cell), log_id(cell->type), log_id(module));
+ ff.has_arst = false;
+ changed = true;
+ } else if (ff.sig_arst == (ff.pol_arst ? State::S1 : State::S0) || (!opt.keepdc && ff.sig_arst == State::Sx)) {
+ // 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));
+ ff.remove();
+ module->connect(ff.sig_q, ff.val_arst);
+ did_something = true;
+ continue;
+ }
+ }
+
+ if (ff.has_srst) {
+ if (ff.sig_srst == (ff.pol_srst ? State::S0 : State::S1)) {
+ // Always-inactive reset — remove.
+ log("Removing never-active SRST on %s (%s) from module %s.\n",
+ log_id(cell), log_id(cell->type), log_id(module));
+ ff.has_srst = false;
+ changed = true;
+ } else if (ff.sig_srst == (ff.pol_srst ? State::S1 : State::S0) || (!opt.keepdc && ff.sig_srst == State::Sx)) {
+ // Always-active sync reset — connect to D instead.
+ log("Handling always-active SRST on %s (%s) from module %s (changing to const D).\n",
+ log_id(cell), log_id(cell->type), log_id(module));
+ ff.has_srst = false;
+ if (!ff.ce_over_srst)
+ ff.has_ce = false;
+ ff.sig_d = ff.val_srst;
+ changed = true;
+ }
+ }
+
+ 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_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_ce = ff.pol_srst;
+ ff.sig_ce = ff.sig_srst;
+ ff.has_srst = false;
+ 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 D latch, SR latch, or a const driver).
+ ff.has_ce = ff.has_clk = ff.has_srst = false;
+ changed = true;
+ }
+ } 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 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_ce = ff.has_clk = ff.has_srst = false;
+ changed = true;
+ }
+ }
+
+ 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_ce && ff.ce_over_srst) {
+ if (!ff.pol_ce) {
+ if (ff.is_fine)
+ ff.sig_ce = module->NotGate(NEW_ID, ff.sig_ce);
+ else
+ ff.sig_ce = module->Not(NEW_ID, ff.sig_ce);
+ }
+ if (!ff.pol_srst) {
+ if (ff.is_fine)
+ ff.sig_srst = module->NotGate(NEW_ID, ff.sig_srst);
+ else
+ ff.sig_srst = module->Not(NEW_ID, ff.sig_srst);
+ }
+ if (ff.is_fine)
+ ff.sig_ce = module->AndGate(NEW_ID, ff.sig_ce, ff.sig_srst);
+ else
+ ff.sig_ce = module->And(NEW_ID, ff.sig_ce, ff.sig_srst);
+ ff.pol_ce = true;
+ } else {
+ ff.pol_ce = ff.pol_srst;
+ ff.sig_ce = ff.sig_srst;
+ }
+ ff.has_ce = true;
+ ff.has_srst = false;
+ 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_clk = ff.has_ce = false;
+ changed = true;
+ }
+ }
+
+ 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_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;
+ Const val_srst;
+
+ for (int i = 0 ; i < ff.width; i++) {
+ ctrls_t resets;
+ State reset_val = State::Sx;
+ if (ff.has_srst)
+ reset_val = ff.val_srst[i];
+ while (bit2mux.count(ff.sig_d[i]) && bitusers[ff.sig_d[i]] == 1) {
+ cell_int_t mbit = bit2mux.at(ff.sig_d[i]);
+ if (GetSize(mbit.first->getPort(ID::S)) != 1)
+ break;
+ SigBit s = mbit.first->getPort(ID::S);
+ SigBit a = mbit.first->getPort(ID::A)[mbit.second];
+ SigBit b = mbit.first->getPort(ID::B)[mbit.second];
+ // Workaround for funny memory WE pattern.
+ if ((a == State::S0 || a == State::S1) && (b == State::S0 || b == State::S1))
+ break;
+ if ((b == State::S0 || b == State::S1) && (b == reset_val || reset_val == State::Sx)) {
+ // This is better handled by CE pattern.
+ if (a == ff.sig_q[i])
+ break;
+ reset_val = b.data;
+ resets.insert(ctrl_t(s, true));
+ ff.sig_d[i] = a;
+ } else if ((a == State::S0 || a == State::S1) && (a == reset_val || reset_val == State::Sx)) {
+ // This is better handled by CE pattern.
+ if (b == ff.sig_q[i])
+ break;
+ reset_val = a.data;
+ resets.insert(ctrl_t(s, false));
+ ff.sig_d[i] = b;
+ } else {
+ break;
+ }
+ }
+
+ if (!resets.empty()) {
+ if (ff.has_srst)
+ resets.insert(ctrl_t(ff.sig_srst, ff.pol_srst));
+ groups[resets].push_back(i);
+ } else
+ remaining_indices.push_back(i);
+ val_srst.bits.push_back(reset_val);
+ }
+
+ for (auto &it : groups) {
+ FfData new_ff = ff.slice(it.second);
+ new_ff.val_srst = Const();
+ for (int i = 0; i < new_ff.width; i++) {
+ int j = it.second[i];
+ new_ff.val_srst.bits.push_back(val_srst[j]);
+ }
+ ctrl_t srst = combine_resets(it.first, ff.is_fine);
+
+ new_ff.has_srst = true;
+ new_ff.sig_srst = srst.first;
+ new_ff.pol_srst = srst.second;
+ if (new_ff.has_ce)
+ new_ff.ce_over_srst = true;
+ 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",
+ log_id(cell), log_id(cell->type), log_id(module), log_signal(new_ff.sig_d), log_signal(new_ff.sig_q), log_signal(new_ff.val_srst));
+ }
+
+ if (remaining_indices.empty()) {
+ module->remove(cell);
+ did_something = true;
+ continue;
+ } else if (GetSize(remaining_indices) != ff.width) {
+ ff = ff.slice(remaining_indices);
+ ff.cell = cell;
+ changed = true;
+ }
+ }
+ 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;
+
+ for (int i = 0 ; i < ff.width; i++) {
+ // First, eat up as many simple muxes as possible.
+ ctrls_t enables;
+ while (bit2mux.count(ff.sig_d[i]) && bitusers[ff.sig_d[i]] == 1) {
+ cell_int_t mbit = bit2mux.at(ff.sig_d[i]);
+ if (GetSize(mbit.first->getPort(ID::S)) != 1)
+ break;
+ SigBit s = mbit.first->getPort(ID::S);
+ SigBit a = mbit.first->getPort(ID::A)[mbit.second];
+ SigBit b = mbit.first->getPort(ID::B)[mbit.second];
+ if (a == ff.sig_q[i]) {
+ enables.insert(ctrl_t(s, true));
+ ff.sig_d[i] = b;
+ } else if (b == ff.sig_q[i]) {
+ enables.insert(ctrl_t(s, false));
+ ff.sig_d[i] = a;
+ } else {
+ break;
+ }
+ }
+
+ patterns_t patterns;
+ 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_ce)
+ enables.insert(ctrl_t(ff.sig_ce, ff.pol_ce));
+ simplify_patterns(patterns);
+ groups[std::make_pair(patterns, enables)].push_back(i);
+ } else
+ remaining_indices.push_back(i);
+ }
+
+ for (auto &it : groups) {
+ 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_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();
+ if (new_cell)
+ dff_cells.push_back(new_cell);
+ log("Adding EN signal on %s (%s) from module %s (D = %s, Q = %s).\n",
+ log_id(cell), log_id(cell->type), log_id(module), log_signal(new_ff.sig_d), log_signal(new_ff.sig_q));
+ }
+
+ if (remaining_indices.empty()) {
+ module->remove(cell);
+ did_something = true;
+ continue;
+ } else if (GetSize(remaining_indices) != ff.width) {
+ ff = ff.slice(remaining_indices);
+ ff.cell = cell;
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ // Rebuild the FF.
+ 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;
+ }
+ }
+ return did_something;
+ }
+};
+
+struct OptDffPass : public Pass {
+ OptDffPass() : Pass("opt_dff", "perform DFF optimizations") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" opt_dff [-nodffe] [-nosdff] [-keepdc] [-sat] [selection]\n");
+ log("\n");
+ log("This pass converts flip-flops to a more suitable type by merging clock enables\n");
+ log("and synchronous reset multiplexers, removing unused control inputs, or potentially\n");
+ log("removes the flip-flop altogether, converting it to a constant driver.\n");
+ log("\n");
+ log(" -nodffe\n");
+ log(" disables dff -> dffe conversion, and other transforms recognizing clock enable\n");
+ log("\n");
+ log(" -nosdff\n");
+ log(" disables dff -> sdff conversion, and other transforms recognizing sync resets\n");
+ log("\n");
+ log(" -simple-dffe\n");
+ log(" only enables clock enable recognition transform for obvious cases\n");
+ log("\n");
+ log(" -sat\n");
+ log(" additionally invoke SAT solver to detect and remove flip-flops (with\n");
+ log(" non-constant inputs) that can also be replaced with a constant driver\n");
+ log("\n");
+ log(" -keepdc\n");
+ log(" some optimizations change the behavior of the circuit with respect to\n");
+ log(" don't-care bits. for example in 'a+0' a single x-bit in 'a' will cause\n");
+ log(" all result bits to be set to x. this behavior changes when 'a+0' is\n");
+ log(" replaced by 'a'. the -keepdc option disables all such optimizations.\n");
+ log("\n");
+ }
+
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ log_header(design, "Executing OPT_DFF pass (perform DFF optimizations).\n");
+ OptDffOptions opt;
+ opt.nodffe = false;
+ opt.nosdff = false;
+ opt.simple_dffe = false;
+ opt.keepdc = false;
+ opt.sat = false;
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ if (args[argidx] == "-nodffe") {
+ opt.nodffe = true;
+ continue;
+ }
+ if (args[argidx] == "-nosdff") {
+ opt.nosdff = true;
+ continue;
+ }
+ if (args[argidx] == "-simple-dffe") {
+ opt.simple_dffe = true;
+ continue;
+ }
+ if (args[argidx] == "-keepdc") {
+ opt.keepdc = true;
+ continue;
+ }
+ if (args[argidx] == "-sat") {
+ opt.sat = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ bool did_something = false;
+ for (auto mod : design->selected_modules()) {
+ OptDffWorker worker(opt, mod);
+ if (worker.run())
+ did_something = true;
+ if (worker.run_constbits())
+ did_something = true;
+ }
+
+ if (did_something)
+ design->scratchpad_set_bool("opt.did_something", true);
+ }
+} OptDffPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc
index 1051a59f2..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)
+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)
{
- 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 clkinv)
-{
- if (!design->selected(module))
- return;
-
CellTypes ct_combinational;
ct_combinational.setup_internals();
ct_combinational.setup_stdcells();
@@ -465,9 +439,9 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
#define ACTION_DO(_p_, _s_) do { cover("opt.opt_expr.action_" S__LINE__); replace_cell(assign_map, module, cell, input.as_string(), _p_, _s_); goto next_cell; } while (0)
#define ACTION_DO_Y(_v_) ACTION_DO(ID::Y, RTLIL::SigSpec(RTLIL::State::S ## _v_))
- if (clkinv)
+ 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);
@@ -604,7 +588,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (cell->type.in(ID($xnor), ID($_XNOR_))) {
cover("opt.opt_expr.const_xnor");
// For consistency since simplemap does $xnor -> $_XOR_ + $_NOT_
- int width = cell->getParam(ID::Y_WIDTH).as_int();
+ int width = GetSize(cell->getPort(ID::Y));
replace_cell(assign_map, module, cell, "const_xnor", ID::Y, SigSpec(RTLIL::State::S1, width));
goto next_cell;
}
@@ -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");
-
- 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);
+ 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");
- 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);
- }
+ 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);
- 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));
@@ -1596,6 +1575,14 @@ skip_identity:
log_debug("Removing low %d A and %d B bits from cell `%s' in module `%s'.\n",
a_zeros, b_zeros, cell->name.c_str(), module->name.c_str());
+ if (y_zeros >= GetSize(sig_y)) {
+ module->connect(sig_y, RTLIL::SigSpec(0, GetSize(sig_y)));
+ module->remove(cell);
+
+ did_something = true;
+ goto next_cell;
+ }
+
if (a_zeros) {
cell->setPort(ID::A, sig_a.extract_end(a_zeros));
cell->parameters[ID::A_WIDTH] = GetSize(sig_a) - a_zeros;
@@ -1614,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();
@@ -1622,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");
@@ -1640,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");
+ 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);
+ 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);
- std::vector<RTLIL::SigBit> new_b = RTLIL::SigSpec(i, 6);
+ Const new_b = exp;
- while (GetSize(new_b) > 1 && new_b.back() == RTLIL::State::S0)
- new_b.pop_back();
-
- 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;
+ }
}
}
@@ -1949,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++) {
@@ -2036,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
@@ -2056,8 +2051,8 @@ struct OptExprPass : public Pass {
log(" -undriven\n");
log(" replace undriven nets with undef (x) constants\n");
log("\n");
- log(" -clkinv\n");
- log(" optimize clock inverters by changing FF types\n");
+ log(" -noclkinv\n");
+ log(" do not optimize clock inverters by changing FF types\n");
log("\n");
log(" -fine\n");
log(" perform fine-grain optimizations\n");
@@ -2077,7 +2072,7 @@ struct OptExprPass : public Pass {
bool mux_undef = false;
bool mux_bool = false;
bool undriven = false;
- bool clkinv = false;
+ bool noclkinv = false;
bool do_fine = false;
bool keepdc = false;
@@ -2098,8 +2093,8 @@ struct OptExprPass : public Pass {
undriven = true;
continue;
}
- if (args[argidx] == "-clkinv") {
- clkinv = true;
+ if (args[argidx] == "-noclkinv") {
+ noclkinv = true;
continue;
}
if (args[argidx] == "-fine") {
@@ -2136,16 +2131,21 @@ struct OptExprPass : public Pass {
do {
do {
did_something = false;
- replace_const_cells(design, module, false /* consume_x */, mux_undef, mux_bool, do_fine, keepdc, clkinv);
+ replace_const_cells(design, module, false /* consume_x */, mux_undef, mux_bool, do_fine, keepdc, noclkinv);
if (did_something)
design->scratchpad_set_bool("opt.did_something", true);
} while (did_something);
if (!keepdc)
- replace_const_cells(design, module, true /* consume_x */, mux_undef, mux_bool, do_fine, keepdc, clkinv);
+ replace_const_cells(design, module, true /* consume_x */, mux_undef, mux_bool, do_fine, keepdc, noclkinv);
if (did_something)
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 07a91af8a..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);
@@ -277,12 +282,13 @@ struct OptLutWorker
module->connect(lut_output, value);
sigmap.add(lut_output, value);
- module->remove(lut);
luts.erase(lut);
luts_arity.erase(lut);
luts_dlogics.erase(lut);
luts_dlogic_inputs.erase(lut);
+ module->remove(lut);
+
eliminated_count++;
if (limit > 0)
limit--;
@@ -493,11 +499,12 @@ struct OptLutWorker
luts_arity[lutM] = lutM_arity;
luts.erase(lutR);
luts_arity.erase(lutR);
- lutR->module->remove(lutR);
worklist.insert(lutM);
worklist.erase(lutR);
+ lutR->module->remove(lutR);
+
combined_count++;
if (limit > 0)
limit--;
@@ -542,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;
@@ -554,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, '=');
@@ -562,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 24df1356b..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
@@ -19,82 +19,11 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
+#include "kernel/mem.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-struct OptMemWorker
-{
- RTLIL::Design *design;
- RTLIL::Module *module;
- SigMap sigmap;
- bool restart;
-
- dict<IdString, vector<IdString>> memrd, memwr, meminit;
- pool<IdString> remove_mem, remove_cells;
-
- OptMemWorker(RTLIL::Module *module) : design(module->design), module(module), sigmap(module), restart(false)
- {
- for (auto &it : module->memories)
- {
- memrd[it.first];
- memwr[it.first];
- meminit[it.first];
- }
-
- for (auto cell : module->cells())
- {
- if (cell->type == ID($memrd)) {
- IdString id = cell->getParam(ID::MEMID).decode_string();
- memrd.at(id).push_back(cell->name);
- }
-
- if (cell->type == ID($memwr)) {
- IdString id = cell->getParam(ID::MEMID).decode_string();
- memwr.at(id).push_back(cell->name);
- }
-
- if (cell->type == ID($meminit)) {
- IdString id = cell->getParam(ID::MEMID).decode_string();
- meminit.at(id).push_back(cell->name);
- }
- }
- }
-
- ~OptMemWorker()
- {
- for (auto it : remove_mem)
- {
- for (auto cell_name : memrd[it])
- module->remove(module->cell(cell_name));
- for (auto cell_name : memwr[it])
- module->remove(module->cell(cell_name));
- for (auto cell_name : meminit[it])
- module->remove(module->cell(cell_name));
-
- delete module->memories.at(it);
- module->memories.erase(it);
- }
-
- for (auto cell_name : remove_cells)
- module->remove(module->cell(cell_name));
- }
-
- int run(RTLIL::Memory *mem)
- {
- if (restart || remove_mem.count(mem->name))
- return 0;
-
- if (memwr.at(mem->name).empty() && meminit.at(mem->name).empty()) {
- log("Removing memory %s.%s with no write ports or init data.\n", log_id(module), log_id(mem));
- remove_mem.insert(mem->name);
- return 1;
- }
-
- return 0;
- }
-};
-
struct OptMemPass : public Pass {
OptMemPass() : Pass("opt_mem", "optimize memories") { }
void help() override
@@ -122,15 +51,35 @@ struct OptMemPass : public Pass {
int total_count = 0;
for (auto module : design->selected_modules()) {
- while (1) {
- int cnt = 0;
- OptMemWorker worker(module);
- for (auto &it : module->memories)
- if (module->selected(it.second))
- cnt += worker.run(it.second);
- if (!cnt && !worker.restart)
- break;
- total_count += cnt;
+ 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 a95aa74c1..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;
@@ -173,17 +173,11 @@ struct OptMergeWorker
for (const auto &it : cell1->connections_) {
if (cell1->output(it.first)) {
- if (it.first == ID::Q && (cell1->type.begins_with("$dff") || cell1->type.begins_with("$dlatch") ||
- cell1->type.begins_with("$_DFF") || cell1->type.begins_with("$_DLATCH") || cell1->type.begins_with("$_SR_") ||
- cell1->type.in(ID($adff), ID($sr), ID($ff), ID($_FF_)))) {
+ 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();
@@ -249,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)
@@ -295,21 +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 && (cell->type.begins_with("$dff") || cell->type.begins_with("$dlatch") ||
- cell->type.begins_with("$_DFF") || cell->type.begins_with("$_DLATCH") || cell->type.begins_with("$_SR_") ||
- cell->type.in(ID($adff), ID($sr), ID($ff), ID($_FF_)))) {
- 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_rmdff.cc b/passes/opt/opt_rmdff.cc
deleted file mode 100644
index 8f7628a4a..000000000
--- a/passes/opt/opt_rmdff.cc
+++ /dev/null
@@ -1,711 +0,0 @@
-/*
- * yosys -- Yosys Open SYnthesis Suite
- *
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#include "kernel/log.h"
-#include "kernel/register.h"
-#include "kernel/rtlil.h"
-#include "kernel/satgen.h"
-#include "kernel/sigtools.h"
-#include <stdio.h>
-#include <stdlib.h>
-
-USING_YOSYS_NAMESPACE
-PRIVATE_NAMESPACE_BEGIN
-
-SigMap assign_map, dff_init_map;
-SigSet<RTLIL::Cell*> mux_drivers;
-dict<SigBit, RTLIL::Cell*> bit2driver;
-dict<SigBit, pool<SigBit>> init_attributes;
-
-bool keepdc;
-bool sat;
-
-void remove_init_attr(SigSpec sig)
-{
- for (auto bit : assign_map(sig))
- if (init_attributes.count(bit))
- for (auto wbit : init_attributes.at(bit))
- wbit.wire->attributes.at(ID::init)[wbit.offset] = State::Sx;
-}
-
-bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
-{
- SigSpec sig_set, sig_clr;
- State pol_set, pol_clr;
-
- if (cell->hasPort(ID::S))
- sig_set = cell->getPort(ID::S);
-
- if (cell->hasPort(ID::R))
- sig_clr = cell->getPort(ID::R);
-
- if (cell->hasPort(ID::SET))
- sig_set = cell->getPort(ID::SET);
-
- if (cell->hasPort(ID::CLR))
- sig_clr = cell->getPort(ID::CLR);
-
- log_assert(GetSize(sig_set) == GetSize(sig_clr));
-
- if (cell->type.begins_with("$_DFFSR_")) {
- pol_set = cell->type[9] == 'P' ? State::S1 : State::S0;
- pol_clr = cell->type[10] == 'P' ? State::S1 : State::S0;
- } else
- if (cell->type.begins_with("$_DLATCHSR_")) {
- pol_set = cell->type[12] == 'P' ? State::S1 : State::S0;
- pol_clr = cell->type[13] == 'P' ? State::S1 : State::S0;
- } else
- if (cell->type.in(ID($dffsr), ID($dlatchsr))) {
- pol_set = cell->parameters[ID::SET_POLARITY].as_bool() ? State::S1 : State::S0;
- pol_clr = cell->parameters[ID::CLR_POLARITY].as_bool() ? State::S1 : State::S0;
- } else
- log_abort();
-
- State npol_set = pol_set == State::S0 ? State::S1 : State::S0;
- State npol_clr = pol_clr == State::S0 ? State::S1 : State::S0;
-
- SigSpec sig_d = cell->getPort(ID::D);
- SigSpec sig_q = cell->getPort(ID::Q);
-
- bool did_something = false;
- bool proper_sr = false;
- bool used_pol_set = false;
- bool used_pol_clr = false;
- bool hasreset = false;
- Const reset_val;
- SigSpec sig_reset;
-
- for (int i = 0; i < GetSize(sig_set); i++)
- {
- SigBit s = sig_set[i], c = sig_clr[i];
-
- if (s != npol_set || c != npol_clr)
- hasreset = true;
-
- if (s == pol_set || c == pol_clr)
- {
- log("Constantly %s Q bit %s for SR cell %s (%s) from module %s.\n",
- s == pol_set ? "set" : "cleared", log_signal(sig_q[i]),
- log_id(cell), log_id(cell->type), log_id(mod));
-
- remove_init_attr(sig_q[i]);
- mod->connect(sig_q[i], s == pol_set ? State::S1 : State::S0);
- sig_set.remove(i);
- sig_clr.remove(i);
- sig_d.remove(i);
- sig_q.remove(i--);
- did_something = true;
- continue;
- }
- if (sig_reset.empty() && s.wire != nullptr) sig_reset = s;
- if (sig_reset.empty() && c.wire != nullptr) sig_reset = c;
-
- if (s.wire != nullptr && s != sig_reset) proper_sr = true;
- if (c.wire != nullptr && c != sig_reset) proper_sr = true;
-
- if ((s.wire == nullptr) != (c.wire == nullptr)) {
- if (s.wire != nullptr) used_pol_set = true;
- if (c.wire != nullptr) used_pol_clr = true;
- reset_val.bits.push_back(c.wire == nullptr ? State::S1 : State::S0);
- } else
- proper_sr = true;
- }
-
- if (!hasreset)
- proper_sr = false;
-
- if (GetSize(sig_set) == 0)
- {
- log("Removing %s (%s) from module %s.\n", log_id(cell), log_id(cell->type), log_id(mod));
- mod->remove(cell);
- return true;
- }
-
- if (cell->type.in(ID($dffsr), ID($dlatchsr)))
- {
- cell->setParam(ID::WIDTH, GetSize(sig_d));
- cell->setPort(ID::SET, sig_set);
- cell->setPort(ID::CLR, sig_clr);
- cell->setPort(ID::D, sig_d);
- cell->setPort(ID::Q, sig_q);
- }
- else
- {
- cell->setPort(ID::S, sig_set);
- cell->setPort(ID::R, sig_clr);
- cell->setPort(ID::D, sig_d);
- cell->setPort(ID::Q, sig_q);
- }
-
- if (proper_sr)
- return did_something;
-
- if (used_pol_set && used_pol_clr && pol_set != pol_clr)
- return did_something;
-
- if (cell->type == ID($dlatchsr))
- return did_something;
-
- State unified_pol = used_pol_set ? pol_set : pol_clr;
-
- if (cell->type == ID($dffsr))
- {
- if (hasreset)
- {
- log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), "$adff", log_id(mod));
-
- cell->type = ID($adff);
- cell->setParam(ID::ARST_POLARITY, unified_pol);
- cell->setParam(ID::ARST_VALUE, reset_val);
- cell->setPort(ID::ARST, sig_reset);
-
- cell->unsetParam(ID::SET_POLARITY);
- cell->unsetParam(ID::CLR_POLARITY);
- cell->unsetPort(ID::SET);
- cell->unsetPort(ID::CLR);
- }
- else
- {
- log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), "$dff", log_id(mod));
-
- cell->type = ID($dff);
- cell->unsetParam(ID::SET_POLARITY);
- cell->unsetParam(ID::CLR_POLARITY);
- cell->unsetPort(ID::SET);
- cell->unsetPort(ID::CLR);
- }
-
- return true;
- }
-
- if (!hasreset)
- {
- IdString new_type;
-
- if (cell->type.begins_with("$_DFFSR_"))
- new_type = stringf("$_DFF_%c_", cell->type[8]);
- else if (cell->type.begins_with("$_DLATCHSR_"))
- new_type = stringf("$_DLATCH_%c_", cell->type[11]);
- else
- log_abort();
-
- log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), log_id(new_type), log_id(mod));
-
- cell->type = new_type;
- cell->unsetPort(ID::S);
- cell->unsetPort(ID::R);
-
- return true;
- }
-
- return did_something;
-}
-
-bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch)
-{
- SigSpec sig_e;
- State on_state, off_state;
-
- if (dlatch->type == ID($dlatch)) {
- sig_e = assign_map(dlatch->getPort(ID::EN));
- on_state = dlatch->getParam(ID::EN_POLARITY).as_bool() ? State::S1 : State::S0;
- off_state = dlatch->getParam(ID::EN_POLARITY).as_bool() ? State::S0 : State::S1;
- } else
- if (dlatch->type == ID($_DLATCH_P_)) {
- sig_e = assign_map(dlatch->getPort(ID::E));
- on_state = State::S1;
- off_state = State::S0;
- } else
- if (dlatch->type == ID($_DLATCH_N_)) {
- sig_e = assign_map(dlatch->getPort(ID::E));
- on_state = State::S0;
- off_state = State::S1;
- } else
- log_abort();
-
- if (sig_e == off_state)
- {
- RTLIL::Const val_init;
- for (auto bit : dff_init_map(dlatch->getPort(ID::Q)))
- val_init.bits.push_back(bit.wire == NULL ? bit.data : State::Sx);
- mod->connect(dlatch->getPort(ID::Q), val_init);
- goto delete_dlatch;
- }
-
- if (sig_e == on_state)
- {
- mod->connect(dlatch->getPort(ID::Q), dlatch->getPort(ID::D));
- goto delete_dlatch;
- }
-
- return false;
-
-delete_dlatch:
- log("Removing %s (%s) from module %s.\n", log_id(dlatch), log_id(dlatch->type), log_id(mod));
- remove_init_attr(dlatch->getPort(ID::Q));
- mod->remove(dlatch);
- return true;
-}
-
-bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
-{
- RTLIL::SigSpec sig_d, sig_q, sig_c, sig_r, sig_e;
- RTLIL::Const val_cp, val_rp, val_rv, val_ep;
-
- if (dff->type == ID($_FF_)) {
- sig_d = dff->getPort(ID::D);
- sig_q = dff->getPort(ID::Q);
- }
- else if (dff->type == ID($_DFF_N_) || dff->type == ID($_DFF_P_)) {
- sig_d = dff->getPort(ID::D);
- sig_q = dff->getPort(ID::Q);
- sig_c = dff->getPort(ID::C);
- val_cp = RTLIL::Const(dff->type == ID($_DFF_P_), 1);
- }
- else if (dff->type.begins_with("$_DFF_") && dff->type.compare(9, 1, "_") == 0 &&
- (dff->type[6] == 'N' || dff->type[6] == 'P') &&
- (dff->type[7] == 'N' || dff->type[7] == 'P') &&
- (dff->type[8] == '0' || dff->type[8] == '1')) {
- sig_d = dff->getPort(ID::D);
- sig_q = dff->getPort(ID::Q);
- sig_c = dff->getPort(ID::C);
- sig_r = dff->getPort(ID::R);
- val_cp = RTLIL::Const(dff->type[6] == 'P', 1);
- val_rp = RTLIL::Const(dff->type[7] == 'P', 1);
- val_rv = RTLIL::Const(dff->type[8] == '1', 1);
- }
- else if (dff->type.begins_with("$_DFFE_") && dff->type.compare(9, 1, "_") == 0 &&
- (dff->type[7] == 'N' || dff->type[7] == 'P') &&
- (dff->type[8] == 'N' || dff->type[8] == 'P')) {
- sig_d = dff->getPort(ID::D);
- sig_q = dff->getPort(ID::Q);
- sig_c = dff->getPort(ID::C);
- sig_e = dff->getPort(ID::E);
- val_cp = RTLIL::Const(dff->type[7] == 'P', 1);
- val_ep = RTLIL::Const(dff->type[8] == 'P', 1);
- }
- else if (dff->type == ID($ff)) {
- sig_d = dff->getPort(ID::D);
- sig_q = dff->getPort(ID::Q);
- }
- else if (dff->type == ID($dff)) {
- sig_d = dff->getPort(ID::D);
- sig_q = dff->getPort(ID::Q);
- sig_c = dff->getPort(ID::CLK);
- val_cp = RTLIL::Const(dff->parameters[ID::CLK_POLARITY].as_bool(), 1);
- }
- else if (dff->type == ID($dffe)) {
- sig_e = dff->getPort(ID::EN);
- sig_d = dff->getPort(ID::D);
- sig_q = dff->getPort(ID::Q);
- sig_c = dff->getPort(ID::CLK);
- val_cp = RTLIL::Const(dff->parameters[ID::CLK_POLARITY].as_bool(), 1);
- val_ep = RTLIL::Const(dff->parameters[ID::EN_POLARITY].as_bool(), 1);
- }
- else if (dff->type == ID($adff)) {
- sig_d = dff->getPort(ID::D);
- sig_q = dff->getPort(ID::Q);
- sig_c = dff->getPort(ID::CLK);
- sig_r = dff->getPort(ID::ARST);
- val_cp = RTLIL::Const(dff->parameters[ID::CLK_POLARITY].as_bool(), 1);
- val_rp = RTLIL::Const(dff->parameters[ID::ARST_POLARITY].as_bool(), 1);
- val_rv = dff->parameters[ID::ARST_VALUE];
- }
- else
- log_abort();
-
- assign_map.apply(sig_d);
- assign_map.apply(sig_q);
- assign_map.apply(sig_c);
- assign_map.apply(sig_r);
-
- bool has_init = false;
- RTLIL::Const val_init;
- for (auto bit : dff_init_map(sig_q).to_sigbit_vector()) {
- if (bit.wire == NULL || keepdc)
- has_init = true;
- val_init.bits.push_back(bit.wire == NULL ? bit.data : RTLIL::State::Sx);
- }
-
- if (dff->type.in(ID($ff), ID($dff)) && mux_drivers.has(sig_d)) {
- std::set<RTLIL::Cell*> muxes;
- mux_drivers.find(sig_d, muxes);
- for (auto mux : muxes) {
- RTLIL::SigSpec sig_a = assign_map(mux->getPort(ID::A));
- RTLIL::SigSpec sig_b = assign_map(mux->getPort(ID::B));
- if (sig_a == sig_q && sig_b.is_fully_const() && (!has_init || val_init == sig_b.as_const())) {
- mod->connect(sig_q, sig_b);
- goto delete_dff;
- }
- if (sig_b == sig_q && sig_a.is_fully_const() && (!has_init || val_init == sig_a.as_const())) {
- mod->connect(sig_q, sig_a);
- goto delete_dff;
- }
- }
- }
-
- // If clock is driven by a constant and (i) no reset signal
- // (ii) Q has no initial value
- // (iii) initial value is same as reset value
- if (!sig_c.empty() && sig_c.is_fully_const() && (!sig_r.size() || !has_init || val_init == val_rv)) {
- if (val_rv.bits.size() == 0)
- val_rv = val_init;
- // Q is permanently reset value or initial value
- mod->connect(sig_q, val_rv);
- goto delete_dff;
- }
-
- // If D is fully undefined and reset signal present and (i) Q has no initial value
- // (ii) initial value is same as reset value
- if (sig_d.is_fully_undef() && sig_r.size() && (!has_init || val_init == val_rv)) {
- // Q is permanently reset value
- mod->connect(sig_q, val_rv);
- goto delete_dff;
- }
-
- // If D is fully undefined and no reset signal and Q has an initial value
- if (sig_d.is_fully_undef() && !sig_r.size() && has_init) {
- // Q is permanently initial value
- mod->connect(sig_q, val_init);
- goto delete_dff;
- }
-
- // If D is fully constant and (i) no reset signal
- // (ii) reset value is same as constant D
- // and (a) has no initial value
- // (b) initial value same as constant D
- if (sig_d.is_fully_const() && (!sig_r.size() || val_rv == sig_d.as_const()) && (!has_init || val_init == sig_d.as_const())) {
- // Q is permanently D
- mod->connect(sig_q, sig_d);
- goto delete_dff;
- }
-
- // If D input is same as Q output and (i) no reset signal
- // (ii) no initial signal
- // (iii) initial value is same as reset value
- if (sig_d == sig_q && (sig_r.empty() || !has_init || val_init == val_rv)) {
- // Q is permanently reset value or initial value
- if (sig_r.size())
- mod->connect(sig_q, val_rv);
- else if (has_init)
- mod->connect(sig_q, val_init);
- goto delete_dff;
- }
-
- // If reset signal is present, and is fully constant
- if (!sig_r.empty() && sig_r.is_fully_const())
- {
- // If reset value is permanently active or if reset is undefined
- if (sig_r == val_rp || sig_r.is_fully_undef()) {
- // Q is permanently reset value
- mod->connect(sig_q, val_rv);
- goto delete_dff;
- }
-
- log("Removing unused reset from %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod));
-
- if (dff->type == ID($adff)) {
- dff->type = ID($dff);
- dff->unsetPort(ID::ARST);
- dff->unsetParam(ID::ARST_POLARITY);
- dff->unsetParam(ID::ARST_VALUE);
- return true;
- }
-
- log_assert(dff->type.begins_with("$_DFF_"));
- dff->type = stringf("$_DFF_%c_", + dff->type[6]);
- dff->unsetPort(ID::R);
- }
-
- // If enable signal is present, and is fully constant
- if (!sig_e.empty() && sig_e.is_fully_const())
- {
- // If enable value is permanently inactive
- if (sig_e != val_ep) {
- // Q is permanently initial value
- mod->connect(sig_q, val_init);
- goto delete_dff;
- }
-
- log("Removing unused enable from %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod));
-
- if (dff->type == ID($dffe)) {
- dff->type = ID($dff);
- dff->unsetPort(ID::EN);
- dff->unsetParam(ID::EN_POLARITY);
- return true;
- }
-
- log_assert(dff->type.begins_with("$_DFFE_"));
- dff->type = stringf("$_DFF_%c_", + dff->type[7]);
- dff->unsetPort(ID::E);
- }
-
- if (sat && has_init && (!sig_r.size() || val_init == val_rv))
- {
- bool removed_sigbits = false;
-
- ezSatPtr ez;
- SatGen satgen(ez.get(), &assign_map);
- pool<Cell*> sat_cells;
-
- 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 : assign_map(conn.second))
- if (bit2driver.count(bit))
- sat_import_cell(bit2driver.at(bit));
- }
- };
-
- // For each register bit, try to prove that it cannot change from the initial value. If so, remove it
- for (int position = 0; position < GetSize(sig_d); position += 1) {
- RTLIL::SigBit q_sigbit = sig_q[position];
- RTLIL::SigBit d_sigbit = sig_d[position];
-
- if ((!q_sigbit.wire) || (!d_sigbit.wire))
- continue;
-
- if (!bit2driver.count(d_sigbit))
- continue;
-
- sat_import_cell(bit2driver.at(d_sigbit));
-
- RTLIL::State sigbit_init_val = val_init[position];
- if (sigbit_init_val != State::S0 && sigbit_init_val != State::S1)
- continue;
-
- int init_sat_pi = satgen.importSigSpec(sigbit_init_val).front();
- int q_sat_pi = satgen.importSigBit(q_sigbit);
- int d_sat_pi = satgen.importSigBit(d_sigbit);
-
- // 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)
- {
- log("Setting constant %d-bit at position %d on %s (%s) from module %s.\n", sigbit_init_val ? 1 : 0,
- position, log_id(dff), log_id(dff->type), log_id(mod));
-
- SigSpec tmp = dff->getPort(ID::D);
- tmp[position] = sigbit_init_val;
- dff->setPort(ID::D, tmp);
-
- removed_sigbits = true;
- }
- }
-
- if (removed_sigbits) {
- handle_dff(mod, dff);
- return true;
- }
- }
-
-
- return false;
-
-delete_dff:
- log("Removing %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod));
- remove_init_attr(dff->getPort(ID::Q));
- mod->remove(dff);
-
- for (auto &entry : bit2driver)
- if (entry.second == dff)
- bit2driver.erase(entry.first);
-
- return true;
-}
-
-struct OptRmdffPass : public Pass {
- OptRmdffPass() : Pass("opt_rmdff", "remove DFFs with constant inputs") { }
- void help() override
- {
- // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
- log("\n");
- log(" opt_rmdff [-keepdc] [-sat] [selection]\n");
- log("\n");
- log("This pass identifies flip-flops with constant inputs and replaces them with\n");
- log("a constant driver.\n");
- log("\n");
- log(" -sat\n");
- log(" additionally invoke SAT solver to detect and remove flip-flops (with \n");
- log(" non-constant inputs) that can also be replaced with a constant driver\n");
- log("\n");
- }
- void execute(std::vector<std::string> args, RTLIL::Design *design) override
- {
- int total_count = 0, total_initdrv = 0;
- log_header(design, "Executing OPT_RMDFF pass (remove dff with constant values).\n");
-
- keepdc = false;
- sat = false;
-
- size_t argidx;
- for (argidx = 1; argidx < args.size(); argidx++) {
- if (args[argidx] == "-keepdc") {
- keepdc = true;
- continue;
- }
- if (args[argidx] == "-sat") {
- sat = true;
- continue;
- }
- break;
- }
- extra_args(args, argidx, design);
-
- for (auto module : design->selected_modules()) {
- pool<SigBit> driven_bits;
- dict<SigBit, State> init_bits;
-
- assign_map.set(module);
- dff_init_map.set(module);
- mux_drivers.clear();
- bit2driver.clear();
- init_attributes.clear();
-
- for (auto wire : module->wires())
- {
- if (wire->attributes.count(ID::init) != 0) {
- Const initval = wire->attributes.at(ID::init);
- for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++)
- if (initval[i] == State::S0 || initval[i] == State::S1)
- dff_init_map.add(SigBit(wire, i), initval[i]);
- for (int i = 0; i < GetSize(wire); i++) {
- SigBit wire_bit(wire, i), mapped_bit = assign_map(wire_bit);
- if (mapped_bit.wire) {
- init_attributes[mapped_bit].insert(wire_bit);
- if (i < GetSize(initval))
- init_bits[mapped_bit] = initval[i];
- }
- }
- }
-
- if (wire->port_input) {
- for (auto bit : assign_map(wire))
- driven_bits.insert(bit);
- }
- }
-
- std::vector<RTLIL::IdString> dff_list;
- std::vector<RTLIL::IdString> dffsr_list;
- std::vector<RTLIL::IdString> dlatch_list;
- for (auto cell : module->cells())
- {
- for (auto &conn : cell->connections()) {
- bool is_output = cell->output(conn.first);
- if (is_output || !cell->known())
- for (auto bit : assign_map(conn.second)) {
- if (is_output)
- bit2driver[bit] = cell;
- driven_bits.insert(bit);
- }
- }
-
- if (cell->type.in(ID($mux), ID($pmux))) {
- if (cell->getPort(ID::A).size() == cell->getPort(ID::B).size())
- mux_drivers.insert(assign_map(cell->getPort(ID::Y)), cell);
- continue;
- }
-
- if (!design->selected(module, cell))
- continue;
-
- 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_), ID($dffsr),
- 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($dlatchsr)))
- dffsr_list.push_back(cell->name);
-
- if (cell->type.in(ID($_FF_), ID($_DFF_N_), ID($_DFF_P_),
- ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
- ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_),
- ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_),
- ID($ff), ID($dff), ID($dffe), ID($adff)))
- dff_list.push_back(cell->name);
-
- if (cell->type.in(ID($dlatch), ID($_DLATCH_P_), ID($_DLATCH_N_)))
- dlatch_list.push_back(cell->name);
- }
-
- for (auto &id : dffsr_list) {
- if (module->cell(id) != nullptr &&
- handle_dffsr(module, module->cells_[id]))
- total_count++;
- }
-
- for (auto &id : dff_list) {
- if (module->cell(id) != nullptr &&
- handle_dff(module, module->cells_[id]))
- total_count++;
- }
-
- for (auto &id : dlatch_list) {
- if (module->cell(id) != nullptr &&
- handle_dlatch(module, module->cells_[id]))
- total_count++;
- }
-
- SigSpec const_init_sigs;
-
- for (auto bit : init_bits)
- if (!driven_bits.count(bit.first))
- const_init_sigs.append(bit.first);
-
- const_init_sigs.sort_and_unify();
-
- for (SigSpec sig : const_init_sigs.chunks())
- {
- Const val;
-
- for (auto bit : sig)
- val.bits.push_back(init_bits.at(bit));
-
- log("Promoting init spec %s = %s to constant driver in module %s.\n",
- log_signal(sig), log_signal(val), log_id(module));
-
- module->connect(sig, val);
- remove_init_attr(sig);
- total_initdrv++;
- }
- }
-
- assign_map.clear();
- mux_drivers.clear();
- bit2driver.clear();
- init_attributes.clear();
-
- if (total_count || total_initdrv)
- design->scratchpad_set_bool("opt.did_something", true);
-
- if (total_initdrv)
- log("Promoted %d init specs to constant drivers.\n", total_initdrv);
-
- if (total_count)
- log("Replaced %d DFF cells.\n", total_count);
- }
-} OptRmdffPass;
-
-PRIVATE_NAMESPACE_END
diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc
index db21cef28..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
@@ -30,8 +30,6 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-SigMap assign_map;
-
struct OpMuxConn {
RTLIL::SigSpec sig;
RTLIL::Cell *mux;
@@ -157,9 +155,9 @@ bool decode_port_signed(RTLIL::Cell *cell, RTLIL::IdString port_name)
return false;
}
-ExtSigSpec decode_port(RTLIL::Cell *cell, RTLIL::IdString port_name, SigMap *sigmap)
+ExtSigSpec decode_port(RTLIL::Cell *cell, RTLIL::IdString port_name, const SigMap &sigmap)
{
- auto sig = (*sigmap)(cell->getPort(port_name));
+ auto sig = sigmap(cell->getPort(port_name));
RTLIL::SigSpec sign = decode_port_sign(cell, port_name);
RTLIL::IdString semantics = decode_port_semantics(cell, port_name);
@@ -169,7 +167,7 @@ ExtSigSpec decode_port(RTLIL::Cell *cell, RTLIL::IdString port_name, SigMap *sig
return ExtSigSpec(sig, sign, is_signed, semantics);
}
-void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector<OpMuxConn> &ports, const ExtSigSpec &operand)
+void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector<OpMuxConn> &ports, const ExtSigSpec &operand, const SigMap &sigmap)
{
std::vector<ExtSigSpec> muxed_operands;
int max_width = 0;
@@ -177,10 +175,10 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector<
auto op = p.op;
RTLIL::IdString muxed_port_name = ID::A;
- if (decode_port(op, ID::A, &assign_map) == operand)
+ if (decode_port(op, ID::A, sigmap) == operand)
muxed_port_name = ID::B;
- auto operand = decode_port(op, muxed_port_name, &assign_map);
+ auto operand = decode_port(op, muxed_port_name, sigmap);
if (operand.sig.size() > max_width)
max_width = operand.sig.size();
@@ -190,11 +188,13 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector<
auto shared_op = ports[0].op;
if (std::any_of(muxed_operands.begin(), muxed_operands.end(), [&](ExtSigSpec &op) { return op.sign != muxed_operands[0].sign; }))
- max_width = std::max(max_width, shared_op->getParam(ID::Y_WIDTH).as_int());
-
+ max_width = std::max(max_width, shared_op->getParam(ID::Y_WIDTH).as_int());
- for (auto &operand : muxed_operands)
+ for (auto &operand : muxed_operands) {
operand.sig.extend_u0(max_width, operand.is_signed);
+ if (operand.sign != muxed_operands[0].sign)
+ operand = ExtSigSpec(module->Neg(NEW_ID, operand.sig, operand.is_signed));
+ }
for (const auto& p : ports) {
auto op = p.op;
@@ -203,61 +203,58 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector<
module->remove(op);
}
- for (auto &muxed_op : muxed_operands)
- if (muxed_op.sign != muxed_operands[0].sign)
- muxed_op = ExtSigSpec(module->Neg(NEW_ID, muxed_op.sig, muxed_op.is_signed));
-
- RTLIL::SigSpec mux_y = mux->getPort(ID::Y);
RTLIL::SigSpec mux_a = mux->getPort(ID::A);
RTLIL::SigSpec mux_b = mux->getPort(ID::B);
RTLIL::SigSpec mux_s = mux->getPort(ID::S);
+ int conn_width = ports[0].sig.size();
+ int conn_mux_offset = ports[0].mux_port_offset;
+ int conn_op_offset = ports[0].op_outsig_offset;
+
RTLIL::SigSpec shared_pmux_a = RTLIL::Const(RTLIL::State::Sx, max_width);
RTLIL::SigSpec shared_pmux_b;
RTLIL::SigSpec shared_pmux_s;
- int conn_width = ports[0].sig.size();
- int conn_offset = ports[0].mux_port_offset;
-
- shared_op->setPort(ID::Y, shared_op->getPort(ID::Y).extract(0, conn_width));
+ // Make a new wire to avoid false equivalence with whatever the former shared output was connected to.
+ Wire *new_out = module->addWire(NEW_ID, conn_op_offset + conn_width);
+ SigSpec new_sig_out = SigSpec(new_out, conn_op_offset, conn_width);
- if (mux->type == ID($pmux)) {
- shared_pmux_s = RTLIL::SigSpec();
-
- for (const auto &p : ports) {
+ for (int i = 0; i < GetSize(ports); i++) {
+ auto &p = ports[i];
+ auto &op = muxed_operands[i];
+ if (p.mux_port_id == GetSize(mux_s)) {
+ shared_pmux_a = op.sig;
+ mux_a.replace(conn_mux_offset, new_sig_out);
+ } else {
shared_pmux_s.append(mux_s[p.mux_port_id]);
- mux_b.replace(p.mux_port_id * mux_a.size() + conn_offset, shared_op->getPort(ID::Y));
+ shared_pmux_b.append(op.sig);
+ mux_b.replace(p.mux_port_id * mux_a.size() + conn_mux_offset, new_sig_out);
}
- } else {
- shared_pmux_s = RTLIL::SigSpec{mux_s, module->Not(NEW_ID, mux_s)};
- mux_a.replace(conn_offset, shared_op->getPort(ID::Y));
- mux_b.replace(conn_offset, shared_op->getPort(ID::Y));
}
mux->setPort(ID::A, mux_a);
mux->setPort(ID::B, mux_b);
- mux->setPort(ID::Y, mux_y);
mux->setPort(ID::S, mux_s);
- for (const auto &op : muxed_operands)
- shared_pmux_b.append(op.sig);
-
- auto mux_to_oper = module->Pmux(NEW_ID, shared_pmux_a, shared_pmux_b, shared_pmux_s);
+ SigSpec mux_to_oper;
+ if (GetSize(shared_pmux_s) == 1) {
+ mux_to_oper = module->Mux(NEW_ID, shared_pmux_a, shared_pmux_b, shared_pmux_s);
+ } else {
+ mux_to_oper = module->Pmux(NEW_ID, shared_pmux_a, shared_pmux_b, shared_pmux_s);
+ }
if (shared_op->type.in(ID($alu))) {
- RTLIL::SigSpec alu_x = shared_op->getPort(ID::X);
- RTLIL::SigSpec alu_co = shared_op->getPort(ID::CO);
-
- shared_op->setPort(ID::X, alu_x.extract(0, conn_width));
- shared_op->setPort(ID::CO, alu_co.extract(0, conn_width));
+ shared_op->setPort(ID::X, module->addWire(NEW_ID, GetSize(new_out)));
+ shared_op->setPort(ID::CO, module->addWire(NEW_ID, GetSize(new_out)));
}
bool is_fine = shared_op->type.in(FINE_BITWISE_OPS);
+ shared_op->setPort(ID::Y, new_out);
if (!is_fine)
- shared_op->setParam(ID::Y_WIDTH, conn_width);
+ shared_op->setParam(ID::Y_WIDTH, GetSize(new_out));
- if (decode_port(shared_op, ID::A, &assign_map) == operand) {
+ if (decode_port(shared_op, ID::A, sigmap) == operand) {
shared_op->setPort(ID::B, mux_to_oper);
if (!is_fine)
shared_op->setParam(ID::B_WIDTH, max_width);
@@ -275,17 +272,7 @@ typedef struct {
} merged_op_t;
-template <typename T> void remove_val(std::vector<T> &v, const std::vector<T> &vals)
-{
- auto val_iter = vals.rbegin();
- for (auto i = v.rbegin(); i != v.rend(); ++i)
- if ((val_iter != vals.rend()) && (*i == *val_iter)) {
- v.erase(i.base() - 1);
- ++val_iter;
- }
-}
-
-void check_muxed_operands(std::vector<const OpMuxConn *> &ports, const ExtSigSpec &shared_operand)
+void check_muxed_operands(std::vector<const OpMuxConn *> &ports, const ExtSigSpec &shared_operand, const SigMap &sigmap)
{
auto it = ports.begin();
ExtSigSpec seed;
@@ -295,11 +282,11 @@ void check_muxed_operands(std::vector<const OpMuxConn *> &ports, const ExtSigSpe
auto op = p->op;
RTLIL::IdString muxed_port_name = ID::A;
- if (decode_port(op, ID::A, &assign_map) == shared_operand) {
+ if (decode_port(op, ID::A, sigmap) == shared_operand) {
muxed_port_name = ID::B;
}
- auto operand = decode_port(op, muxed_port_name, &assign_map);
+ auto operand = decode_port(op, muxed_port_name, sigmap);
if (seed.empty())
seed = operand;
@@ -312,7 +299,7 @@ void check_muxed_operands(std::vector<const OpMuxConn *> &ports, const ExtSigSpe
}
}
-ExtSigSpec find_shared_operand(const OpMuxConn* seed, std::vector<const OpMuxConn *> &ports, const std::map<ExtSigSpec, std::set<RTLIL::Cell *>> &operand_to_users)
+ExtSigSpec find_shared_operand(const OpMuxConn* seed, std::vector<const OpMuxConn *> &ports, const std::map<ExtSigSpec, std::set<RTLIL::Cell *>> &operand_to_users, const SigMap &sigmap)
{
std::set<RTLIL::Cell *> ops_using_operand;
std::set<RTLIL::Cell *> ops_set;
@@ -324,7 +311,7 @@ ExtSigSpec find_shared_operand(const OpMuxConn* seed, std::vector<const OpMuxCon
auto op_a = seed->op;
for (RTLIL::IdString port_name : {ID::A, ID::B}) {
- oper = decode_port(op_a, port_name, &assign_map);
+ oper = decode_port(op_a, port_name, sigmap);
auto operand_users = operand_to_users.at(oper);
if (operand_users.size() == 1)
@@ -345,132 +332,6 @@ ExtSigSpec find_shared_operand(const OpMuxConn* seed, std::vector<const OpMuxCon
return ExtSigSpec();
}
-dict<RTLIL::SigSpec, OpMuxConn> find_valid_op_mux_conns(RTLIL::Module *module, dict<RTLIL::SigBit, RTLIL::SigSpec> &op_outbit_to_outsig,
- dict<RTLIL::SigSpec, RTLIL::Cell *> outsig_to_operator,
- dict<RTLIL::SigBit, RTLIL::SigSpec> &op_aux_to_outsig)
-{
- dict<RTLIL::SigSpec, int> op_outsig_user_track;
- dict<RTLIL::SigSpec, OpMuxConn> op_mux_conn_map;
-
- std::function<void(RTLIL::SigSpec)> remove_outsig = [&](RTLIL::SigSpec outsig) {
- for (auto op_outbit : outsig)
- op_outbit_to_outsig.erase(op_outbit);
-
- if (op_mux_conn_map.count(outsig))
- op_mux_conn_map.erase(outsig);
- };
-
- std::function<void(RTLIL::SigBit)> remove_outsig_from_aux_bit = [&](RTLIL::SigBit auxbit) {
- auto aux_outsig = op_aux_to_outsig.at(auxbit);
- auto op = outsig_to_operator.at(aux_outsig);
- auto op_outsig = assign_map(op->getPort(ID::Y));
- remove_outsig(op_outsig);
-
- for (auto aux_outbit : aux_outsig)
- op_aux_to_outsig.erase(aux_outbit);
- };
-
- std::function<void(RTLIL::Cell *)> find_op_mux_conns = [&](RTLIL::Cell *mux) {
- RTLIL::SigSpec sig;
- int mux_port_size;
-
- if (mux->type.in(ID($mux), ID($_MUX_))) {
- mux_port_size = mux->getPort(ID::A).size();
- sig = RTLIL::SigSpec{mux->getPort(ID::B), mux->getPort(ID::A)};
- } else {
- mux_port_size = mux->getPort(ID::A).size();
- sig = mux->getPort(ID::B);
- }
-
- auto mux_insig = assign_map(sig);
-
- for (int i = 0; i < mux_insig.size(); ++i) {
- if (op_aux_to_outsig.count(mux_insig[i])) {
- remove_outsig_from_aux_bit(mux_insig[i]);
- continue;
- }
-
- if (!op_outbit_to_outsig.count(mux_insig[i]))
- continue;
-
- auto op_outsig = op_outbit_to_outsig.at(mux_insig[i]);
-
- if (op_mux_conn_map.count(op_outsig)) {
- remove_outsig(op_outsig);
- continue;
- }
-
- int mux_port_id = i / mux_port_size;
- int mux_port_offset = i % mux_port_size;
-
- int op_outsig_offset;
- for (op_outsig_offset = 0; op_outsig[op_outsig_offset] != mux_insig[i]; ++op_outsig_offset)
- ;
-
- int j = op_outsig_offset;
- do {
- if (!op_outbit_to_outsig.count(mux_insig[i]))
- break;
-
- if (op_outbit_to_outsig.at(mux_insig[i]) != op_outsig)
- break;
-
- ++i;
- ++j;
- } while ((i / mux_port_size == mux_port_id) && (j < op_outsig.size()));
-
- int op_conn_width = j - op_outsig_offset;
- OpMuxConn inp = {
- op_outsig.extract(op_outsig_offset, op_conn_width),
- mux,
- outsig_to_operator.at(op_outsig),
- mux_port_id,
- mux_port_offset,
- op_outsig_offset,
- };
-
- op_mux_conn_map[op_outsig] = inp;
-
- --i;
- }
- };
-
- std::function<void(RTLIL::SigSpec)> remove_connected_ops = [&](RTLIL::SigSpec sig) {
- auto mux_insig = assign_map(sig);
- for (auto outbit : mux_insig) {
- if (op_aux_to_outsig.count(outbit)) {
- remove_outsig_from_aux_bit(outbit);
- continue;
- }
-
- if (!op_outbit_to_outsig.count(outbit))
- continue;
-
- remove_outsig(op_outbit_to_outsig.at(outbit));
- }
- };
-
- for (auto cell : module->cells()) {
- if (cell->type.in(ID($mux), ID($_MUX_), ID($pmux))) {
- remove_connected_ops(cell->getPort(ID::S));
- find_op_mux_conns(cell);
- } else {
- for (auto &conn : cell->connections())
- if (cell->input(conn.first))
- remove_connected_ops(conn.second);
- }
- }
-
- for (auto w : module->wires()) {
- if (!w->port_output)
- continue;
-
- remove_connected_ops(w);
- }
-
- return op_mux_conn_map;
-}
-
struct OptSharePass : public Pass {
OptSharePass() : Pass("opt_share", "merge mutually exclusive cells of the same type that share an input signal") {}
void help() override
@@ -495,37 +356,46 @@ struct OptSharePass : public Pass {
extra_args(args, 1, design);
for (auto module : design->selected_modules()) {
- assign_map.clear();
- assign_map.set(module);
+ SigMap sigmap(module);
+
+ dict<RTLIL::SigBit, int> bit_users;
+
+ for (auto cell : module->cells())
+ for (auto conn : cell->connections())
+ for (auto bit : conn.second)
+ bit_users[sigmap(bit)]++;
+
+ for (auto wire : module->wires())
+ if (wire->port_id != 0)
+ for (auto bit : SigSpec(wire))
+ bit_users[sigmap(bit)]++;
std::map<ExtSigSpec, std::set<RTLIL::Cell *>> operand_to_users;
- dict<RTLIL::SigSpec, RTLIL::Cell *> outsig_to_operator;
- dict<RTLIL::SigBit, RTLIL::SigSpec> op_outbit_to_outsig;
- dict<RTLIL::SigBit, RTLIL::SigSpec> op_aux_to_outsig;
+ dict<RTLIL::SigBit, std::pair<RTLIL::Cell *, int>> op_outbit_to_outsig;
bool any_shared_operands = false;
- std::vector<ExtSigSpec> op_insigs;
- for (auto cell : module->cells()) {
+ for (auto cell : module->selected_cells()) {
if (!cell_supported(cell))
continue;
+ bool skip = false;
if (cell->type == ID($alu)) {
for (RTLIL::IdString port_name : {ID::X, ID::CO}) {
- auto mux_insig = assign_map(cell->getPort(port_name));
- outsig_to_operator[mux_insig] = cell;
- for (auto outbit : mux_insig)
- op_aux_to_outsig[outbit] = mux_insig;
+ for (auto outbit : sigmap(cell->getPort(port_name)))
+ if (bit_users[outbit] > 1)
+ skip = true;
}
}
- auto mux_insig = assign_map(cell->getPort(ID::Y));
- outsig_to_operator[mux_insig] = cell;
- for (auto outbit : mux_insig)
- op_outbit_to_outsig[outbit] = mux_insig;
+ if (skip)
+ continue;
+
+ auto mux_insig = sigmap(cell->getPort(ID::Y));
+ for (int i = 0; i < GetSize(mux_insig); i++)
+ op_outbit_to_outsig[mux_insig[i]] = std::make_pair(cell, i);
for (RTLIL::IdString port_name : {ID::A, ID::B}) {
- auto op_insig = decode_port(cell, port_name, &assign_map);
- op_insigs.push_back(op_insig);
+ auto op_insig = decode_port(cell, port_name, sigmap);
operand_to_users[op_insig].insert(cell);
if (operand_to_users[op_insig].size() > 1)
any_shared_operands = true;
@@ -537,34 +407,79 @@ struct OptSharePass : public Pass {
// Operator outputs need to be exclusively connected to the $mux inputs in order to be mergeable. Hence we count to
// how many points are operator output bits connected.
- dict<RTLIL::SigSpec, OpMuxConn> op_mux_conn_map =
- find_valid_op_mux_conns(module, op_outbit_to_outsig, outsig_to_operator, op_aux_to_outsig);
+ std::vector<merged_op_t> merged_ops;
- // Group op connections connected to same ports of the same $mux. Sort them in ascending order of their port offset
- dict<RTLIL::Cell*, std::vector<std::set<OpMuxConn>>> mux_port_op_conns;
- for (auto& val: op_mux_conn_map) {
- OpMuxConn p = val.second;
- auto& mux_port_conns = mux_port_op_conns[p.mux];
+ for (auto mux : module->selected_cells()) {
+ if (!mux->type.in(ID($mux), ID($_MUX_), ID($pmux)))
+ continue;
- if (mux_port_conns.size() == 0) {
- int mux_port_num;
+ int mux_port_size = GetSize(mux->getPort(ID::A));
+ int mux_port_num = GetSize(mux->getPort(ID::S)) + 1;
- if (p.mux->type.in(ID($mux), ID($_MUX_)))
- mux_port_num = 2;
- else
- mux_port_num = p.mux->getPort(ID::S).size();
+ RTLIL::SigSpec mux_insig = sigmap(RTLIL::SigSpec{mux->getPort(ID::B), mux->getPort(ID::A)});
+ std::vector<std::set<OpMuxConn>> mux_port_conns(mux_port_num);
+ int found = 0;
- mux_port_conns.resize(mux_port_num);
- }
+ for (int mux_port_id = 0; mux_port_id < mux_port_num; mux_port_id++) {
+ SigSpec mux_insig;
+ if (mux_port_id == mux_port_num - 1) {
+ mux_insig = sigmap(mux->getPort(ID::A));
+ } else {
+ mux_insig = sigmap(mux->getPort(ID::B).extract(mux_port_id * mux_port_size, mux_port_size));
+ }
- mux_port_conns[p.mux_port_id].insert(p);
- }
+ for (int mux_port_offset = 0; mux_port_offset < mux_port_size; ++mux_port_offset) {
+ if (!op_outbit_to_outsig.count(mux_insig[mux_port_offset]))
+ continue;
- std::vector<merged_op_t> merged_ops;
- for (auto& val: mux_port_op_conns) {
+ RTLIL::Cell *cell;
+ int op_outsig_offset;
+ std::tie(cell, op_outsig_offset) = op_outbit_to_outsig.at(mux_insig[mux_port_offset]);
+ SigSpec op_outsig = sigmap(cell->getPort(ID::Y));
+ int op_outsig_size = GetSize(op_outsig);
+ int op_conn_width = 0;
+
+ while (mux_port_offset + op_conn_width < mux_port_size &&
+ op_outsig_offset + op_conn_width < op_outsig_size &&
+ mux_insig[mux_port_offset + op_conn_width] == op_outsig[op_outsig_offset + op_conn_width])
+ op_conn_width++;
+
+ log_assert(op_conn_width >= 1);
+
+ bool skip = false;
+ for (int i = 0; i < op_outsig_size; i++) {
+ int expected = 1;
+ if (i >= op_outsig_offset && i < op_outsig_offset + op_conn_width)
+ expected = 2;
+ if (bit_users[op_outsig[i]] != expected)
+ skip = true;
+ }
+ if (skip) {
+ mux_port_offset += op_conn_width;
+ mux_port_offset--;
+ continue;
+ }
+
+ OpMuxConn inp = {
+ op_outsig.extract(op_outsig_offset, op_conn_width),
+ mux,
+ cell,
+ mux_port_id,
+ mux_port_offset,
+ op_outsig_offset,
+ };
+
+ mux_port_conns[mux_port_id].insert(inp);
+
+ mux_port_offset += op_conn_width;
+ mux_port_offset--;
- RTLIL::Cell* cell = val.first;
- auto &mux_port_conns = val.second;
+ found++;
+ }
+ }
+
+ if (found < 2)
+ continue;
const OpMuxConn *seed = NULL;
@@ -612,12 +527,12 @@ struct OptSharePass : public Pass {
continue;
// Filter mergeable connections whose ops share an operand with seed connection's op
- auto shared_operand = find_shared_operand(seed, mergeable_conns, operand_to_users);
+ auto shared_operand = find_shared_operand(seed, mergeable_conns, operand_to_users, sigmap);
if (shared_operand.empty())
continue;
- check_muxed_operands(mergeable_conns, shared_operand);
+ check_muxed_operands(mergeable_conns, shared_operand, sigmap);
if (mergeable_conns.size() < 2)
continue;
@@ -631,7 +546,7 @@ struct OptSharePass : public Pass {
seed = NULL;
- merged_ops.push_back(merged_op_t{cell, merged_ports, shared_operand});
+ merged_ops.push_back(merged_op_t{mux, merged_ports, shared_operand});
design->scratchpad_set_bool("opt.did_something", true);
}
@@ -647,7 +562,7 @@ struct OptSharePass : public Pass {
log(" %s\n", log_id(op.op));
log("\n");
- merge_operators(module, shared.mux, shared.ports, shared.shared_operand);
+ merge_operators(module, shared.mux, shared.ports, shared.shared_operand, sigmap);
}
}
}
diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc
index 9f226e12d..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
@@ -19,6 +19,7 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
+#include "kernel/ffinit.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -30,7 +31,7 @@ struct OnehotDatabase
bool verbose = false;
bool initialized = false;
- pool<SigBit> init_ones;
+ FfInitVals initvals;
dict<SigSpec, pool<SigSpec>> sig_sources_db;
dict<SigSpec, bool> sig_onehot_cache;
pool<SigSpec> recursion_guard;
@@ -44,19 +45,7 @@ struct OnehotDatabase
log_assert(!initialized);
initialized = true;
- for (auto wire : module->wires())
- {
- auto it = wire->attributes.find(ID::init);
- if (it == wire->attributes.end())
- continue;
-
- auto &val = it->second;
- int width = std::max(GetSize(wire), GetSize(val));
-
- for (int i = 0; i < width; i++)
- if (val[i] == State::S1)
- init_ones.insert(sigmap(SigBit(wire, i)));
- }
+ initvals.set(&sigmap, module);
for (auto cell : module->cells())
{
@@ -119,7 +108,7 @@ struct OnehotDatabase
bool found_init_ones = false;
for (auto bit : sig) {
- if (init_ones.count(bit)) {
+ if (initvals(bit) == State::S1) {
if (found_init_ones) {
if (verbose)
log("%*s - non-onehot init value\n", indent, "");
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 78e2bcbea..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
@@ -20,6 +20,7 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
#include "kernel/modtools.h"
+#include "kernel/ffinit.h"
USING_YOSYS_NAMESPACE
@@ -54,8 +55,7 @@ struct WreduceWorker
std::set<Cell*, IdString::compare_ptr_by_name<Cell>> work_queue_cells;
std::set<SigBit> work_queue_bits;
pool<SigBit> keep_bits;
- dict<SigBit, State> init_bits;
- pool<SigBit> remove_init_bits;
+ FfInitVals initvals;
WreduceWorker(WreduceConfig *config, Module *module) :
config(config), module(module), mi(module) { }
@@ -145,7 +145,7 @@ struct WreduceWorker
SigSpec sig_d = mi.sigmap(cell->getPort(ID::D));
SigSpec sig_q = mi.sigmap(cell->getPort(ID::Q));
bool has_reset = false;
- Const initval, rst_value;
+ Const initval = initvals(sig_q), rst_value;
int width_before = GetSize(sig_q);
@@ -163,20 +163,12 @@ struct WreduceWorker
bool zero_ext = sig_d[GetSize(sig_d)-1] == State::S0;
bool sign_ext = !zero_ext;
- for (int i = 0; i < GetSize(sig_q); i++) {
- SigBit bit = sig_q[i];
- if (init_bits.count(bit))
- initval.bits.push_back(init_bits.at(bit));
- else
- initval.bits.push_back(State::Sx);
- }
-
for (int i = GetSize(sig_q)-1; i >= 0; i--)
{
if (zero_ext && sig_d[i] == State::S0 && (initval[i] == State::S0 || initval[i] == State::Sx) &&
(!has_reset || i >= GetSize(rst_value) || rst_value[i] == State::S0 || rst_value[i] == State::Sx)) {
module->connect(sig_q[i], State::S0);
- remove_init_bits.insert(sig_q[i]);
+ initvals.remove_init(sig_q[i]);
sig_d.remove(i);
sig_q.remove(i);
continue;
@@ -185,7 +177,7 @@ struct WreduceWorker
if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1] && initval[i] == initval[i-1] &&
(!has_reset || i >= GetSize(rst_value) || rst_value[i] == rst_value[i-1])) {
module->connect(sig_q[i], sig_q[i-1]);
- remove_init_bits.insert(sig_q[i]);
+ initvals.remove_init(sig_q[i]);
sig_d.remove(i);
sig_q.remove(i);
continue;
@@ -195,7 +187,7 @@ struct WreduceWorker
if (info == nullptr)
return;
if (!info->is_output && GetSize(info->ports) == 1 && !keep_bits.count(mi.sigmap(sig_q[i]))) {
- remove_init_bits.insert(sig_q[i]);
+ initvals.remove_init(sig_q[i]);
sig_d.remove(i);
sig_q.remove(i);
zero_ext = false;
@@ -409,18 +401,12 @@ struct WreduceWorker
{
// create a copy as mi.sigmap will be updated as we process the module
SigMap init_attr_sigmap = mi.sigmap;
+ initvals.set(&init_attr_sigmap, module);
for (auto w : module->wires()) {
if (w->get_bool_attribute(ID::keep))
for (auto bit : mi.sigmap(w))
keep_bits.insert(bit);
- if (w->attributes.count(ID::init)) {
- Const initval = w->attributes.at(ID::init);
- SigSpec initsig = init_attr_sigmap(w);
- int width = std::min(GetSize(initval), GetSize(initsig));
- for (int i = 0; i < width; i++)
- init_bits[initsig[i]] = initval[i];
- }
}
for (auto c : module->selected_cells())
@@ -469,22 +455,6 @@ struct WreduceWorker
module->connect(nw, SigSpec(w).extract(0, GetSize(nw)));
module->swap_names(w, nw);
}
-
- if (!remove_init_bits.empty()) {
- for (auto w : module->wires()) {
- if (w->attributes.count(ID::init)) {
- Const initval = w->attributes.at(ID::init);
- Const new_initval(State::Sx, GetSize(w));
- SigSpec initsig = init_attr_sigmap(w);
- int width = std::min(GetSize(initval), GetSize(initsig));
- for (int i = 0; i < width; i++) {
- if (!remove_init_bits.count(initsig[i]))
- new_initval[i] = initval[i];
- }
- w->attributes.at(ID::init) = new_initval;
- }
- }
- }
}
};
@@ -588,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 1a57bef7d..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,12 +38,12 @@ $(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))
PEEPOPT_PATTERN = passes/pmgen/peepopt_shiftmul.pmg
PEEPOPT_PATTERN += passes/pmgen/peepopt_muldiv.pmg
-PEEPOPT_PATTERN += passes/pmgen/peepopt_dffmux.pmg
passes/pmgen/peepopt_pm.h: passes/pmgen/pmgen.py $(PEEPOPT_PATTERN)
$(P) mkdir -p passes/pmgen && $(PYTHON_EXECUTABLE) $< -o $@ -p peepopt $(filter-out $<,$^)
@@ -44,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 fff04074b..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
@@ -31,15 +31,15 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
log("Checking %s.%s for iCE40 DSP inference.\n", log_id(pm.module), log_id(st.mul));
- log_debug("ffA: %s %s %s\n", log_id(st.ffA, "--"), log_id(st.ffAholdmux, "--"), log_id(st.ffArstmux, "--"));
- log_debug("ffB: %s %s %s\n", log_id(st.ffB, "--"), log_id(st.ffBholdmux, "--"), log_id(st.ffBrstmux, "--"));
- log_debug("ffCD: %s %s\n", log_id(st.ffCD, "--"), log_id(st.ffCDholdmux, "--"));
+ log_debug("ffA: %s\n", log_id(st.ffA, "--"));
+ log_debug("ffB: %s\n", log_id(st.ffB, "--"));
+ log_debug("ffCD: %s\n", log_id(st.ffCD, "--"));
log_debug("mul: %s\n", log_id(st.mul, "--"));
log_debug("ffFJKG: %s\n", log_id(st.ffFJKG, "--"));
log_debug("ffH: %s\n", log_id(st.ffH, "--"));
log_debug("add: %s\n", log_id(st.add, "--"));
log_debug("mux: %s\n", log_id(st.mux, "--"));
- log_debug("ffO: %s %s %s\n", log_id(st.ffO, "--"), log_id(st.ffOholdmux, "--"), log_id(st.ffOrstmux, "--"));
+ log_debug("ffO: %s\n", log_id(st.ffO, "--"));
log_debug("\n");
if (GetSize(st.sigA) > 16) {
@@ -97,16 +97,16 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
cell->setParam(ID(D_REG), st.ffCD ? State::S1 : State::S0);
SigSpec AHOLD, BHOLD, CDHOLD;
- if (st.ffAholdmux)
- AHOLD = st.ffAholdpol ? st.ffAholdmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffAholdmux->getPort(ID::S));
+ if (st.ffA && st.ffA->hasPort(ID::EN))
+ AHOLD = st.ffA->getParam(ID::EN_POLARITY).as_bool() ? pm.module->Not(NEW_ID, st.ffA->getPort(ID::EN)) : st.ffA->getPort(ID::EN);
else
AHOLD = State::S0;
- if (st.ffBholdmux)
- BHOLD = st.ffBholdpol ? st.ffBholdmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffBholdmux->getPort(ID::S));
+ if (st.ffB && st.ffB->hasPort(ID::EN))
+ BHOLD = st.ffB->getParam(ID::EN_POLARITY).as_bool() ? pm.module->Not(NEW_ID, st.ffB->getPort(ID::EN)) : st.ffB->getPort(ID::EN);
else
BHOLD = State::S0;
- if (st.ffCDholdmux)
- CDHOLD = st.ffCDholdpol ? st.ffCDholdmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffCDholdmux->getPort(ID::S));
+ if (st.ffCD && st.ffCD->hasPort(ID::EN))
+ CDHOLD = st.ffCD->getParam(ID::EN_POLARITY).as_bool() ? pm.module->Not(NEW_ID, st.ffCD->getPort(ID::EN)) : st.ffCD->getPort(ID::EN);
else
CDHOLD = State::S0;
cell->setPort(ID(AHOLD), AHOLD);
@@ -115,12 +115,12 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
cell->setPort(ID(DHOLD), CDHOLD);
SigSpec IRSTTOP, IRSTBOT;
- if (st.ffArstmux)
- IRSTTOP = st.ffArstpol ? st.ffArstmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffArstmux->getPort(ID::S));
+ if (st.ffA && st.ffA->hasPort(ID::ARST))
+ IRSTTOP = st.ffA->getParam(ID::ARST_POLARITY).as_bool() ? st.ffA->getPort(ID::ARST) : pm.module->Not(NEW_ID, st.ffA->getPort(ID::ARST));
else
IRSTTOP = State::S0;
- if (st.ffBrstmux)
- IRSTBOT = st.ffBrstpol ? st.ffBrstmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffBrstmux->getPort(ID::S));
+ if (st.ffB && st.ffB->hasPort(ID::ARST))
+ IRSTBOT = st.ffB->getParam(ID::ARST_POLARITY).as_bool() ? st.ffB->getPort(ID::ARST) : pm.module->Not(NEW_ID, st.ffB->getPort(ID::ARST));
else
IRSTBOT = State::S0;
cell->setPort(ID(IRSTTOP), IRSTTOP);
@@ -207,16 +207,16 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
}
SigSpec OHOLD;
- if (st.ffOholdmux)
- OHOLD = st.ffOholdpol ? st.ffOholdmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffOholdmux->getPort(ID::S));
+ if (st.ffO && st.ffO->hasPort(ID::EN))
+ OHOLD = st.ffO->getParam(ID::EN_POLARITY).as_bool() ? pm.module->Not(NEW_ID, st.ffO->getPort(ID::EN)) : st.ffO->getPort(ID::EN);
else
OHOLD = State::S0;
cell->setPort(ID(OHOLDTOP), OHOLD);
cell->setPort(ID(OHOLDBOT), OHOLD);
SigSpec ORST;
- if (st.ffOrstmux)
- ORST = st.ffOrstpol ? st.ffOrstmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffOrstmux->getPort(ID::S));
+ if (st.ffO && st.ffO->hasPort(ID::ARST))
+ ORST = st.ffO->getParam(ID::ARST_POLARITY).as_bool() ? st.ffO->getPort(ID::ARST) : pm.module->Not(NEW_ID, st.ffO->getPort(ID::ARST));
else
ORST = State::S0;
cell->setPort(ID(ORSTTOP), ORST);
@@ -228,6 +228,8 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
acc_reset = st.mux->getPort(ID::S);
else
acc_reset = pm.module->Not(NEW_ID, st.mux->getPort(ID::S));
+ } else if (st.ffO && st.ffO->hasPort(ID::SRST)) {
+ acc_reset = st.ffO->getParam(ID::SRST_POLARITY).as_bool() ? st.ffO->getPort(ID::SRST) : pm.module->Not(NEW_ID, st.ffO->getPort(ID::SRST));
}
cell->setPort(ID(OLOADTOP), acc_reset);
cell->setPort(ID(OLOADBOT), acc_reset);
diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg
index 2456a49dc..4de479122 100644
--- a/passes/pmgen/ice40_dsp.pmg
+++ b/passes/pmgen/ice40_dsp.pmg
@@ -6,20 +6,16 @@ state <SigSpec> sigA sigB sigCD sigH sigO
state <Cell*> add mux
state <IdString> addAB muxAB
-state <bool> ffAholdpol ffBholdpol ffCDholdpol ffOholdpol
-state <bool> ffArstpol ffBrstpol ffCDrstpol ffOrstpol
-
-state <Cell*> ffA ffAholdmux ffArstmux ffB ffBholdmux ffBrstmux ffCD ffCDholdmux
-state <Cell*> ffFJKG ffH ffO ffOholdmux ffOrstmux
+state <Cell*> ffA ffB ffCD
+state <Cell*> ffFJKG ffH ffO
// subpattern
+state <bool> argSdff
state <SigSpec> argQ argD
-state <bool> ffholdpol ffrstpol
-state <int> ffoffset
udata <SigSpec> dffD dffQ
udata <SigBit> dffclock
-udata <Cell*> dff dffholdmux dffrstmux
-udata <bool> dffholdpol dffrstpol dffclock_pol
+udata <Cell*> dff
+udata <bool> dffclock_pol
match mul
select mul->type.in($mul, \SB_MAC16)
@@ -32,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));
@@ -64,7 +59,7 @@ code sigA sigB sigH
log_assert(nusers(O.extract_end(i)) <= 1);
endcode
-code argQ ffA ffAholdmux ffArstmux ffAholdpol ffArstpol sigA clock clock_pol
+code argQ ffA sigA clock clock_pol
if (mul->type != \SB_MAC16 || !param(mul, \A_REG).as_bool()) {
argQ = sigA;
subpattern(in_dffe);
@@ -72,20 +67,12 @@ code argQ ffA ffAholdmux ffArstmux ffAholdpol ffArstpol sigA clock clock_pol
ffA = dff;
clock = dffclock;
clock_pol = dffclock_pol;
- if (dffrstmux) {
- ffArstmux = dffrstmux;
- ffArstpol = dffrstpol;
- }
- if (dffholdmux) {
- ffAholdmux = dffholdmux;
- ffAholdpol = dffholdpol;
- }
sigA = dffD;
}
}
endcode
-code argQ ffB ffBholdmux ffBrstmux ffBholdpol ffBrstpol sigB clock clock_pol
+code argQ ffB sigB clock clock_pol
if (mul->type != \SB_MAC16 || !param(mul, \B_REG).as_bool()) {
argQ = sigB;
subpattern(in_dffe);
@@ -93,47 +80,44 @@ code argQ ffB ffBholdmux ffBrstmux ffBholdpol ffBrstpol sigB clock clock_pol
ffB = dff;
clock = dffclock;
clock_pol = dffclock_pol;
- if (dffrstmux) {
- ffBrstmux = dffrstmux;
- ffBrstpol = dffrstpol;
- }
- if (dffholdmux) {
- ffBholdmux = dffholdmux;
- ffBholdpol = dffholdpol;
- }
sigB = dffD;
}
}
endcode
-code argD ffFJKG sigH clock clock_pol
+code argD argSdff ffFJKG sigH clock clock_pol
if (nusers(sigH) == 2 &&
(mul->type != \SB_MAC16 ||
(!param(mul, \TOP_8x8_MULT_REG).as_bool() && !param(mul, \BOT_8x8_MULT_REG).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1).as_bool()))) {
argD = sigH;
+ argSdff = false;
subpattern(out_dffe);
if (dff) {
// F/J/K/G do not have a CE-like (hold) input
- if (dffholdmux)
+ if (dff->hasPort(\EN))
goto reject_ffFJKG;
// Reset signal of F/J (IRSTTOP) and K/G (IRSTBOT)
// shared with A and B
- if ((ffArstmux != NULL) != (dffrstmux != NULL))
- goto reject_ffFJKG;
- if ((ffBrstmux != NULL) != (dffrstmux != NULL))
- goto reject_ffFJKG;
- if (ffArstmux) {
- if (port(ffArstmux, \S) != port(dffrstmux, \S))
- goto reject_ffFJKG;
- if (ffArstpol != dffrstpol)
+ if (ffA) {
+ if (ffA->hasPort(\ARST) != dff->hasPort(\ARST))
goto reject_ffFJKG;
+ if (ffA->hasPort(\ARST)) {
+ if (port(ffA, \ARST) != port(dff, \ARST))
+ goto reject_ffFJKG;
+ if (param(ffA, \ARST_POLARITY) != param(dff, \ARST_POLARITY))
+ goto reject_ffFJKG;
+ }
}
- if (ffBrstmux) {
- if (port(ffBrstmux, \S) != port(dffrstmux, \S))
- goto reject_ffFJKG;
- if (ffBrstpol != dffrstpol)
+ if (ffB) {
+ if (ffB->hasPort(\ARST) != dff->hasPort(\ARST))
goto reject_ffFJKG;
+ if (ffB->hasPort(\ARST)) {
+ if (port(ffB, \ARST) != port(dff, \ARST))
+ goto reject_ffFJKG;
+ if (param(ffB, \ARST_POLARITY) != param(dff, \ARST_POLARITY))
+ goto reject_ffFJKG;
+ }
}
ffFJKG = dff;
@@ -146,23 +130,24 @@ reject_ffFJKG: ;
}
endcode
-code argD ffH sigH sigO clock clock_pol
+code argD argSdff ffH sigH sigO clock clock_pol
if (ffFJKG && nusers(sigH) == 2 &&
(mul->type != \SB_MAC16 || !param(mul, \PIPELINE_16x16_MULT_REG2).as_bool())) {
argD = sigH;
+ argSdff = false;
subpattern(out_dffe);
if (dff) {
// H does not have a CE-like (hold) input
- if (dffholdmux)
+ if (dff->hasPort(\EN))
goto reject_ffH;
// Reset signal of H (IRSTBOT) shared with B
- if ((ffBrstmux != NULL) != (dffrstmux != NULL))
+ if (ffB->hasPort(\ARST) != dff->hasPort(\ARST))
goto reject_ffH;
- if (ffBrstmux) {
- if (port(ffBrstmux, \S) != port(dffrstmux, \S))
+ if (ffB->hasPort(\ARST)) {
+ if (port(ffB, \ARST) != port(dff, \ARST))
goto reject_ffH;
- if (ffBrstpol != dffrstpol)
+ if (param(ffB, \ARST_POLARITY) != param(dff, \ARST_POLARITY))
goto reject_ffH;
}
@@ -226,7 +211,7 @@ code sigO
sigO = port(mux, \Y);
endcode
-code argD ffO ffOholdmux ffOrstmux ffOholdpol ffOrstpol sigO sigCD clock clock_pol cd_signed o_lo
+code argD argSdff ffO sigO sigCD clock clock_pol cd_signed o_lo
if (mul->type != \SB_MAC16 ||
// Ensure that register is not already used
((param(mul, \TOPOUTPUT_SELECT).as_int() != 1 && param(mul, \BOTOUTPUT_SELECT).as_int() != 1) &&
@@ -238,6 +223,7 @@ code argD ffO ffOholdmux ffOrstmux ffOholdpol ffOrstpol sigO sigCD clock clock_p
// First try entire sigO
if (nusers(sigO) == 2) {
argD = sigO;
+ argSdff = !mux;
subpattern(out_dffe);
}
@@ -245,6 +231,7 @@ code argD ffO ffOholdmux ffOrstmux ffOholdpol ffOrstpol sigO sigCD clock clock_p
if (!dff && GetSize(sigO) > 16) {
argD = sigO.extract(0, 16);
if (nusers(argD) == 2) {
+ argSdff = !mux;
subpattern(out_dffe);
o_lo = dff;
}
@@ -254,14 +241,6 @@ code argD ffO ffOholdmux ffOrstmux ffOholdpol ffOrstpol sigO sigCD clock clock_p
ffO = dff;
clock = dffclock;
clock_pol = dffclock_pol;
- if (dffrstmux) {
- ffOrstmux = dffrstmux;
- ffOrstpol = dffrstpol;
- }
- if (dffholdmux) {
- ffOholdmux = dffholdmux;
- ffOholdpol = dffholdpol;
- }
sigO.replace(sigO.extract(0, GetSize(dffQ)), dffQ);
}
@@ -274,38 +253,43 @@ code argD ffO ffOholdmux ffOrstmux ffOholdpol ffOrstpol sigO sigCD clock clock_p
sigCD = port(mux, muxAB == \B ? \A : \B);
cd_signed = add && param(add, \A_SIGNED).as_bool() && param(add, \B_SIGNED).as_bool();
+ } else if (dff && dff->hasPort(\SRST)) {
+ if (sigCD != sigO)
+ reject;
+ sigCD = param(dff, \SRST_VALUE);
+
+ cd_signed = add && param(add, \A_SIGNED).as_bool() && param(add, \B_SIGNED).as_bool();
}
}
endcode
-code argQ ffCD ffCDholdmux ffCDholdpol ffCDrstpol sigCD clock clock_pol
+code argQ ffCD sigCD clock clock_pol
if (!sigCD.empty() && sigCD != sigO &&
(mul->type != \SB_MAC16 || (!param(mul, \C_REG).as_bool() && !param(mul, \D_REG).as_bool()))) {
argQ = sigCD;
subpattern(in_dffe);
if (dff) {
- if (dffholdmux) {
- ffCDholdmux = dffholdmux;
- ffCDholdpol = dffholdpol;
- }
-
// Reset signal of C (IRSTTOP) and D (IRSTBOT)
// shared with A and B
- if ((ffArstmux != NULL) != (dffrstmux != NULL))
- goto reject_ffCD;
- if ((ffBrstmux != NULL) != (dffrstmux != NULL))
- goto reject_ffCD;
- if (ffArstmux) {
- if (port(ffArstmux, \S) != port(dffrstmux, \S))
- goto reject_ffCD;
- if (ffArstpol != dffrstpol)
+ if (ffA) {
+ if (ffA->hasPort(\ARST) != dff->hasPort(\ARST))
goto reject_ffCD;
+ if (ffA->hasPort(\ARST)) {
+ if (port(ffA, \ARST) != port(dff, \ARST))
+ goto reject_ffCD;
+ if (param(ffA, \ARST_POLARITY) != param(dff, \ARST_POLARITY))
+ goto reject_ffCD;
+ }
}
- if (ffBrstmux) {
- if (port(ffBrstmux, \S) != port(dffrstmux, \S))
- goto reject_ffCD;
- if (ffBrstpol != dffrstpol)
+ if (ffB) {
+ if (ffB->hasPort(\ARST) != dff->hasPort(\ARST))
goto reject_ffCD;
+ if (ffB->hasPort(\ARST)) {
+ if (port(ffB, \ARST) != port(dff, \ARST))
+ goto reject_ffCD;
+ if (param(ffB, \ARST_POLARITY) != param(dff, \ARST_POLARITY))
+ goto reject_ffCD;
+ }
}
ffCD = dff;
@@ -347,7 +331,7 @@ code
endcode
match ff
- select ff->type.in($dff)
+ select ff->type.in($dff, $dffe)
// DSP48E1 does not support clock inversion
select param(ff, \CLK_POLARITY).as_bool()
@@ -357,8 +341,6 @@ match ff
// Check that the rest of argQ is present
filter GetSize(port(ff, \Q)) >= offset + GetSize(argQ)
filter port(ff, \Q).extract(offset, GetSize(argQ)) == argQ
-
- set ffoffset offset
endmatch
code argQ argD
@@ -378,72 +360,13 @@ code argQ argD
argD = port(ff, \D);
argQ = Q;
dffD.replace(argQ, argD);
- // Only search for ffrstmux if dffD only
- // has two (ff, ffrstmux) users
- if (nusers(dffD) > 2)
- argD = SigSpec();
}
endcode
-match ffrstmux
- if false /* TODO: ice40 resets are actually async */
-
- if !argD.empty()
- select ffrstmux->type.in($mux)
- index <SigSpec> port(ffrstmux, \Y) === argD
-
- choice <IdString> BA {\B, \A}
- // DSP48E1 only supports reset to zero
- select port(ffrstmux, BA).is_fully_zero()
-
- define <bool> pol (BA == \B)
- set ffrstpol pol
- semioptional
-endmatch
-
-code argD
- if (ffrstmux) {
- dffrstmux = ffrstmux;
- dffrstpol = ffrstpol;
- argD = port(ffrstmux, ffrstpol ? \A : \B);
- dffD.replace(port(ffrstmux, \Y), argD);
-
- // Only search for ffholdmux if argQ has at
- // least 3 users (ff, <upstream>, ffrstmux) and
- // dffD only has two (ff, ffrstmux)
- if (!(nusers(argQ) >= 3 && nusers(dffD) == 2))
- argD = SigSpec();
- }
- else
- dffrstmux = nullptr;
-endcode
-
-match ffholdmux
- if !argD.empty()
- select ffholdmux->type.in($mux)
- index <SigSpec> port(ffholdmux, \Y) === argD
- choice <IdString> BA {\B, \A}
- index <SigSpec> port(ffholdmux, BA) === argQ
- define <bool> pol (BA == \B)
- set ffholdpol pol
- semioptional
-endmatch
-
-code argD
- if (ffholdmux) {
- dffholdmux = ffholdmux;
- dffholdpol = ffholdpol;
- argD = port(ffholdmux, ffholdpol ? \A : \B);
- dffD.replace(port(ffholdmux, \Y), argD);
- }
- else
- dffholdmux = nullptr;
-endcode
-
// #######################
subpattern out_dffe
-arg argD argQ clock clock_pol
+arg argD argSdff argQ clock clock_pol
code
dff = nullptr;
@@ -452,101 +375,19 @@ code
reject;
endcode
-match ffholdmux
- select ffholdmux->type.in($mux)
- // ffholdmux output must have two users: ffholdmux and ff.D
- select nusers(port(ffholdmux, \Y)) == 2
-
- choice <IdString> BA {\B, \A}
- // keep-last-value net must have at least three users: ffholdmux, ff, downstream sink(s)
- select nusers(port(ffholdmux, BA)) >= 3
-
- slice offset GetSize(port(ffholdmux, \Y))
- define <IdString> AB (BA == \B ? \A : \B)
- index <SigBit> port(ffholdmux, AB)[offset] === argD[0]
-
- // Check that the rest of argD is present
- filter GetSize(port(ffholdmux, AB)) >= offset + GetSize(argD)
- filter port(ffholdmux, AB).extract(offset, GetSize(argD)) == argD
-
- set ffoffset offset
- define <bool> pol (BA == \B)
- set ffholdpol pol
-
- semioptional
-endmatch
-
-code argD argQ
- dffholdmux = ffholdmux;
- if (ffholdmux) {
- SigSpec AB = port(ffholdmux, ffholdpol ? \A : \B);
- SigSpec Y = port(ffholdmux, \Y);
- argQ = argD;
- argD.replace(AB, Y);
- argQ.replace(AB, port(ffholdmux, ffholdpol ? \B : \A));
-
- dffholdmux = ffholdmux;
- dffholdpol = ffholdpol;
- }
-endcode
-
-match ffrstmux
- if false /* TODO: ice40 resets are actually async */
-
- select ffrstmux->type.in($mux)
- // ffrstmux output must have two users: ffrstmux and ff.D
- select nusers(port(ffrstmux, \Y)) == 2
-
- choice <IdString> BA {\B, \A}
- // DSP48E1 only supports reset to zero
- select port(ffrstmux, BA).is_fully_zero()
-
- slice offset GetSize(port(ffrstmux, \Y))
- define <IdString> AB (BA == \B ? \A : \B)
- index <SigBit> port(ffrstmux, AB)[offset] === argD[0]
-
- // Check that offset is consistent
- filter !ffholdmux || ffoffset == offset
- // Check that the rest of argD is present
- filter GetSize(port(ffrstmux, AB)) >= offset + GetSize(argD)
- filter port(ffrstmux, AB).extract(offset, GetSize(argD)) == argD
-
- set ffoffset offset
- define <bool> pol (AB == \A)
- set ffrstpol pol
-
- semioptional
-endmatch
-
-code argD argQ
- dffrstmux = ffrstmux;
- if (ffrstmux) {
- SigSpec AB = port(ffrstmux, ffrstpol ? \A : \B);
- SigSpec Y = port(ffrstmux, \Y);
- argD.replace(AB, Y);
-
- dffrstmux = ffrstmux;
- dffrstpol = ffrstpol;
- }
-endcode
-
match ff
- select ff->type.in($dff)
+ select ff->type.in($dff, $dffe, $sdff, $sdffce)
// SB_MAC16 does not support clock inversion
select param(ff, \CLK_POLARITY).as_bool()
slice offset GetSize(port(ff, \D))
index <SigBit> port(ff, \D)[offset] === argD[0]
- // Check that offset is consistent
- filter (!ffholdmux && !ffrstmux) || ffoffset == offset
+ // Only allow sync reset if requested.
+ filter argSdff || ff->type.in($dff, $dffe)
// Check that the rest of argD is present
filter GetSize(port(ff, \D)) >= offset + GetSize(argD)
filter port(ff, \D).extract(offset, GetSize(argD)) == argD
- // Check that FF.Q is connected to CE-mux
- filter !ffholdmux || port(ff, \Q).extract(offset, GetSize(argQ)) == argQ
-
- set ffoffset offset
endmatch
code argQ
@@ -559,10 +400,8 @@ code argQ
}
SigSpec D = port(ff, \D);
SigSpec Q = port(ff, \Q);
- if (!ffholdmux) {
- argQ = argD;
- argQ.replace(D, Q);
- }
+ argQ = argD;
+ argQ.replace(D, Q);
for (auto c : argQ.chunks()) {
Const init = c.wire->attributes.at(\init, State::Sx);
@@ -575,7 +414,4 @@ code argQ
dffclock = port(ff, \CLK);
dffclock_pol = param(ff, \CLK_POLARITY).as_bool();
}
- // No enable/reset mux possible without flop
- else if (dffholdmux || dffrstmux)
- reject;
endcode
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 c16b4486d..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
@@ -67,8 +67,6 @@ struct PeepoptPass : public Pass {
GENERATE_PATTERN(peepopt_pm, shiftmul);
else if (genmode == "muldiv")
GENERATE_PATTERN(peepopt_pm, muldiv);
- else if (genmode == "dffmux")
- GENERATE_PATTERN(peepopt_pm, dffmux);
else
log_abort();
return;
@@ -106,7 +104,6 @@ struct PeepoptPass : public Pass {
pm.run_shiftmul();
pm.run_muldiv();
- pm.run_dffmux();
for (auto w : module->wires()) {
auto it = w->attributes.find(ID::init);
diff --git a/passes/pmgen/peepopt_dffmux.pmg b/passes/pmgen/peepopt_dffmux.pmg
deleted file mode 100644
index 0069b0570..000000000
--- a/passes/pmgen/peepopt_dffmux.pmg
+++ /dev/null
@@ -1,171 +0,0 @@
-pattern dffmux
-
-state <IdString> cemuxAB rstmuxBA
-state <SigSpec> sigD
-
-match dff
- select dff->type == $dff
- select GetSize(port(dff, \D)) > 1
-endmatch
-
-code sigD
- sigD = port(dff, \D);
-endcode
-
-match rstmux
- select rstmux->type == $mux
- select GetSize(port(rstmux, \Y)) > 1
- index <SigSpec> port(rstmux, \Y) === sigD
- choice <IdString> BA {\B, \A}
- select port(rstmux, BA).is_fully_const()
- set rstmuxBA BA
- semioptional
-endmatch
-
-code sigD
- if (rstmux)
- sigD = port(rstmux, rstmuxBA == \B ? \A : \B);
-endcode
-
-match cemux
- select cemux->type == $mux
- select GetSize(port(cemux, \Y)) > 1
- index <SigSpec> port(cemux, \Y) === sigD
- choice <IdString> AB {\A, \B}
- index <SigSpec> port(cemux, AB) === port(dff, \Q)
- set cemuxAB AB
- semioptional
-endmatch
-
-code
- if (!cemux && !rstmux)
- reject;
-endcode
-
-code
- Const rst;
- SigSpec D;
- if (cemux) {
- D = port(cemux, cemuxAB == \A ? \B : \A);
- if (rstmux)
- rst = port(rstmux, rstmuxBA).as_const();
- else
- rst = Const(State::Sx, GetSize(D));
- }
- else {
- log_assert(rstmux);
- D = port(rstmux, rstmuxBA == \B ? \A : \B);
- rst = port(rstmux, rstmuxBA).as_const();
- }
- SigSpec Q = port(dff, \Q);
- int width = GetSize(D);
-
- SigSpec dffD = dff->getPort(\D);
- SigSpec dffQ = dff->getPort(\Q);
-
- Const initval;
- for (auto b : Q) {
- auto it = initbits.find(b);
- initval.bits.push_back(it == initbits.end() ? State::Sx : it->second);
- }
-
- auto cmpx = [=](State lhs, State rhs) {
- if (lhs == State::Sx || rhs == State::Sx)
- return true;
- return lhs == rhs;
- };
-
- int i = width-1;
- while (i > 1) {
- if (D[i] != D[i-1])
- break;
- if (!cmpx(rst[i], rst[i-1]))
- break;
- if (!cmpx(initval[i], initval[i-1]))
- break;
- if (!cmpx(rst[i], initval[i]))
- break;
- rminitbits.insert(Q[i]);
- module->connect(Q[i], Q[i-1]);
- i--;
- }
- if (i < width-1) {
- did_something = true;
- if (cemux) {
- SigSpec ceA = cemux->getPort(\A);
- SigSpec ceB = cemux->getPort(\B);
- SigSpec ceY = cemux->getPort(\Y);
- ceA.remove(i, width-1-i);
- ceB.remove(i, width-1-i);
- ceY.remove(i, width-1-i);
- cemux->setPort(\A, ceA);
- cemux->setPort(\B, ceB);
- cemux->setPort(\Y, ceY);
- cemux->fixup_parameters();
- blacklist(cemux);
- }
- if (rstmux) {
- SigSpec rstA = rstmux->getPort(\A);
- SigSpec rstB = rstmux->getPort(\B);
- SigSpec rstY = rstmux->getPort(\Y);
- rstA.remove(i, width-1-i);
- rstB.remove(i, width-1-i);
- rstY.remove(i, width-1-i);
- rstmux->setPort(\A, rstA);
- rstmux->setPort(\B, rstB);
- rstmux->setPort(\Y, rstY);
- rstmux->fixup_parameters();
- blacklist(rstmux);
- }
- dffD.remove(i, width-1-i);
- dffQ.remove(i, width-1-i);
- dff->setPort(\D, dffD);
- dff->setPort(\Q, dffQ);
- dff->fixup_parameters();
- blacklist(dff);
-
- log("dffcemux pattern in %s: dff=%s, cemux=%s, rstmux=%s; removed top %d bits.\n", log_id(module), log_id(dff), log_id(cemux, "n/a"), log_id(rstmux, "n/a"), width-1-i);
- width = i+1;
- }
- if (cemux) {
- SigSpec ceA = cemux->getPort(\A);
- SigSpec ceB = cemux->getPort(\B);
- SigSpec ceY = cemux->getPort(\Y);
-
- int count = 0;
- for (int i = width-1; i >= 0; i--) {
- if (D[i].wire)
- continue;
- if (cmpx(rst[i], D[i].data) && cmpx(initval[i], D[i].data)) {
- count++;
- rminitbits.insert(Q[i]);
- module->connect(Q[i], D[i]);
- ceA.remove(i);
- ceB.remove(i);
- ceY.remove(i);
- dffD.remove(i);
- dffQ.remove(i);
- }
- }
- if (count > 0)
- {
- did_something = true;
-
- cemux->setPort(\A, ceA);
- cemux->setPort(\B, ceB);
- cemux->setPort(\Y, ceY);
- cemux->fixup_parameters();
- blacklist(cemux);
-
- dff->setPort(\D, dffD);
- dff->setPort(\Q, dffQ);
- dff->fixup_parameters();
- blacklist(dff);
-
- log("dffcemux pattern in %s: dff=%s, cemux=%s, rstmux=%s; removed %d constant bits.\n", log_id(module), log_id(dff), log_id(cemux), log_id(rstmux, "n/a"), count);
- }
- }
-
- if (did_something)
- accept;
-endcode
diff --git a/passes/pmgen/peepopt_muldiv.pmg b/passes/pmgen/peepopt_muldiv.pmg
index 7cad759d0..a4e232342 100644
--- a/passes/pmgen/peepopt_muldiv.pmg
+++ b/passes/pmgen/peepopt_muldiv.pmg
@@ -1,16 +1,18 @@
pattern muldiv
state <SigSpec> t x y
+state <bool> is_signed
match mul
select mul->type == $mul
select GetSize(port(mul, \A)) + GetSize(port(mul, \B)) <= GetSize(port(mul, \Y))
endmatch
-code t x y
+code t x y is_signed
t = port(mul, \Y);
x = port(mul, \A);
y = port(mul, \B);
+ is_signed = param(mul, \A_SIGNED).as_bool();
branch;
std::swap(x, y);
endcode
@@ -19,6 +21,7 @@ match div
select div->type.in($div)
index <SigSpec> port(div, \A) === t
index <SigSpec> port(div, \B) === x
+ filter param(div, \A_SIGNED).as_bool() == is_signed
endmatch
code
diff --git a/passes/pmgen/peepopt_shiftmul.pmg b/passes/pmgen/peepopt_shiftmul.pmg
index d4748ae19..d71fbf744 100644
--- a/passes/pmgen/peepopt_shiftmul.pmg
+++ b/passes/pmgen/peepopt_shiftmul.pmg
@@ -31,22 +31,18 @@ match mul
select mul->type.in($mul)
select port(mul, \A).is_fully_const() || port(mul, \B).is_fully_const()
index <SigSpec> port(mul, \Y) === shamt
+ filter !param(mul, \A_SIGNED).as_bool()
endmatch
code
{
IdString const_factor_port = port(mul, \A).is_fully_const() ? \A : \B;
- IdString const_factor_signed = const_factor_port == \A ? \A_SIGNED : \B_SIGNED;
Const const_factor_cnst = port(mul, const_factor_port).as_const();
int const_factor = const_factor_cnst.as_int();
if (GetSize(const_factor_cnst) == 0)
reject;
- if (const_factor_cnst.bits[GetSize(const_factor_cnst)-1] != State::S0 &&
- param(mul, const_factor_signed).as_bool())
- reject;
-
if (GetSize(const_factor_cnst) > 20)
reject;
diff --git a/passes/pmgen/pmgen.py b/passes/pmgen/pmgen.py
index 592a26fa6..6e2fabeeb 100644
--- a/passes/pmgen/pmgen.py
+++ b/passes/pmgen/pmgen.py
@@ -451,7 +451,9 @@ with open(outfile, "w") as f:
current_pattern = None
print(" SigSpec port(Cell *cell, IdString portname) {", file=f)
- print(" return sigmap(cell->getPort(portname));", file=f)
+ print(" try {", file=f)
+ print(" return sigmap(cell->getPort(portname));", file=f)
+ print(" } catch(std::out_of_range&) { log_error(\"Accessing non existing port %s\\n\",portname.c_str()); }", file=f)
print(" }", file=f)
print("", file=f)
print(" SigSpec port(Cell *cell, IdString portname, const SigSpec& defval) {", file=f)
@@ -460,7 +462,9 @@ with open(outfile, "w") as f:
print("", file=f)
print(" Const param(Cell *cell, IdString paramname) {", file=f)
- print(" return cell->getParam(paramname);", file=f)
+ print(" try {", file=f)
+ print(" return cell->getParam(paramname);", file=f)
+ print(" } catch(std::out_of_range&) { log_error(\"Accessing non existing parameter %s\\n\",paramname.c_str()); }", file=f)
print(" }", file=f)
print("", file=f)
print(" Const param(Cell *cell, IdString paramname, const Const& defval) {", file=f)
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 d05157270..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
@@ -263,17 +263,17 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm)
log("Analysing %s.%s for Xilinx DSP packing.\n", log_id(pm.module), log_id(st.dsp));
log_debug("preAdd: %s\n", log_id(st.preAdd, "--"));
- log_debug("ffAD: %s %s %s\n", log_id(st.ffAD, "--"), log_id(st.ffADcemux, "--"), log_id(st.ffADrstmux, "--"));
- log_debug("ffA2: %s %s %s\n", log_id(st.ffA2, "--"), log_id(st.ffA2cemux, "--"), log_id(st.ffA2rstmux, "--"));
- log_debug("ffA1: %s %s %s\n", log_id(st.ffA1, "--"), log_id(st.ffA1cemux, "--"), log_id(st.ffA1rstmux, "--"));
- log_debug("ffB2: %s %s %s\n", log_id(st.ffB2, "--"), log_id(st.ffB2cemux, "--"), log_id(st.ffB2rstmux, "--"));
- log_debug("ffB1: %s %s %s\n", log_id(st.ffB1, "--"), log_id(st.ffB1cemux, "--"), log_id(st.ffB1rstmux, "--"));
- log_debug("ffD: %s %s %s\n", log_id(st.ffD, "--"), log_id(st.ffDcemux, "--"), log_id(st.ffDrstmux, "--"));
+ log_debug("ffAD: %s\n", log_id(st.ffAD, "--"));
+ log_debug("ffA2: %s\n", log_id(st.ffA2, "--"));
+ log_debug("ffA1: %s\n", log_id(st.ffA1, "--"));
+ log_debug("ffB2: %s\n", log_id(st.ffB2, "--"));
+ log_debug("ffB1: %s\n", log_id(st.ffB1, "--"));
+ log_debug("ffD: %s\n", log_id(st.ffD, "--"));
log_debug("dsp: %s\n", log_id(st.dsp, "--"));
- log_debug("ffM: %s %s %s\n", log_id(st.ffM, "--"), log_id(st.ffMcemux, "--"), log_id(st.ffMrstmux, "--"));
+ log_debug("ffM: %s\n", log_id(st.ffM, "--"));
log_debug("postAdd: %s\n", log_id(st.postAdd, "--"));
log_debug("postAddMux: %s\n", log_id(st.postAddMux, "--"));
- log_debug("ffP: %s %s %s\n", log_id(st.ffP, "--"), log_id(st.ffPcemux, "--"), log_id(st.ffPrstmux, "--"));
+ log_debug("ffP: %s\n", log_id(st.ffP, "--"));
log_debug("overflow: %s\n", log_id(st.overflow, "--"));
Cell *cell = st.dsp;
@@ -291,9 +291,10 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm)
cell->setPort(ID(INMODE), Const::from_string("00100"));
if (st.ffAD) {
- if (st.ffADcemux) {
- SigSpec S = st.ffADcemux->getPort(ID::S);
- cell->setPort(ID(CEAD), st.ffADcepol ? S : pm.module->Not(NEW_ID, S));
+ if (st.ffAD->type.in(ID($dffe), ID($sdffe))) {
+ bool pol = st.ffAD->getParam(ID::EN_POLARITY).as_bool();
+ SigSpec S = st.ffAD->getPort(ID::EN);
+ cell->setPort(ID(CEAD), pol ? S : pm.module->Not(NEW_ID, S));
}
else
cell->setPort(ID(CEAD), State::S1);
@@ -363,30 +364,24 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm)
{
cell->setPort(ID::CLK, st.clock);
- auto f = [&pm,cell](SigSpec &A, Cell* ff, Cell* cemux, bool cepol, IdString ceport, Cell* rstmux, bool rstpol, IdString rstport) {
+ auto f = [&pm,cell](SigSpec &A, Cell* ff, IdString ceport, IdString rstport) {
SigSpec D = ff->getPort(ID::D);
SigSpec Q = pm.sigmap(ff->getPort(ID::Q));
if (!A.empty())
A.replace(Q, D);
- if (rstmux) {
- SigSpec Y = rstmux->getPort(ID::Y);
- SigSpec AB = rstmux->getPort(rstpol ? ID::A : ID::B);
- if (!A.empty())
- A.replace(Y, AB);
- if (rstport != IdString()) {
- SigSpec S = rstmux->getPort(ID::S);
- cell->setPort(rstport, rstpol ? S : pm.module->Not(NEW_ID, S));
+ if (rstport != IdString()) {
+ if (ff->type.in(ID($sdff), ID($sdffe))) {
+ SigSpec srst = ff->getPort(ID::SRST);
+ bool rstpol = ff->getParam(ID::SRST_POLARITY).as_bool();
+ cell->setPort(rstport, rstpol ? srst : pm.module->Not(NEW_ID, srst));
+ } else {
+ cell->setPort(rstport, State::S0);
}
}
- else if (rstport != IdString())
- cell->setPort(rstport, State::S0);
- if (cemux) {
- SigSpec Y = cemux->getPort(ID::Y);
- SigSpec BA = cemux->getPort(cepol ? ID::B : ID::A);
- SigSpec S = cemux->getPort(ID::S);
- if (!A.empty())
- A.replace(Y, BA);
- cell->setPort(ceport, cepol ? S : pm.module->Not(NEW_ID, S));
+ if (ff->type.in(ID($dffe), ID($sdffe))) {
+ SigSpec ce = ff->getPort(ID::EN);
+ bool cepol = ff->getParam(ID::EN_POLARITY).as_bool();
+ cell->setPort(ceport, cepol ? ce : pm.module->Not(NEW_ID, ce));
}
else
cell->setPort(ceport, State::S1);
@@ -404,9 +399,9 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm)
if (st.ffA2) {
SigSpec A = cell->getPort(ID::A);
- f(A, st.ffA2, st.ffA2cemux, st.ffA2cepol, ID(CEA2), st.ffA2rstmux, st.ffArstpol, ID(RSTA));
+ f(A, st.ffA2, ID(CEA2), ID(RSTA));
if (st.ffA1) {
- f(A, st.ffA1, st.ffA1cemux, st.ffA1cepol, ID(CEA1), st.ffA1rstmux, st.ffArstpol, IdString());
+ f(A, st.ffA1, ID(CEA1), IdString());
cell->setParam(ID(AREG), 2);
cell->setParam(ID(ACASCREG), 2);
}
@@ -419,9 +414,9 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm)
}
if (st.ffB2) {
SigSpec B = cell->getPort(ID::B);
- f(B, st.ffB2, st.ffB2cemux, st.ffB2cepol, ID(CEB2), st.ffB2rstmux, st.ffBrstpol, ID(RSTB));
+ f(B, st.ffB2, ID(CEB2), ID(RSTB));
if (st.ffB1) {
- f(B, st.ffB1, st.ffB1cemux, st.ffB1cepol, ID(CEB1), st.ffB1rstmux, st.ffBrstpol, IdString());
+ f(B, st.ffB1, ID(CEB1), IdString());
cell->setParam(ID(BREG), 2);
cell->setParam(ID(BCASCREG), 2);
}
@@ -434,20 +429,20 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm)
}
if (st.ffD) {
SigSpec D = cell->getPort(ID::D);
- f(D, st.ffD, st.ffDcemux, st.ffDcepol, ID(CED), st.ffDrstmux, st.ffDrstpol, ID(RSTD));
+ f(D, st.ffD, ID(CED), ID(RSTD));
pm.add_siguser(D, cell);
cell->setPort(ID::D, D);
cell->setParam(ID(DREG), 1);
}
if (st.ffM) {
SigSpec M; // unused
- f(M, st.ffM, st.ffMcemux, st.ffMcepol, ID(CEM), st.ffMrstmux, st.ffMrstpol, ID(RSTM));
+ f(M, st.ffM, ID(CEM), ID(RSTM));
st.ffM->connections_.at(ID::Q).replace(st.sigM, pm.module->addWire(NEW_ID, GetSize(st.sigM)));
cell->setParam(ID(MREG), State::S1);
}
if (st.ffP) {
SigSpec P; // unused
- f(P, st.ffP, st.ffPcemux, st.ffPcepol, ID(CEP), st.ffPrstmux, st.ffPrstpol, ID(RSTP));
+ f(P, st.ffP, ID(CEP), ID(RSTP));
st.ffP->connections_.at(ID::Q).replace(st.sigP, pm.module->addWire(NEW_ID, GetSize(st.sigP)));
cell->setParam(ID(PREG), State::S1);
}
@@ -495,16 +490,16 @@ void xilinx_dsp48a_pack(xilinx_dsp48a_pm &pm)
log("Analysing %s.%s for Xilinx DSP48A/DSP48A1 packing.\n", log_id(pm.module), log_id(st.dsp));
log_debug("preAdd: %s\n", log_id(st.preAdd, "--"));
- log_debug("ffA1: %s %s %s\n", log_id(st.ffA1, "--"), log_id(st.ffA1cemux, "--"), log_id(st.ffA1rstmux, "--"));
- log_debug("ffA0: %s %s %s\n", log_id(st.ffA0, "--"), log_id(st.ffA0cemux, "--"), log_id(st.ffA0rstmux, "--"));
- log_debug("ffB1: %s %s %s\n", log_id(st.ffB1, "--"), log_id(st.ffB1cemux, "--"), log_id(st.ffB1rstmux, "--"));
- log_debug("ffB0: %s %s %s\n", log_id(st.ffB0, "--"), log_id(st.ffB0cemux, "--"), log_id(st.ffB0rstmux, "--"));
- log_debug("ffD: %s %s %s\n", log_id(st.ffD, "--"), log_id(st.ffDcemux, "--"), log_id(st.ffDrstmux, "--"));
+ log_debug("ffA1: %s\n", log_id(st.ffA1, "--"));
+ log_debug("ffA0: %s\n", log_id(st.ffA0, "--"));
+ log_debug("ffB1: %s\n", log_id(st.ffB1, "--"));
+ log_debug("ffB0: %s\n", log_id(st.ffB0, "--"));
+ log_debug("ffD: %s\n", log_id(st.ffD, "--"));
log_debug("dsp: %s\n", log_id(st.dsp, "--"));
- log_debug("ffM: %s %s %s\n", log_id(st.ffM, "--"), log_id(st.ffMcemux, "--"), log_id(st.ffMrstmux, "--"));
+ log_debug("ffM: %s\n", log_id(st.ffM, "--"));
log_debug("postAdd: %s\n", log_id(st.postAdd, "--"));
log_debug("postAddMux: %s\n", log_id(st.postAddMux, "--"));
- log_debug("ffP: %s %s %s\n", log_id(st.ffP, "--"), log_id(st.ffPcemux, "--"), log_id(st.ffPrstmux, "--"));
+ log_debug("ffP: %s\n", log_id(st.ffP, "--"));
Cell *cell = st.dsp;
SigSpec &opmode = cell->connections_.at(ID(OPMODE));
@@ -556,30 +551,24 @@ void xilinx_dsp48a_pack(xilinx_dsp48a_pm &pm)
{
cell->setPort(ID::CLK, st.clock);
- auto f = [&pm,cell](SigSpec &A, Cell* ff, Cell* cemux, bool cepol, IdString ceport, Cell* rstmux, bool rstpol, IdString rstport) {
+ auto f = [&pm,cell](SigSpec &A, Cell* ff, IdString ceport, IdString rstport) {
SigSpec D = ff->getPort(ID::D);
SigSpec Q = pm.sigmap(ff->getPort(ID::Q));
if (!A.empty())
A.replace(Q, D);
- if (rstmux) {
- SigSpec Y = rstmux->getPort(ID::Y);
- SigSpec AB = rstmux->getPort(rstpol ? ID::A : ID::B);
- if (!A.empty())
- A.replace(Y, AB);
- if (rstport != IdString()) {
- SigSpec S = rstmux->getPort(ID::S);
- cell->setPort(rstport, rstpol ? S : pm.module->Not(NEW_ID, S));
+ if (rstport != IdString()) {
+ if (ff->type.in(ID($sdff), ID($sdffe))) {
+ SigSpec srst = ff->getPort(ID::SRST);
+ bool rstpol = ff->getParam(ID::SRST_POLARITY).as_bool();
+ cell->setPort(rstport, rstpol ? srst : pm.module->Not(NEW_ID, srst));
+ } else {
+ cell->setPort(rstport, State::S0);
}
}
- else if (rstport != IdString())
- cell->setPort(rstport, State::S0);
- if (cemux) {
- SigSpec Y = cemux->getPort(ID::Y);
- SigSpec BA = cemux->getPort(cepol ? ID::B : ID::A);
- SigSpec S = cemux->getPort(ID::S);
- if (!A.empty())
- A.replace(Y, BA);
- cell->setPort(ceport, cepol ? S : pm.module->Not(NEW_ID, S));
+ if (ff->type.in(ID($dffe), ID($sdffe))) {
+ SigSpec ce = ff->getPort(ID::EN);
+ bool cepol = ff->getParam(ID::EN_POLARITY).as_bool();
+ cell->setPort(ceport, cepol ? ce : pm.module->Not(NEW_ID, ce));
}
else
cell->setPort(ceport, State::S1);
@@ -598,11 +587,11 @@ void xilinx_dsp48a_pack(xilinx_dsp48a_pm &pm)
if (st.ffA0 || st.ffA1) {
SigSpec A = cell->getPort(ID::A);
if (st.ffA1) {
- f(A, st.ffA1, st.ffA1cemux, st.ffAcepol, ID(CEA), st.ffA1rstmux, st.ffArstpol, ID(RSTA));
+ f(A, st.ffA1, ID(CEA), ID(RSTA));
cell->setParam(ID(A1REG), 1);
}
if (st.ffA0) {
- f(A, st.ffA0, st.ffA0cemux, st.ffAcepol, ID(CEA), st.ffA0rstmux, st.ffArstpol, ID(RSTA));
+ f(A, st.ffA0, ID(CEA), ID(RSTA));
cell->setParam(ID(A0REG), 1);
}
pm.add_siguser(A, cell);
@@ -611,11 +600,11 @@ void xilinx_dsp48a_pack(xilinx_dsp48a_pm &pm)
if (st.ffB0 || st.ffB1) {
SigSpec B = cell->getPort(ID::B);
if (st.ffB1) {
- f(B, st.ffB1, st.ffB1cemux, st.ffBcepol, ID(CEB), st.ffB1rstmux, st.ffBrstpol, ID(RSTB));
+ f(B, st.ffB1, ID(CEB), ID(RSTB));
cell->setParam(ID(B1REG), 1);
}
if (st.ffB0) {
- f(B, st.ffB0, st.ffB0cemux, st.ffBcepol, ID(CEB), st.ffB0rstmux, st.ffBrstpol, ID(RSTB));
+ f(B, st.ffB0, ID(CEB), ID(RSTB));
cell->setParam(ID(B0REG), 1);
}
pm.add_siguser(B, cell);
@@ -623,20 +612,20 @@ void xilinx_dsp48a_pack(xilinx_dsp48a_pm &pm)
}
if (st.ffD) {
SigSpec D = cell->getPort(ID::D);
- f(D, st.ffD, st.ffDcemux, st.ffDcepol, ID(CED), st.ffDrstmux, st.ffDrstpol, ID(RSTD));
+ f(D, st.ffD, ID(CED), ID(RSTD));
pm.add_siguser(D, cell);
cell->setPort(ID::D, D);
cell->setParam(ID(DREG), 1);
}
if (st.ffM) {
SigSpec M; // unused
- f(M, st.ffM, st.ffMcemux, st.ffMcepol, ID(CEM), st.ffMrstmux, st.ffMrstpol, ID(RSTM));
+ f(M, st.ffM, ID(CEM), ID(RSTM));
st.ffM->connections_.at(ID::Q).replace(st.sigM, pm.module->addWire(NEW_ID, GetSize(st.sigM)));
cell->setParam(ID(MREG), State::S1);
}
if (st.ffP) {
SigSpec P; // unused
- f(P, st.ffP, st.ffPcemux, st.ffPcepol, ID(CEP), st.ffPrstmux, st.ffPrstpol, ID(RSTP));
+ f(P, st.ffP, ID(CEP), ID(RSTP));
st.ffP->connections_.at(ID::Q).replace(st.sigP, pm.module->addWire(NEW_ID, GetSize(st.sigP)));
cell->setParam(ID(PREG), State::S1);
}
@@ -677,7 +666,7 @@ void xilinx_dsp_packC(xilinx_dsp_CREG_pm &pm)
auto &st = pm.st_xilinx_dsp_packC;
log_debug("Analysing %s.%s for Xilinx DSP packing (CREG).\n", log_id(pm.module), log_id(st.dsp));
- log_debug("ffC: %s %s %s\n", log_id(st.ffC, "--"), log_id(st.ffCcemux, "--"), log_id(st.ffCrstmux, "--"));
+ log_debug("ffC: %s\n", log_id(st.ffC, "--"));
Cell *cell = st.dsp;
@@ -685,30 +674,24 @@ void xilinx_dsp_packC(xilinx_dsp_CREG_pm &pm)
{
cell->setPort(ID::CLK, st.clock);
- auto f = [&pm,cell](SigSpec &A, Cell* ff, Cell* cemux, bool cepol, IdString ceport, Cell* rstmux, bool rstpol, IdString rstport) {
+ auto f = [&pm,cell](SigSpec &A, Cell* ff, IdString ceport, IdString rstport) {
SigSpec D = ff->getPort(ID::D);
SigSpec Q = pm.sigmap(ff->getPort(ID::Q));
if (!A.empty())
A.replace(Q, D);
- if (rstmux) {
- SigSpec Y = rstmux->getPort(ID::Y);
- SigSpec AB = rstmux->getPort(rstpol ? ID::A : ID::B);
- if (!A.empty())
- A.replace(Y, AB);
- if (rstport != IdString()) {
- SigSpec S = rstmux->getPort(ID::S);
- cell->setPort(rstport, rstpol ? S : pm.module->Not(NEW_ID, S));
+ if (rstport != IdString()) {
+ if (ff->type.in(ID($sdff), ID($sdffe))) {
+ SigSpec srst = ff->getPort(ID::SRST);
+ bool rstpol = ff->getParam(ID::SRST_POLARITY).as_bool();
+ cell->setPort(rstport, rstpol ? srst : pm.module->Not(NEW_ID, srst));
+ } else {
+ cell->setPort(rstport, State::S0);
}
}
- else if (rstport != IdString())
- cell->setPort(rstport, State::S0);
- if (cemux) {
- SigSpec Y = cemux->getPort(ID::Y);
- SigSpec BA = cemux->getPort(cepol ? ID::B : ID::A);
- SigSpec S = cemux->getPort(ID::S);
- if (!A.empty())
- A.replace(Y, BA);
- cell->setPort(ceport, cepol ? S : pm.module->Not(NEW_ID, S));
+ if (ff->type.in(ID($dffe), ID($sdffe))) {
+ SigSpec ce = ff->getPort(ID::EN);
+ bool cepol = ff->getParam(ID::EN_POLARITY).as_bool();
+ cell->setPort(ceport, cepol ? ce : pm.module->Not(NEW_ID, ce));
}
else
cell->setPort(ceport, State::S1);
@@ -726,7 +709,7 @@ void xilinx_dsp_packC(xilinx_dsp_CREG_pm &pm)
if (st.ffC) {
SigSpec C = cell->getPort(ID::C);
- f(C, st.ffC, st.ffCcemux, st.ffCcepol, ID(CEC), st.ffCrstmux, st.ffCrstpol, ID(RSTC));
+ f(C, st.ffC, ID(CEC), ID(RSTC));
pm.add_siguser(C, cell);
cell->setPort(ID::C, C);
cell->setParam(ID(CREG), 1);
diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg
index d40f073c9..0cd23c09d 100644
--- a/passes/pmgen/xilinx_dsp.pmg
+++ b/passes/pmgen/xilinx_dsp.pmg
@@ -2,9 +2,7 @@
// forms the `xilinx_dsp` pass described in xilinx_dsp.cc
// At a high level, it works as follows:
// ( 1) Starting from a DSP48E1 cell
-// ( 2) Match the driver of the 'A' input to a possible $dff cell (ADREG)
-// (attached to at most two $mux cells that implement clock-enable or
-// reset functionality, using a subpattern discussed below)
+// ( 2) Match the driver of the 'A' input to a possible $sdffe cell (ADREG)
// If ADREG matched, treat 'A' input as input of ADREG
// ( 3) Match the driver of the 'A' and 'D' inputs for a possible $add cell
// (pre-adder)
@@ -44,7 +42,7 @@
// DSP48E1 cells inferred from multiply operations by Yosys, as well as for
// user instantiations that may already contain the cells being packed...
// (though the latter is currently untested)
-// - Since the $dff-with-optional-clock-enable-or-reset-mux pattern is used
+// - Since the $sdffe pattern is used
// for each *REG match, it has been factored out into two subpatterns:
// in_dffe and out_dffe located at the bottom of this file.
// - Matching for pattern detector features is currently incomplete. For
@@ -57,20 +55,15 @@ pattern xilinx_dsp_pack
state <SigBit> clock
state <SigSpec> sigA sigB sigC sigD sigM sigP
state <IdString> postAddAB postAddMuxAB
-state <bool> ffA1cepol ffA2cepol ffADcepol ffB1cepol ffB2cepol ffDcepol ffMcepol ffPcepol
-state <bool> ffArstpol ffADrstpol ffBrstpol ffDrstpol ffMrstpol ffPrstpol
-state <Cell*> ffAD ffADcemux ffADrstmux ffA1 ffA1cemux ffA1rstmux ffA2 ffA2cemux ffA2rstmux
-state <Cell*> ffB1 ffB1cemux ffB1rstmux ffB2 ffB2cemux ffB2rstmux
-state <Cell*> ffD ffDcemux ffDrstmux ffM ffMcemux ffMrstmux ffP ffPcemux ffPrstmux
+state <Cell*> ffAD ffA1 ffA2
+state <Cell*> ffB1 ffB2
+state <Cell*> ffD ffM ffP
// Variables used for subpatterns
state <SigSpec> argQ argD
-state <bool> ffcepol ffrstpol
-state <int> ffoffset
udata <SigSpec> dffD dffQ
udata <SigBit> dffclock
-udata <Cell*> dff dffcemux dffrstmux
-udata <bool> dffcepol dffrstpol
+udata <Cell*> dff
// (1) Starting from a DSP48E1 cell
match dsp
@@ -115,25 +108,15 @@ code sigA sigB sigC sigD sigM clock
clock = port(dsp, \CLK, SigBit());
endcode
-// (2) Match the driver of the 'A' input to a possible $dff cell (ADREG)
-// (attached to at most two $mux cells that implement clock-enable or
-// reset functionality, using a subpattern discussed above)
+// (2) Match the driver of the 'A' input to a possible $sdffe cell (ADREG)
// If matched, treat 'A' input as input of ADREG
-code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock
+code argQ ffAD sigA clock
if (param(dsp, \ADREG).as_int() == 0) {
argQ = sigA;
subpattern(in_dffe);
if (dff) {
ffAD = dff;
clock = dffclock;
- if (dffrstmux) {
- ffADrstmux = dffrstmux;
- ffADrstpol = dffrstpol;
- }
- if (dffcemux) {
- ffADcemux = dffcemux;
- ffADcepol = dffcepol;
- }
sigA = dffD;
}
}
@@ -172,7 +155,7 @@ endcode
// (4) If pre-adder was present, find match 'A' input for A2REG
// If pre-adder was not present, move ADREG to A2REG
// Then match 'A' input for A1REG
-code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock ffA2 ffA2cemux ffA2rstmux ffA2cepol ffArstpol ffA1 ffA1cemux ffA1rstmux ffA1cepol
+code argQ ffAD sigA clock ffA2 ffA1
// Only search for ffA2 if there was a pre-adder
// (otherwise ffA2 would have been matched as ffAD)
if (preAdd) {
@@ -182,14 +165,6 @@ code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock ffA2 ffA2cem
if (dff) {
ffA2 = dff;
clock = dffclock;
- if (dffrstmux) {
- ffA2rstmux = dffrstmux;
- ffArstpol = dffrstpol;
- }
- if (dffcemux) {
- ffA2cepol = dffcepol;
- ffA2cemux = dffcemux;
- }
sigA = dffD;
}
}
@@ -197,12 +172,8 @@ code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock ffA2 ffA2cem
// And if there wasn't a pre-adder,
// move AD register to A
else if (ffAD) {
- log_assert(!ffA2 && !ffA2cemux && !ffA2rstmux);
+ log_assert(!ffA2);
std::swap(ffA2, ffAD);
- std::swap(ffA2cemux, ffADcemux);
- std::swap(ffA2rstmux, ffADrstmux);
- ffA2cepol = ffADcepol;
- ffArstpol = ffADrstpol;
}
// Now attempt to match A1
@@ -210,23 +181,23 @@ code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock ffA2 ffA2cem
argQ = sigA;
subpattern(in_dffe);
if (dff) {
- if ((ffA2rstmux != nullptr) ^ (dffrstmux != nullptr))
+ if (dff->type != ffA2->type)
goto ffA1_end;
- if (dffrstmux) {
- if (ffArstpol != dffrstpol)
+ if (dff->type.in($sdff, $sdffe, $sdffce)) {
+ if (param(dff, \SRST_POLARITY) != param(ffA2, \SRST_POLARITY))
goto ffA1_end;
- if (port(ffA2rstmux, \S) != port(dffrstmux, \S))
+ if (port(dff, \SRST) != port(ffA2, \SRST))
+ goto ffA1_end;
+ }
+ if (dff->type.in($dffe, $sdffe, $sdffce)) {
+ if (param(dff, \EN_POLARITY) != param(ffA2, \EN_POLARITY))
+ goto ffA1_end;
+ if (port(dff, \EN) != port(ffA2, \EN))
goto ffA1_end;
- ffA1rstmux = dffrstmux;
}
ffA1 = dff;
clock = dffclock;
-
- if (dffcemux) {
- ffA1cemux = dffcemux;
- ffA1cepol = dffcepol;
- }
sigA = dffD;
ffA1_end: ;
@@ -236,21 +207,13 @@ endcode
// (5) Match 'B' input for B2REG
// If B2REG, then match 'B' input for B1REG
-code argQ ffB2 ffB2cemux ffB2rstmux ffB2cepol ffBrstpol sigB clock ffB1 ffB1cemux ffB1rstmux ffB1cepol
+code argQ ffB2 sigB clock ffB1
if (param(dsp, \BREG).as_int() == 0) {
argQ = sigB;
subpattern(in_dffe);
if (dff) {
ffB2 = dff;
clock = dffclock;
- if (dffrstmux) {
- ffB2rstmux = dffrstmux;
- ffBrstpol = dffrstpol;
- }
- if (dffcemux) {
- ffB2cemux = dffcemux;
- ffB2cepol = dffcepol;
- }
sigB = dffD;
// Now attempt to match B1
@@ -258,23 +221,23 @@ code argQ ffB2 ffB2cemux ffB2rstmux ffB2cepol ffBrstpol sigB clock ffB1 ffB1cemu
argQ = sigB;
subpattern(in_dffe);
if (dff) {
- if ((ffB2rstmux != nullptr) ^ (dffrstmux != nullptr))
+ if (dff->type != ffB2->type)
goto ffB1_end;
- if (dffrstmux) {
- if (ffBrstpol != dffrstpol)
+ if (dff->type.in($sdff, $sdffe, $sdffce)) {
+ if (param(dff, \SRST_POLARITY) != param(ffB2, \SRST_POLARITY))
+ goto ffB1_end;
+ if (port(dff, \SRST) != port(ffB2, \SRST))
+ goto ffB1_end;
+ }
+ if (dff->type.in($dffe, $sdffe, $sdffce)) {
+ if (param(dff, \EN_POLARITY) != param(ffB2, \EN_POLARITY))
goto ffB1_end;
- if (port(ffB2rstmux, \S) != port(dffrstmux, \S))
+ if (port(dff, \EN) != port(ffB2, \EN))
goto ffB1_end;
- ffB1rstmux = dffrstmux;
}
ffB1 = dff;
clock = dffclock;
-
- if (dffcemux) {
- ffB1cemux = dffcemux;
- ffB1cepol = dffcepol;
- }
sigB = dffD;
ffB1_end: ;
@@ -286,42 +249,26 @@ ffB1_end: ;
endcode
// (6) Match 'D' input for DREG
-code argQ ffD ffDcemux ffDrstmux ffDcepol ffDrstpol sigD clock
+code argQ ffD sigD clock
if (param(dsp, \DREG).as_int() == 0) {
argQ = sigD;
subpattern(in_dffe);
if (dff) {
ffD = dff;
clock = dffclock;
- if (dffrstmux) {
- ffDrstmux = dffrstmux;
- ffDrstpol = dffrstpol;
- }
- if (dffcemux) {
- ffDcemux = dffcemux;
- ffDcepol = dffcepol;
- }
sigD = dffD;
}
}
endcode
// (7) Match 'P' output that exclusively drives an MREG
-code argD ffM ffMcemux ffMrstmux ffMcepol ffMrstpol sigM sigP clock
+code argD ffM sigM sigP clock
if (param(dsp, \MREG).as_int() == 0 && nusers(sigM) == 2) {
argD = sigM;
subpattern(out_dffe);
if (dff) {
ffM = dff;
clock = dffclock;
- if (dffrstmux) {
- ffMrstmux = dffrstmux;
- ffMrstpol = dffrstpol;
- }
- if (dffcemux) {
- ffMcemux = dffcemux;
- ffMcepol = dffcepol;
- }
sigM = dffQ;
}
}
@@ -340,9 +287,7 @@ match postAdd
select postAdd->type.in($add)
select GetSize(port(postAdd, \Y)) <= 48
choice <IdString> AB {\A, \B}
- select nusers(port(postAdd, AB)) <= 3
- filter ffMcemux || nusers(port(postAdd, AB)) == 2
- filter !ffMcemux || nusers(port(postAdd, AB)) == 3
+ select nusers(port(postAdd, AB)) == 2
index <SigBit> port(postAdd, AB)[0] === sigP[0]
filter GetSize(port(postAdd, AB)) >= GetSize(sigP)
@@ -362,25 +307,14 @@ code sigC sigP
endcode
// (9) Match 'P' output that exclusively drives a PREG
-code argD ffP ffPcemux ffPrstmux ffPcepol ffPrstpol sigP clock
+code argD ffP sigP clock
if (param(dsp, \PREG).as_int() == 0) {
- int users = 2;
- // If ffMcemux and no postAdd new-value net must have three users: ffMcemux, ffM and ffPcemux
- if (ffMcemux && !postAdd) users++;
- if (nusers(sigP) == users) {
+ if (nusers(sigP) == 2) {
argD = sigP;
subpattern(out_dffe);
if (dff) {
ffP = dff;
clock = dffclock;
- if (dffrstmux) {
- ffPrstmux = dffrstmux;
- ffPrstpol = dffrstpol;
- }
- if (dffcemux) {
- ffPcemux = dffcemux;
- ffPcepol = dffcepol;
- }
sigP = dffQ;
}
}
@@ -441,22 +375,9 @@ endcode
// #######################
// Subpattern for matching against input registers, based on knowledge of the
-// 'Q' input. Typically, identifying registers with clock-enable and reset
-// capability would be a task would be handled by other Yosys passes such as
-// dff2dffe, but since DSP inference happens much before this, these patterns
-// have to be manually identified.
-// At a high level:
-// (1) Starting from a $dff cell that (partially or fully) drives the given
-// 'Q' argument
-// (2) Match for a $mux cell implementing synchronous reset semantics ---
-// one that exclusively drives the 'D' input of the $dff, with one of its
-// $mux inputs being fully zero
-// (3) Match for a $mux cell implement clock enable semantics --- one that
-// exclusively drives the 'D' input of the $dff (or the other input of
-// the reset $mux) and where one of this $mux's inputs is connected to
-// the 'Q' output of the $dff
+// 'Q' input.
subpattern in_dffe
-arg argD argQ clock
+arg argQ clock
code
dff = nullptr;
@@ -479,13 +400,14 @@ code
}
endcode
-// (1) Starting from a $dff cell that (partially or fully) drives the given
-// 'Q' argument
match ff
- select ff->type.in($dff)
+ select ff->type.in($dff, $dffe, $sdff, $sdffe)
// DSP48E1 does not support clock inversion
select param(ff, \CLK_POLARITY).as_bool()
+ // Check that reset value, if present, is fully 0.
+ filter ff->type.in($dff, $dffe) || param(ff, \SRST_VALUE).is_fully_zero()
+
slice offset GetSize(port(ff, \D))
index <SigBit> port(ff, \Q)[offset] === argQ[0]
@@ -494,82 +416,16 @@ match ff
filter port(ff, \Q).extract(offset, GetSize(argQ)) == argQ
filter clock == SigBit() || port(ff, \CLK) == clock
-
- set ffoffset offset
endmatch
-code argQ argD
+code argQ
SigSpec Q = port(ff, \Q);
dff = ff;
dffclock = port(ff, \CLK);
dffD = argQ;
- argD = port(ff, \D);
+ SigSpec D = port(ff, \D);
argQ = Q;
- dffD.replace(argQ, argD);
- // Only search for ffrstmux if dffD only
- // has two (ff, ffrstmux) users
- if (nusers(dffD) > 2)
- argD = SigSpec();
-endcode
-
-// (2) Match for a $mux cell implementing synchronous reset semantics ---
-// exclusively drives the 'D' input of the $dff, with one of the $mux
-// inputs being fully zero
-match ffrstmux
- if !argD.empty()
- select ffrstmux->type.in($mux)
- index <SigSpec> port(ffrstmux, \Y) === argD
-
- choice <IdString> BA {\B, \A}
- // DSP48E1 only supports reset to zero
- select port(ffrstmux, BA).is_fully_zero()
-
- define <bool> pol (BA == \B)
- set ffrstpol pol
- semioptional
-endmatch
-
-code argD
- if (ffrstmux) {
- dffrstmux = ffrstmux;
- dffrstpol = ffrstpol;
- argD = port(ffrstmux, ffrstpol ? \A : \B);
- dffD.replace(port(ffrstmux, \Y), argD);
-
- // Only search for ffcemux if argQ has at
- // least 3 users (ff, <upstream>, ffrstmux) and
- // dffD only has two (ff, ffrstmux)
- if (!(nusers(argQ) >= 3 && nusers(dffD) == 2))
- argD = SigSpec();
- }
- else
- dffrstmux = nullptr;
-endcode
-
-// (3) Match for a $mux cell implement clock enable semantics --- one that
-// exclusively drives the 'D' input of the $dff (or the other input of
-// the reset $mux) and where one of this $mux's inputs is connected to
-// the 'Q' output of the $dff
-match ffcemux
- if !argD.empty()
- select ffcemux->type.in($mux)
- index <SigSpec> port(ffcemux, \Y) === argD
- choice <IdString> AB {\A, \B}
- index <SigSpec> port(ffcemux, AB) === argQ
- define <bool> pol (AB == \A)
- set ffcepol pol
- semioptional
-endmatch
-
-code argD
- if (ffcemux) {
- dffcemux = ffcemux;
- dffcepol = ffcepol;
- argD = port(ffcemux, ffcepol ? \B : \A);
- dffD.replace(port(ffcemux, \Y), argD);
- }
- else
- dffcemux = nullptr;
+ dffD.replace(argQ, D);
endcode
// #######################
@@ -597,119 +453,26 @@ code
reject;
endcode
-// (1) Starting from an optional $mux cell that implements clock enable
-// semantics --- one where the given 'D' argument (partially or fully)
-// drives one of its two inputs
-match ffcemux
- select ffcemux->type.in($mux)
- // ffcemux output must have two users: ffcemux and ff.D
- select nusers(port(ffcemux, \Y)) == 2
-
- choice <IdString> AB {\A, \B}
- // keep-last-value net must have at least three users: ffcemux, ff, downstream sink(s)
- select nusers(port(ffcemux, AB)) >= 3
-
- slice offset GetSize(port(ffcemux, \Y))
- define <IdString> BA (AB == \A ? \B : \A)
- index <SigBit> port(ffcemux, BA)[offset] === argD[0]
-
- // Check that the rest of argD is present
- filter GetSize(port(ffcemux, BA)) >= offset + GetSize(argD)
- filter port(ffcemux, BA).extract(offset, GetSize(argD)) == argD
-
- set ffoffset offset
- define <bool> pol (AB == \A)
- set ffcepol pol
-
- semioptional
-endmatch
-
-code argD argQ
- dffcemux = ffcemux;
- if (ffcemux) {
- SigSpec BA = port(ffcemux, ffcepol ? \B : \A);
- SigSpec Y = port(ffcemux, \Y);
- argQ = argD;
- argD.replace(BA, Y);
- argQ.replace(BA, port(ffcemux, ffcepol ? \A : \B));
-
- dffcemux = ffcemux;
- dffcepol = ffcepol;
- }
-endcode
-
-// (2) Starting from, or continuing onto, another optional $mux cell that
-// implements synchronous reset semantics --- one where the given 'D'
-// argument (or the clock enable $mux output) drives one of its two inputs
-// and where the other input is fully zero
-match ffrstmux
- select ffrstmux->type.in($mux)
- // ffrstmux output must have two users: ffrstmux and ff.D
- select nusers(port(ffrstmux, \Y)) == 2
-
- choice <IdString> BA {\B, \A}
- // DSP48E1 only supports reset to zero
- select port(ffrstmux, BA).is_fully_zero()
-
- slice offset GetSize(port(ffrstmux, \Y))
- define <IdString> AB (BA == \B ? \A : \B)
- index <SigBit> port(ffrstmux, AB)[offset] === argD[0]
-
- // Check that offset is consistent
- filter !ffcemux || ffoffset == offset
- // Check that the rest of argD is present
- filter GetSize(port(ffrstmux, AB)) >= offset + GetSize(argD)
- filter port(ffrstmux, AB).extract(offset, GetSize(argD)) == argD
-
- set ffoffset offset
- define <bool> pol (AB == \A)
- set ffrstpol pol
-
- semioptional
-endmatch
-
-code argD argQ
- dffrstmux = ffrstmux;
- if (ffrstmux) {
- SigSpec AB = port(ffrstmux, ffrstpol ? \A : \B);
- SigSpec Y = port(ffrstmux, \Y);
- argD.replace(AB, Y);
-
- dffrstmux = ffrstmux;
- dffrstpol = ffrstpol;
- }
-endcode
-
-// (3) Match for a $dff cell (whose 'D' input is the 'D' argument, or the
-// output of the previous clock enable or reset $mux cells)
match ff
- select ff->type.in($dff)
+ select ff->type.in($dff, $dffe, $sdff, $sdffe)
// DSP48E1 does not support clock inversion
select param(ff, \CLK_POLARITY).as_bool()
slice offset GetSize(port(ff, \D))
index <SigBit> port(ff, \D)[offset] === argD[0]
- // Check that offset is consistent
- filter (!ffcemux && !ffrstmux) || ffoffset == offset
// Check that the rest of argD is present
filter GetSize(port(ff, \D)) >= offset + GetSize(argD)
filter port(ff, \D).extract(offset, GetSize(argD)) == argD
- // Check that FF.Q is connected to CE-mux
- filter !ffcemux || port(ff, \Q).extract(offset, GetSize(argQ)) == argQ
filter clock == SigBit() || port(ff, \CLK) == clock
-
- set ffoffset offset
endmatch
code argQ
SigSpec D = port(ff, \D);
SigSpec Q = port(ff, \Q);
- if (!ffcemux) {
- argQ = argD;
- argQ.replace(D, Q);
- }
+ argQ = argD;
+ argQ.replace(D, Q);
// Abandon matches when 'Q' has a non-zero init attribute set
// (not supported by DSP48E1)
diff --git a/passes/pmgen/xilinx_dsp48a.pmg b/passes/pmgen/xilinx_dsp48a.pmg
index 16f5e598d..dce1b61b0 100644
--- a/passes/pmgen/xilinx_dsp48a.pmg
+++ b/passes/pmgen/xilinx_dsp48a.pmg
@@ -4,8 +4,6 @@
// At a high level, it works as follows:
// ( 1) Starting from a DSP48A/DSP48A1 cell
// ( 2) Match the driver of the 'B' input to a possible $dff cell (B1REG)
-// (attached to at most two $mux cells that implement clock-enable or
-// reset functionality, using a subpattern discussed below)
// If B1REG matched, treat 'B' input as input of B1REG
// ( 3) Match the driver of the 'B' and 'D' inputs for a possible $add cell
// (pre-adder)
@@ -40,20 +38,15 @@ pattern xilinx_dsp48a_pack
state <SigBit> clock
state <SigSpec> sigA sigB sigC sigD sigM sigP
state <IdString> postAddAB postAddMuxAB
-state <bool> ffAcepol ffBcepol ffDcepol ffMcepol ffPcepol
-state <bool> ffArstpol ffBrstpol ffDrstpol ffMrstpol ffPrstpol
-state <Cell*> ffA0 ffA0cemux ffA0rstmux ffA1 ffA1cemux ffA1rstmux
-state <Cell*> ffB0 ffB0cemux ffB0rstmux ffB1 ffB1cemux ffB1rstmux
-state <Cell*> ffD ffDcemux ffDrstmux ffM ffMcemux ffMrstmux ffP ffPcemux ffPrstmux
+state <Cell*> ffA0 ffA1
+state <Cell*> ffB0 ffB1
+state <Cell*> ffD ffM ffP
// Variables used for subpatterns
state <SigSpec> argQ argD
-state <bool> ffcepol ffrstpol
-state <int> ffoffset
udata <SigSpec> dffD dffQ
udata <SigBit> dffclock
-udata <Cell*> dff dffcemux dffrstmux
-udata <bool> dffcepol dffrstpol
+udata <Cell*> dff
// (1) Starting from a DSP48A/DSP48A1 cell
match dsp
@@ -98,21 +91,13 @@ endcode
// (attached to at most two $mux cells that implement clock-enable or
// reset functionality, using a subpattern discussed above)
// If matched, treat 'B' input as input of B1REG
-code argQ ffB1 ffB1cemux ffB1rstmux ffBcepol ffBrstpol sigB clock
+code argQ ffB1 sigB clock
if (param(dsp, \B1REG).as_int() == 0 && param(dsp, \B0REG).as_int() == 0 && port(dsp, \OPMODE, SigSpec()).extract(4, 1).is_fully_zero()) {
argQ = sigB;
subpattern(in_dffe);
if (dff) {
ffB1 = dff;
clock = dffclock;
- if (dffrstmux) {
- ffB1rstmux = dffrstmux;
- ffBrstpol = dffrstpol;
- }
- if (dffcemux) {
- ffB1cemux = dffcemux;
- ffBcepol = dffcepol;
- }
sigB = dffD;
}
}
@@ -147,41 +132,29 @@ code sigB sigD
endcode
// (4) Match 'B' input for B0REG
-code argQ ffB0 ffB0cemux ffB0rstmux ffBcepol ffBrstpol sigB clock
+code argQ ffB0 sigB clock
if (param(dsp, \B0REG).as_int() == 0) {
argQ = sigB;
subpattern(in_dffe);
if (dff) {
if (ffB1) {
- if ((ffB1rstmux != nullptr) ^ (dffrstmux != nullptr))
+ if (dff->type != ffB1->type)
goto ffB0_end;
- if ((ffB1cemux != nullptr) ^ (dffcemux != nullptr))
- goto ffB0_end;
- if (dffrstmux) {
- if (ffBrstpol != dffrstpol)
+ if (dff->type.in($sdff, $sdffe, $sdffce)) {
+ if (param(dff, \SRST_POLARITY) != param(ffB1, \SRST_POLARITY))
goto ffB0_end;
- if (port(ffB1rstmux, \S) != port(dffrstmux, \S))
+ if (port(dff, \SRST) != port(ffB1, \SRST))
goto ffB0_end;
- ffB0rstmux = dffrstmux;
}
- if (dffcemux) {
- if (ffBcepol != dffcepol)
+ if (dff->type.in($dffe, $sdffe, $sdffce)) {
+ if (param(dff, \EN_POLARITY) != param(ffB1, \EN_POLARITY))
goto ffB0_end;
- if (port(ffB1cemux, \S) != port(dffcemux, \S))
+ if (port(dff, \EN) != port(ffB1, \EN))
goto ffB0_end;
- ffB0cemux = dffcemux;
}
}
ffB0 = dff;
clock = dffclock;
- if (dffrstmux) {
- ffB0rstmux = dffrstmux;
- ffBrstpol = dffrstpol;
- }
- if (dffcemux) {
- ffB0cemux = dffcemux;
- ffBcepol = dffcepol;
- }
sigB = dffD;
}
}
@@ -190,21 +163,13 @@ endcode
// (5) Match 'A' input for A1REG
// If A1REG, then match 'A' input for A0REG
-code argQ ffA1 ffA1cemux ffA1rstmux ffAcepol ffArstpol sigA clock ffA0 ffA0cemux ffA0rstmux
+code argQ ffA1 sigA clock ffA0
if (param(dsp, \A0REG).as_int() == 0 && param(dsp, \A1REG).as_int() == 0) {
argQ = sigA;
subpattern(in_dffe);
if (dff) {
ffA1 = dff;
clock = dffclock;
- if (dffrstmux) {
- ffA1rstmux = dffrstmux;
- ffArstpol = dffrstpol;
- }
- if (dffcemux) {
- ffA1cemux = dffcemux;
- ffAcepol = dffcepol;
- }
sigA = dffD;
// Now attempt to match A0
@@ -212,32 +177,23 @@ code argQ ffA1 ffA1cemux ffA1rstmux ffAcepol ffArstpol sigA clock ffA0 ffA0cemux
argQ = sigA;
subpattern(in_dffe);
if (dff) {
- if ((ffA1rstmux != nullptr) ^ (dffrstmux != nullptr))
+ if (dff->type != ffA1->type)
goto ffA0_end;
- if ((ffA1cemux != nullptr) ^ (dffcemux != nullptr))
- goto ffA0_end;
- if (dffrstmux) {
- if (ffArstpol != dffrstpol)
+ if (dff->type.in($sdff, $sdffe, $sdffce)) {
+ if (param(dff, \SRST_POLARITY) != param(ffA1, \SRST_POLARITY))
goto ffA0_end;
- if (port(ffA1rstmux, \S) != port(dffrstmux, \S))
+ if (port(dff, \SRST) != port(ffA1, \SRST))
goto ffA0_end;
- ffA0rstmux = dffrstmux;
}
- if (dffcemux) {
- if (ffAcepol != dffcepol)
+ if (dff->type.in($dffe, $sdffe, $sdffce)) {
+ if (param(dff, \EN_POLARITY) != param(ffA1, \EN_POLARITY))
goto ffA0_end;
- if (port(ffA1cemux, \S) != port(dffcemux, \S))
+ if (port(dff, \EN) != port(ffA1, \EN))
goto ffA0_end;
- ffA0cemux = dffcemux;
}
ffA0 = dff;
clock = dffclock;
-
- if (dffcemux) {
- ffA0cemux = dffcemux;
- ffAcepol = dffcepol;
- }
sigA = dffD;
ffA0_end: ;
@@ -249,42 +205,26 @@ ffA0_end: ;
endcode
// (6) Match 'D' input for DREG
-code argQ ffD ffDcemux ffDrstmux ffDcepol ffDrstpol sigD clock
+code argQ ffD sigD clock
if (param(dsp, \DREG).as_int() == 0) {
argQ = sigD;
subpattern(in_dffe);
if (dff) {
ffD = dff;
clock = dffclock;
- if (dffrstmux) {
- ffDrstmux = dffrstmux;
- ffDrstpol = dffrstpol;
- }
- if (dffcemux) {
- ffDcemux = dffcemux;
- ffDcepol = dffcepol;
- }
sigD = dffD;
}
}
endcode
// (7) Match 'P' output that exclusively drives an MREG
-code argD ffM ffMcemux ffMrstmux ffMcepol ffMrstpol sigM sigP clock
+code argD ffM sigM sigP clock
if (param(dsp, \MREG).as_int() == 0 && nusers(sigM) == 2) {
argD = sigM;
subpattern(out_dffe);
if (dff) {
ffM = dff;
clock = dffclock;
- if (dffrstmux) {
- ffMrstmux = dffrstmux;
- ffMrstpol = dffrstpol;
- }
- if (dffcemux) {
- ffMcemux = dffcemux;
- ffMcepol = dffcepol;
- }
sigM = dffQ;
}
}
@@ -303,9 +243,7 @@ match postAdd
select postAdd->type.in($add)
select GetSize(port(postAdd, \Y)) <= 48
choice <IdString> AB {\A, \B}
- select nusers(port(postAdd, AB)) <= 3
- filter ffMcemux || nusers(port(postAdd, AB)) == 2
- filter !ffMcemux || nusers(port(postAdd, AB)) == 3
+ select nusers(port(postAdd, AB)) == 2
index <SigBit> port(postAdd, AB)[0] === sigP[0]
filter GetSize(port(postAdd, AB)) >= GetSize(sigP)
@@ -325,25 +263,14 @@ code sigC sigP
endcode
// (9) Match 'P' output that exclusively drives a PREG
-code argD ffP ffPcemux ffPrstmux ffPcepol ffPrstpol sigP clock
+code argD ffP sigP clock
if (param(dsp, \PREG).as_int() == 0) {
- int users = 2;
- // If ffMcemux and no postAdd new-value net must have three users: ffMcemux, ffM and ffPcemux
- if (ffMcemux && !postAdd) users++;
- if (nusers(sigP) == users) {
+ if (nusers(sigP) == 2) {
argD = sigP;
subpattern(out_dffe);
if (dff) {
ffP = dff;
clock = dffclock;
- if (dffrstmux) {
- ffPrstmux = dffrstmux;
- ffPrstpol = dffrstpol;
- }
- if (dffcemux) {
- ffPcemux = dffcemux;
- ffPcepol = dffcepol;
- }
sigP = dffQ;
}
}
@@ -387,26 +314,13 @@ endcode
// #######################
// Subpattern for matching against input registers, based on knowledge of the
-// 'Q' input. Typically, identifying registers with clock-enable and reset
-// capability would be a task would be handled by other Yosys passes such as
-// dff2dffe, but since DSP inference happens much before this, these patterns
-// have to be manually identified.
-// At a high level:
-// (1) Starting from a $dff cell that (partially or fully) drives the given
-// 'Q' argument
-// (2) Match for a $mux cell implementing synchronous reset semantics ---
-// one that exclusively drives the 'D' input of the $dff, with one of its
-// $mux inputs being fully zero
-// (3) Match for a $mux cell implement clock enable semantics --- one that
-// exclusively drives the 'D' input of the $dff (or the other input of
-// the reset $mux) and where one of this $mux's inputs is connected to
-// the 'Q' output of the $dff
+// 'Q' input.
subpattern in_dffe
-arg argD argQ clock
+arg argQ clock
code
dff = nullptr;
- if (GetSize(argQ) == 0)
+ if (argQ.empty())
reject;
for (const auto &c : argQ.chunks()) {
// Abandon matches when 'Q' is a constant
@@ -425,13 +339,14 @@ code
}
endcode
-// (1) Starting from a $dff cell that (partially or fully) drives the given
-// 'Q' argument
match ff
- select ff->type.in($dff)
+ select ff->type.in($dff, $dffe, $sdff, $sdffe)
// DSP48E1 does not support clock inversion
select param(ff, \CLK_POLARITY).as_bool()
+ // Check that reset value, if present, is fully 0.
+ filter ff->type.in($dff, $dffe) || param(ff, \SRST_VALUE).is_fully_zero()
+
slice offset GetSize(port(ff, \D))
index <SigBit> port(ff, \Q)[offset] === argQ[0]
@@ -440,82 +355,16 @@ match ff
filter port(ff, \Q).extract(offset, GetSize(argQ)) == argQ
filter clock == SigBit() || port(ff, \CLK) == clock
-
- set ffoffset offset
endmatch
-code argQ argD
+code argQ
SigSpec Q = port(ff, \Q);
dff = ff;
dffclock = port(ff, \CLK);
dffD = argQ;
- argD = port(ff, \D);
+ SigSpec D = port(ff, \D);
argQ = Q;
- dffD.replace(argQ, argD);
- // Only search for ffrstmux if dffD only
- // has two (ff, ffrstmux) users
- if (nusers(dffD) > 2)
- argD = SigSpec();
-endcode
-
-// (2) Match for a $mux cell implementing synchronous reset semantics ---
-// exclusively drives the 'D' input of the $dff, with one of the $mux
-// inputs being fully zero
-match ffrstmux
- if !argD.empty()
- select ffrstmux->type.in($mux)
- index <SigSpec> port(ffrstmux, \Y) === argD
-
- choice <IdString> BA {\B, \A}
- // DSP48E1 only supports reset to zero
- select port(ffrstmux, BA).is_fully_zero()
-
- define <bool> pol (BA == \B)
- set ffrstpol pol
- semioptional
-endmatch
-
-code argD
- if (ffrstmux) {
- dffrstmux = ffrstmux;
- dffrstpol = ffrstpol;
- argD = port(ffrstmux, ffrstpol ? \A : \B);
- dffD.replace(port(ffrstmux, \Y), argD);
-
- // Only search for ffcemux if argQ has at
- // least 3 users (ff, <upstream>, ffrstmux) and
- // dffD only has two (ff, ffrstmux)
- if (!(nusers(argQ) >= 3 && nusers(dffD) == 2))
- argD = SigSpec();
- }
- else
- dffrstmux = nullptr;
-endcode
-
-// (3) Match for a $mux cell implement clock enable semantics --- one that
-// exclusively drives the 'D' input of the $dff (or the other input of
-// the reset $mux) and where one of this $mux's inputs is connected to
-// the 'Q' output of the $dff
-match ffcemux
- if !argD.empty()
- select ffcemux->type.in($mux)
- index <SigSpec> port(ffcemux, \Y) === argD
- choice <IdString> AB {\A, \B}
- index <SigSpec> port(ffcemux, AB) === argQ
- define <bool> pol (AB == \A)
- set ffcepol pol
- semioptional
-endmatch
-
-code argD
- if (ffcemux) {
- dffcemux = ffcemux;
- dffcepol = ffcepol;
- argD = port(ffcemux, ffcepol ? \B : \A);
- dffD.replace(port(ffcemux, \Y), argD);
- }
- else
- dffcemux = nullptr;
+ dffD.replace(argQ, D);
endcode
// #######################
@@ -543,119 +392,26 @@ code
reject;
endcode
-// (1) Starting from an optional $mux cell that implements clock enable
-// semantics --- one where the given 'D' argument (partially or fully)
-// drives one of its two inputs
-match ffcemux
- select ffcemux->type.in($mux)
- // ffcemux output must have two users: ffcemux and ff.D
- select nusers(port(ffcemux, \Y)) == 2
-
- choice <IdString> AB {\A, \B}
- // keep-last-value net must have at least three users: ffcemux, ff, downstream sink(s)
- select nusers(port(ffcemux, AB)) >= 3
-
- slice offset GetSize(port(ffcemux, \Y))
- define <IdString> BA (AB == \A ? \B : \A)
- index <SigBit> port(ffcemux, BA)[offset] === argD[0]
-
- // Check that the rest of argD is present
- filter GetSize(port(ffcemux, BA)) >= offset + GetSize(argD)
- filter port(ffcemux, BA).extract(offset, GetSize(argD)) == argD
-
- set ffoffset offset
- define <bool> pol (AB == \A)
- set ffcepol pol
-
- semioptional
-endmatch
-
-code argD argQ
- dffcemux = ffcemux;
- if (ffcemux) {
- SigSpec BA = port(ffcemux, ffcepol ? \B : \A);
- SigSpec Y = port(ffcemux, \Y);
- argQ = argD;
- argD.replace(BA, Y);
- argQ.replace(BA, port(ffcemux, ffcepol ? \A : \B));
-
- dffcemux = ffcemux;
- dffcepol = ffcepol;
- }
-endcode
-
-// (2) Starting from, or continuing onto, another optional $mux cell that
-// implements synchronous reset semantics --- one where the given 'D'
-// argument (or the clock enable $mux output) drives one of its two inputs
-// and where the other input is fully zero
-match ffrstmux
- select ffrstmux->type.in($mux)
- // ffrstmux output must have two users: ffrstmux and ff.D
- select nusers(port(ffrstmux, \Y)) == 2
-
- choice <IdString> BA {\B, \A}
- // DSP48E1 only supports reset to zero
- select port(ffrstmux, BA).is_fully_zero()
-
- slice offset GetSize(port(ffrstmux, \Y))
- define <IdString> AB (BA == \B ? \A : \B)
- index <SigBit> port(ffrstmux, AB)[offset] === argD[0]
-
- // Check that offset is consistent
- filter !ffcemux || ffoffset == offset
- // Check that the rest of argD is present
- filter GetSize(port(ffrstmux, AB)) >= offset + GetSize(argD)
- filter port(ffrstmux, AB).extract(offset, GetSize(argD)) == argD
-
- set ffoffset offset
- define <bool> pol (AB == \A)
- set ffrstpol pol
-
- semioptional
-endmatch
-
-code argD argQ
- dffrstmux = ffrstmux;
- if (ffrstmux) {
- SigSpec AB = port(ffrstmux, ffrstpol ? \A : \B);
- SigSpec Y = port(ffrstmux, \Y);
- argD.replace(AB, Y);
-
- dffrstmux = ffrstmux;
- dffrstpol = ffrstpol;
- }
-endcode
-
-// (3) Match for a $dff cell (whose 'D' input is the 'D' argument, or the
-// output of the previous clock enable or reset $mux cells)
match ff
- select ff->type.in($dff)
+ select ff->type.in($dff, $dffe, $sdff, $sdffe)
// DSP48E1 does not support clock inversion
select param(ff, \CLK_POLARITY).as_bool()
slice offset GetSize(port(ff, \D))
index <SigBit> port(ff, \D)[offset] === argD[0]
- // Check that offset is consistent
- filter (!ffcemux && !ffrstmux) || ffoffset == offset
// Check that the rest of argD is present
filter GetSize(port(ff, \D)) >= offset + GetSize(argD)
filter port(ff, \D).extract(offset, GetSize(argD)) == argD
- // Check that FF.Q is connected to CE-mux
- filter !ffcemux || port(ff, \Q).extract(offset, GetSize(argQ)) == argQ
filter clock == SigBit() || port(ff, \CLK) == clock
-
- set ffoffset offset
endmatch
code argQ
SigSpec D = port(ff, \D);
SigSpec Q = port(ff, \Q);
- if (!ffcemux) {
- argQ = argD;
- argQ.replace(D, Q);
- }
+ argQ = argD;
+ argQ.replace(D, Q);
// Abandon matches when 'Q' has a non-zero init attribute set
// (not supported by DSP48E1)
diff --git a/passes/pmgen/xilinx_dsp_CREG.pmg b/passes/pmgen/xilinx_dsp_CREG.pmg
index 42d4d1b9b..95379771a 100644
--- a/passes/pmgen/xilinx_dsp_CREG.pmg
+++ b/passes/pmgen/xilinx_dsp_CREG.pmg
@@ -26,17 +26,14 @@ pattern xilinx_dsp_packC
udata <std::function<SigSpec(const SigSpec&)>> unextend
state <SigBit> clock
state <SigSpec> sigC sigP
-state <bool> ffCcepol ffCrstpol
-state <Cell*> ffC ffCcemux ffCrstmux
+state <Cell*> ffC
// Variables used for subpatterns
state <SigSpec> argQ argD
-state <bool> ffcepol ffrstpol
state <int> ffoffset
udata <SigSpec> dffD dffQ
udata <SigBit> dffclock
-udata <Cell*> dff dffcemux dffrstmux
-udata <bool> dffcepol dffrstpol
+udata <Cell*> dff
// (1) Starting from a DSP48* cell that (a) doesn't have a CREG already,
// and (b) uses the 'C' port
@@ -80,20 +77,12 @@ endcode
// (2) Match the driver of the 'C' input to a possible $dff cell (CREG)
// (attached to at most two $mux cells that implement clock-enable or
// reset functionality, using the in_dffe subpattern)
-code argQ ffC ffCcemux ffCrstmux ffCcepol ffCrstpol sigC clock
+code argQ ffC sigC clock
argQ = sigC;
subpattern(in_dffe);
if (dff) {
ffC = dff;
clock = dffclock;
- if (dffrstmux) {
- ffCrstmux = dffrstmux;
- ffCrstpol = dffrstpol;
- }
- if (dffcemux) {
- ffCcemux = dffcemux;
- ffCcepol = dffcepol;
- }
sigC = dffD;
}
endcode
@@ -106,25 +95,14 @@ endcode
// #######################
// Subpattern for matching against input registers, based on knowledge of the
-// 'Q' input. Typically, identifying registers with clock-enable and reset
-// capability would be a task would be handled by other Yosys passes such as
-// dff2dffe, but since DSP inference happens much before this, these patterns
-// have to be manually identified.
-// At a high level:
-// (1) Starting from a $dff cell that (partially or fully) drives the given
-// 'Q' argument
-// (2) Match for a $mux cell implementing synchronous reset semantics ---
-// one that exclusively drives the 'D' input of the $dff, with one of its
-// $mux inputs being fully zero
-// (3) Match for a $mux cell implement clock enable semantics --- one that
-// exclusively drives the 'D' input of the $dff (or the other input of
-// the reset $mux) and where one of this $mux's inputs is connected to
-// the 'Q' output of the $dff
+// 'Q' input.
subpattern in_dffe
-arg argD argQ clock
+arg argQ clock
code
dff = nullptr;
+ if (argQ.empty())
+ reject;
for (const auto &c : argQ.chunks()) {
// Abandon matches when 'Q' is a constant
if (!c.wire)
@@ -135,19 +113,21 @@ code
// Abandon matches when 'Q' has a non-zero init attribute set
// (not supported by DSP48E1)
Const init = c.wire->attributes.at(\init, Const());
- for (auto b : init.extract(c.offset, c.width))
- if (b != State::Sx && b != State::S0)
- reject;
+ if (!init.empty())
+ for (auto b : init.extract(c.offset, c.width))
+ if (b != State::Sx && b != State::S0)
+ reject;
}
endcode
-// (1) Starting from a $dff cell that (partially or fully) drives the given
-// 'Q' argument
match ff
- select ff->type.in($dff)
+ select ff->type.in($dff, $dffe, $sdff, $sdffe)
// DSP48E1 does not support clock inversion
select param(ff, \CLK_POLARITY).as_bool()
+ // Check that reset value, if present, is fully 0.
+ filter ff->type.in($dff, $dffe) || param(ff, \SRST_VALUE).is_fully_zero()
+
slice offset GetSize(port(ff, \D))
index <SigBit> port(ff, \Q)[offset] === argQ[0]
@@ -156,80 +136,14 @@ match ff
filter port(ff, \Q).extract(offset, GetSize(argQ)) == argQ
filter clock == SigBit() || port(ff, \CLK) == clock
-
- set ffoffset offset
endmatch
-code argQ argD
+code argQ
SigSpec Q = port(ff, \Q);
dff = ff;
dffclock = port(ff, \CLK);
dffD = argQ;
- argD = port(ff, \D);
+ SigSpec D = port(ff, \D);
argQ = Q;
- dffD.replace(argQ, argD);
- // Only search for ffrstmux if dffD only
- // has two (ff, ffrstmux) users
- if (nusers(dffD) > 2)
- argD = SigSpec();
-endcode
-
-// (2) Match for a $mux cell implementing synchronous reset semantics ---
-// exclusively drives the 'D' input of the $dff, with one of the $mux
-// inputs being fully zero
-match ffrstmux
- if !argD.empty()
- select ffrstmux->type.in($mux)
- index <SigSpec> port(ffrstmux, \Y) === argD
-
- choice <IdString> BA {\B, \A}
- // DSP48E1 only supports reset to zero
- select port(ffrstmux, BA).is_fully_zero()
-
- define <bool> pol (BA == \B)
- set ffrstpol pol
- semioptional
-endmatch
-
-code argD
- if (ffrstmux) {
- dffrstmux = ffrstmux;
- dffrstpol = ffrstpol;
- argD = port(ffrstmux, ffrstpol ? \A : \B);
- dffD.replace(port(ffrstmux, \Y), argD);
-
- // Only search for ffcemux if argQ has at
- // least 3 users (ff, <upstream>, ffrstmux) and
- // dffD only has two (ff, ffrstmux)
- if (!(nusers(argQ) >= 3 && nusers(dffD) == 2))
- argD = SigSpec();
- }
- else
- dffrstmux = nullptr;
-endcode
-
-// (3) Match for a $mux cell implement clock enable semantics --- one that
-// exclusively drives the 'D' input of the $dff (or the other input of
-// the reset $mux) and where one of this $mux's inputs is connected to
-// the 'Q' output of the $dff
-match ffcemux
- if !argD.empty()
- select ffcemux->type.in($mux)
- index <SigSpec> port(ffcemux, \Y) === argD
- choice <IdString> AB {\A, \B}
- index <SigSpec> port(ffcemux, AB) === argQ
- define <bool> pol (AB == \A)
- set ffcepol pol
- semioptional
-endmatch
-
-code argD
- if (ffcemux) {
- dffcemux = ffcemux;
- dffcepol = ffcepol;
- argD = port(ffcemux, ffcepol ? \B : \A);
- dffD.replace(port(ffcemux, \Y), argD);
- }
- else
- dffcemux = nullptr;
+ dffD.replace(argQ, D);
endcode
diff --git a/passes/pmgen/xilinx_dsp_cascade.pmg b/passes/pmgen/xilinx_dsp_cascade.pmg
index 8babb88e6..06601554c 100644
--- a/passes/pmgen/xilinx_dsp_cascade.pmg
+++ b/passes/pmgen/xilinx_dsp_cascade.pmg
@@ -51,12 +51,10 @@ state <int> AREG BREG
// Variables used for subpatterns
state <SigSpec> argQ argD
-state <bool> ffcepol ffrstpol
state <int> ffoffset
udata <SigSpec> dffD dffQ
udata <SigBit> dffclock
-udata <Cell*> dff dffcemux dffrstmux
-udata <bool> dffcepol dffrstpol
+udata <Cell*> dff
code
#define MAX_DSP_CASCADE 20
@@ -254,9 +252,9 @@ code argQ clock AREG
clock = port(prev, \CLK);
subpattern(in_dffe);
if (dff) {
- if (!dffrstmux && port(prev, \RSTA, State::S0) != State::S0)
+ if (!dff->type.in($sdff, $sdffe) && port(prev, \RSTA, State::S0) != State::S0)
goto reject_AREG;
- if (dffrstmux && port(dffrstmux, \S) != port(prev, \RSTA, State::S0))
+ if (dff->type.in($sdff, $sdffe) && (port(dff, \SRST) != port(prev, \RSTA, State::S0) || !param(dff, \SRST_POLARITY).as_bool()))
goto reject_AREG;
IdString CEA;
if (param(prev, \AREG) == 1)
@@ -264,9 +262,9 @@ code argQ clock AREG
else if (param(prev, \AREG) == 2)
CEA = \CEA1;
else log_abort();
- if (!dffcemux && port(prev, CEA, State::S0) != State::S1)
+ if (!dff->type.in($dffe, $sdffe) && port(prev, CEA, State::S0) != State::S1)
goto reject_AREG;
- if (dffcemux && port(dffcemux, \S) != port(prev, CEA, State::S0))
+ if (dff->type.in($dffe, $sdffe) && (port(dff, \EN) != port(prev, CEA, State::S0) || !param(dff, \EN_POLARITY).as_bool()))
goto reject_AREG;
if (dffD == unextend(port(prev, \A)))
AREG = 1;
@@ -295,9 +293,9 @@ code argQ clock BREG
clock = port(prev, \CLK);
subpattern(in_dffe);
if (dff) {
- if (!dffrstmux && port(prev, \RSTB, State::S0) != State::S0)
+ if (!dff->type.in($sdff, $sdffe) && port(prev, \RSTB, State::S0) != State::S0)
goto reject_BREG;
- if (dffrstmux && port(dffrstmux, \S) != port(prev, \RSTB, State::S0))
+ if (dff->type.in($sdff, $sdffe) && (port(dff, \SRST) != port(prev, \RSTB, State::S0) || !param(dff, \SRST_POLARITY).as_bool()))
goto reject_BREG;
IdString CEB;
if (next->type.in(\DSP48A, \DSP48A1))
@@ -310,9 +308,9 @@ code argQ clock BREG
else log_abort();
}
else log_abort();
- if (!dffcemux && port(prev, CEB, State::S0) != State::S1)
+ if (!dff->type.in($dffe, $sdffe) && port(prev, CEB, State::S0) != State::S1)
goto reject_BREG;
- if (dffcemux && port(dffcemux, \S) != port(prev, CEB, State::S0))
+ if (dff->type.in($dffe, $sdffe) && (port(dff, \EN) != port(prev, CEB, State::S0) || !param(dff, \EN_POLARITY).as_bool()))
goto reject_BREG;
if (dffD == unextend(port(prev, \B))) {
if (next->type.in(\DSP48A, \DSP48A1) && param(prev, \B0REG) != 0)
@@ -357,25 +355,14 @@ endcode
// #######################
// Subpattern for matching against input registers, based on knowledge of the
-// 'Q' input. Typically, identifying registers with clock-enable and reset
-// capability would be a task would be handled by other Yosys passes such as
-// dff2dffe, but since DSP inference happens much before this, these patterns
-// have to be manually identified.
-// At a high level:
-// (1) Starting from a $dff cell that (partially or fully) drives the given
-// 'Q' argument
-// (2) Match for a $mux cell implementing synchronous reset semantics ---
-// one that exclusively drives the 'D' input of the $dff, with one of its
-// $mux inputs being fully zero
-// (3) Match for a $mux cell implement clock enable semantics --- one that
-// exclusively drives the 'D' input of the $dff (or the other input of
-// the reset $mux) and where one of this $mux's inputs is connected to
-// the 'Q' output of the $dff
+// 'Q' input.
subpattern in_dffe
-arg argD argQ clock
+arg argQ clock
code
dff = nullptr;
+ if (argQ.empty())
+ reject;
for (const auto &c : argQ.chunks()) {
// Abandon matches when 'Q' is a constant
if (!c.wire)
@@ -386,19 +373,21 @@ code
// Abandon matches when 'Q' has a non-zero init attribute set
// (not supported by DSP48E1)
Const init = c.wire->attributes.at(\init, Const());
- for (auto b : init.extract(c.offset, c.width))
- if (b != State::Sx && b != State::S0)
- reject;
+ if (!init.empty())
+ for (auto b : init.extract(c.offset, c.width))
+ if (b != State::Sx && b != State::S0)
+ reject;
}
endcode
-// (1) Starting from a $dff cell that (partially or fully) drives the given
-// 'Q' argument
match ff
- select ff->type.in($dff)
+ select ff->type.in($dff, $dffe, $sdff, $sdffe)
// DSP48E1 does not support clock inversion
select param(ff, \CLK_POLARITY).as_bool()
+ // Check that reset value, if present, is fully 0.
+ filter ff->type.in($dff, $dffe) || param(ff, \SRST_VALUE).is_fully_zero()
+
slice offset GetSize(port(ff, \D))
index <SigBit> port(ff, \Q)[offset] === argQ[0]
@@ -407,80 +396,14 @@ match ff
filter port(ff, \Q).extract(offset, GetSize(argQ)) == argQ
filter clock == SigBit() || port(ff, \CLK) == clock
-
- set ffoffset offset
endmatch
-code argQ argD
+code argQ
SigSpec Q = port(ff, \Q);
dff = ff;
dffclock = port(ff, \CLK);
dffD = argQ;
- argD = port(ff, \D);
+ SigSpec D = port(ff, \D);
argQ = Q;
- dffD.replace(argQ, argD);
- // Only search for ffrstmux if dffD only
- // has two (ff, ffrstmux) users
- if (nusers(dffD) > 2)
- argD = SigSpec();
-endcode
-
-// (2) Match for a $mux cell implementing synchronous reset semantics ---
-// exclusively drives the 'D' input of the $dff, with one of the $mux
-// inputs being fully zero
-match ffrstmux
- if !argD.empty()
- select ffrstmux->type.in($mux)
- index <SigSpec> port(ffrstmux, \Y) === argD
-
- choice <IdString> BA {\B, \A}
- // DSP48E1 only supports reset to zero
- select port(ffrstmux, BA).is_fully_zero()
-
- define <bool> pol (BA == \B)
- set ffrstpol pol
- semioptional
-endmatch
-
-code argD
- if (ffrstmux) {
- dffrstmux = ffrstmux;
- dffrstpol = ffrstpol;
- argD = port(ffrstmux, ffrstpol ? \A : \B);
- dffD.replace(port(ffrstmux, \Y), argD);
-
- // Only search for ffcemux if argQ has at
- // least 3 users (ff, <upstream>, ffrstmux) and
- // dffD only has two (ff, ffrstmux)
- if (!(nusers(argQ) >= 3 && nusers(dffD) == 2))
- argD = SigSpec();
- }
- else
- dffrstmux = nullptr;
-endcode
-
-// (3) Match for a $mux cell implement clock enable semantics --- one that
-// exclusively drives the 'D' input of the $dff (or the other input of
-// the reset $mux) and where one of this $mux's inputs is connected to
-// the 'Q' output of the $dff
-match ffcemux
- if !argD.empty()
- select ffcemux->type.in($mux)
- index <SigSpec> port(ffcemux, \Y) === argD
- choice <IdString> AB {\A, \B}
- index <SigSpec> port(ffcemux, AB) === argQ
- define <bool> pol (AB == \A)
- set ffcepol pol
- semioptional
-endmatch
-
-code argD
- if (ffcemux) {
- dffcemux = ffcemux;
- dffcepol = ffcepol;
- argD = port(ffcemux, ffcepol ? \B : \A);
- dffD.replace(port(ffcemux, \Y), argD);
- }
- else
- dffcemux = nullptr;
+ dffD.replace(argQ, D);
endcode
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 f20a167b4..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,13 +43,18 @@ 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");
log("\n");
log("The following options are supported:\n");
log("\n");
+ log(" -nomux\n");
+ log(" Will omit the proc_mux pass.\n");
+ log("\n");
log(" -global_arst [!]<netname>\n");
log(" This option is passed through to proc_arst.\n");
log("\n");
@@ -57,11 +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();
@@ -69,6 +79,10 @@ struct ProcPass : public Pass {
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
+ if (args[argidx] == "-nomux") {
+ nomux = true;
+ continue;
+ }
if (args[argidx] == "-global_arst" && argidx+1 < args.size()) {
global_arst = args[++argidx];
continue;
@@ -77,6 +91,10 @@ struct ProcPass : public Pass {
ifxmode = true;
continue;
}
+ if (args[argidx] == "-noopt") {
+ noopt = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -90,10 +108,14 @@ struct ProcPass : public Pass {
Pass::call(design, "proc_arst");
else
Pass::call(design, "proc_arst -global_arst " + global_arst);
- Pass::call(design, ifxmode ? "proc_mux -ifx" : "proc_mux");
+ if (!nomux)
+ 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 e7c8a80dd..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
@@ -19,6 +19,7 @@
#include "kernel/register.h"
#include "kernel/sigtools.h"
+#include "kernel/ffinit.h"
#include "kernel/consteval.h"
#include "kernel/log.h"
#include <sstream>
@@ -32,6 +33,7 @@ struct proc_dlatch_db_t
{
Module *module;
SigMap sigmap;
+ FfInitVals initvals;
pool<Cell*> generated_dlatches;
dict<Cell*, vector<SigBit>> mux_srcbits;
@@ -40,6 +42,8 @@ struct proc_dlatch_db_t
proc_dlatch_db_t(Module *module) : module(module), sigmap(module)
{
+ initvals.set(&sigmap, module);
+
for (auto cell : module->cells())
{
if (cell->type.in(ID($mux), ID($pmux)))
@@ -69,9 +73,11 @@ struct proc_dlatch_db_t
}
for (auto wire : module->wires())
+ {
if (wire->port_input)
for (auto bit : sigmap(wire))
sigusers[bit]++;
+ }
}
bool quickcheck(const SigSpec &haystack, const SigSpec &needle)
@@ -336,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;
@@ -345,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;
}
@@ -367,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();
@@ -393,6 +396,13 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc)
else
log("No latch inferred for signal `%s.%s' from process `%s.%s'.\n",
db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str());
+ for (auto &bit : lhs) {
+ State val = db.initvals(bit);
+ if (db.initvals(bit) != State::Sx) {
+ log("Removing init bit %s for non-memory siginal `%s.%s` in process `%s.%s`.\n", log_signal(val), db.module->name.c_str(), log_signal(bit), db.module->name.c_str(), proc->name.c_str());
+ }
+ db.initvals.remove_init(bit);
+ }
db.module->connect(lhs, rhs);
offset += chunk.width;
}
@@ -428,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 e9a10465e..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
@@ -88,7 +88,7 @@ struct AssertpmuxWorker
{
SigSpec output;
- for (auto muxuser : sigbit_muxusers.at(bit))
+ for (auto muxuser : sigbit_muxusers[bit])
{
Cell *cell = std::get<0>(muxuser);
int portidx = std::get<1>(muxuser);
diff --git a/passes/sat/async2sync.cc b/passes/sat/async2sync.cc
index 6fc480925..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
@@ -19,6 +19,8 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
+#include "kernel/ffinit.h"
+#include "kernel/ff.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -39,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
{
@@ -62,169 +62,213 @@ struct Async2syncPass : public Pass {
for (auto module : design->selected_modules())
{
SigMap sigmap(module);
- dict<SigBit, State> initbits;
- pool<SigBit> del_initbits;
-
- for (auto wire : module->wires())
- if (wire->attributes.count(ID::init) > 0)
- {
- Const initval = wire->attributes.at(ID::init);
- SigSpec initsig = sigmap(wire);
-
- for (int i = 0; i < GetSize(initval) && i < GetSize(initsig); i++)
- if (initval[i] == State::S0 || initval[i] == State::S1)
- initbits[initsig[i]] = initval[i];
- }
+ FfInitVals initvals(&sigmap, module);
for (auto cell : vector<Cell*>(module->selected_cells()))
{
- if (cell->type.in(ID($adff)))
- {
- // bool clk_pol = cell->parameters[ID::CLK_POLARITY].as_bool();
- bool arst_pol = cell->parameters[ID::ARST_POLARITY].as_bool();
- Const arst_val = cell->parameters[ID::ARST_VALUE];
-
- // SigSpec sig_clk = cell->getPort(ID::CLK);
- SigSpec sig_arst = cell->getPort(ID::ARST);
- SigSpec sig_d = cell->getPort(ID::D);
- SigSpec sig_q = cell->getPort(ID::Q);
-
- log("Replacing %s.%s (%s): ARST=%s, D=%s, Q=%s\n",
- log_id(module), log_id(cell), log_id(cell->type),
- log_signal(sig_arst), log_signal(sig_d), log_signal(sig_q));
-
- Const init_val;
- for (int i = 0; i < GetSize(sig_q); i++) {
- SigBit bit = sigmap(sig_q[i]);
- init_val.bits.push_back(initbits.count(bit) ? initbits.at(bit) : State::Sx);
- del_initbits.insert(bit);
- }
-
- Wire *new_d = module->addWire(NEW_ID, GetSize(sig_d));
- Wire *new_q = module->addWire(NEW_ID, GetSize(sig_q));
- new_q->attributes[ID::init] = init_val;
+ if (!RTLIL::builtin_ff_cell_types().count(cell->type))
+ continue;
- if (arst_pol) {
- module->addMux(NEW_ID, sig_d, arst_val, sig_arst, new_d);
- module->addMux(NEW_ID, new_q, arst_val, sig_arst, sig_q);
- } else {
- module->addMux(NEW_ID, arst_val, sig_d, sig_arst, new_d);
- module->addMux(NEW_ID, arst_val, new_q, sig_arst, sig_q);
- }
+ FfData ff(&initvals, cell);
- cell->setPort(ID::D, new_d);
- cell->setPort(ID::Q, new_q);
- cell->unsetPort(ID::ARST);
- cell->unsetParam(ID::ARST_POLARITY);
- cell->unsetParam(ID::ARST_VALUE);
- cell->type = ID($dff);
+ // Skip for $_FF_ and $ff cells.
+ if (ff.has_gclk)
continue;
- }
- if (cell->type.in(ID($dffsr)))
+ if (ff.has_clk)
{
- // bool clk_pol = cell->parameters[ID::CLK_POLARITY].as_bool();
- bool set_pol = cell->parameters[ID::SET_POLARITY].as_bool();
- bool clr_pol = cell->parameters[ID::CLR_POLARITY].as_bool();
-
- // SigSpec sig_clk = cell->getPort(ID::CLK);
- SigSpec sig_set = cell->getPort(ID::SET);
- SigSpec sig_clr = cell->getPort(ID::CLR);
- SigSpec sig_d = cell->getPort(ID::D);
- SigSpec sig_q = cell->getPort(ID::Q);
-
- log("Replacing %s.%s (%s): SET=%s, CLR=%s, D=%s, Q=%s\n",
- log_id(module), log_id(cell), log_id(cell->type),
- log_signal(sig_set), log_signal(sig_clr), log_signal(sig_d), log_signal(sig_q));
-
- Const init_val;
- for (int i = 0; i < GetSize(sig_q); i++) {
- SigBit bit = sigmap(sig_q[i]);
- init_val.bits.push_back(initbits.count(bit) ? initbits.at(bit) : State::Sx);
- del_initbits.insert(bit);
+ if (ff.has_sr) {
+ 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),
+ log_signal(ff.sig_set), log_signal(ff.sig_clr), 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);
+
+ SigSpec sig_set = ff.sig_set;
+ SigSpec sig_clr = ff.sig_clr;
+
+ if (!ff.pol_set) {
+ if (!ff.is_fine)
+ sig_set = module->Not(NEW_ID, sig_set);
+ else
+ sig_set = module->NotGate(NEW_ID, sig_set);
+ }
+
+ if (ff.pol_clr) {
+ if (!ff.is_fine)
+ sig_clr = module->Not(NEW_ID, sig_clr);
+ else
+ sig_clr = module->NotGate(NEW_ID, sig_clr);
+ }
+
+ if (!ff.is_fine) {
+ SigSpec tmp = module->Or(NEW_ID, ff.sig_d, sig_set);
+ module->addAnd(NEW_ID, tmp, sig_clr, new_d);
+
+ tmp = module->Or(NEW_ID, new_q, sig_set);
+ module->addAnd(NEW_ID, tmp, sig_clr, ff.sig_q);
+ } else {
+ SigSpec tmp = module->OrGate(NEW_ID, ff.sig_d, sig_set);
+ module->addAndGate(NEW_ID, tmp, sig_clr, new_d);
+
+ tmp = module->OrGate(NEW_ID, new_q, sig_set);
+ module->addAndGate(NEW_ID, tmp, sig_clr, ff.sig_q);
+ }
+
+ 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();
+
+ log("Replacing %s.%s (%s): ARST=%s, D=%s, Q=%s\n",
+ log_id(module), log_id(cell), log_id(cell->type),
+ log_signal(ff.sig_arst), log_signal(ff.sig_d), log_signal(ff.sig_q));
+
+ initvals.remove_init(ff.sig_q);
+
+ Wire *new_q = module->addWire(NEW_ID, ff.width);
+
+ if (ff.pol_arst) {
+ if (!ff.is_fine)
+ module->addMux(NEW_ID, new_q, ff.val_arst, ff.sig_arst, ff.sig_q);
+ else
+ module->addMuxGate(NEW_ID, new_q, ff.val_arst[0], ff.sig_arst, ff.sig_q);
+ } else {
+ if (!ff.is_fine)
+ module->addMux(NEW_ID, ff.val_arst, new_q, ff.sig_arst, ff.sig_q);
+ else
+ module->addMuxGate(NEW_ID, ff.val_arst[0], new_q, ff.sig_arst, ff.sig_q);
+ }
+
+ 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;
}
-
- Wire *new_d = module->addWire(NEW_ID, GetSize(sig_d));
- Wire *new_q = module->addWire(NEW_ID, GetSize(sig_q));
- new_q->attributes[ID::init] = init_val;
-
- if (!set_pol)
- sig_set = module->Not(NEW_ID, sig_set);
-
- if (clr_pol)
- sig_clr = module->Not(NEW_ID, sig_clr);
-
- SigSpec tmp = module->Or(NEW_ID, sig_d, sig_set);
- module->addAnd(NEW_ID, tmp, sig_clr, new_d);
-
- tmp = module->Or(NEW_ID, new_q, sig_set);
- module->addAnd(NEW_ID, tmp, sig_clr, sig_q);
-
- cell->setPort(ID::D, new_d);
- cell->setPort(ID::Q, new_q);
- cell->unsetPort(ID::SET);
- cell->unsetPort(ID::CLR);
- cell->unsetParam(ID::SET_POLARITY);
- cell->unsetParam(ID::CLR_POLARITY);
- cell->type = ID($dff);
- continue;
}
-
- if (cell->type.in(ID($dlatch)))
+ else
{
- bool en_pol = cell->parameters[ID::EN_POLARITY].as_bool();
-
- SigSpec sig_en = cell->getPort(ID::EN);
- SigSpec sig_d = cell->getPort(ID::D);
- SigSpec sig_q = cell->getPort(ID::Q);
-
+ // 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(sig_en), log_signal(sig_d), log_signal(sig_q));
-
- Const init_val;
- for (int i = 0; i < GetSize(sig_q); i++) {
- SigBit bit = sigmap(sig_q[i]);
- init_val.bits.push_back(initbits.count(bit) ? initbits.at(bit) : State::Sx);
- del_initbits.insert(bit);
+ 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_aload) {
+ new_d = 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, new_d);
+ else
+ 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_ad, new_q, ff.sig_aload, new_d);
+ else
+ module->addMuxGate(NEW_ID, ff.sig_ad, new_q, ff.sig_aload, new_d);
+ }
+ } else {
+ new_d = new_q;
}
- Wire *new_q = module->addWire(NEW_ID, GetSize(sig_q));
- new_q->attributes[ID::init] = init_val;
-
- if (en_pol) {
- module->addMux(NEW_ID, new_q, sig_d, sig_en, sig_q);
+ if (ff.has_sr) {
+ SigSpec sig_set = ff.sig_set;
+ SigSpec sig_clr = ff.sig_clr;
+
+ if (!ff.pol_set) {
+ if (!ff.is_fine)
+ sig_set = module->Not(NEW_ID, sig_set);
+ else
+ sig_set = module->NotGate(NEW_ID, sig_set);
+ }
+
+ if (ff.pol_clr) {
+ if (!ff.is_fine)
+ sig_clr = module->Not(NEW_ID, sig_clr);
+ else
+ sig_clr = module->NotGate(NEW_ID, sig_clr);
+ }
+
+ if (!ff.is_fine) {
+ SigSpec tmp = module->Or(NEW_ID, new_d, sig_set);
+ module->addAnd(NEW_ID, tmp, sig_clr, ff.sig_q);
+ } else {
+ SigSpec tmp = module->OrGate(NEW_ID, new_d, sig_set);
+ module->addAndGate(NEW_ID, tmp, sig_clr, ff.sig_q);
+ }
+ } else if (ff.has_arst) {
+ if (ff.pol_arst) {
+ if (!ff.is_fine)
+ module->addMux(NEW_ID, new_d, ff.val_arst, ff.sig_arst, ff.sig_q);
+ else
+ module->addMuxGate(NEW_ID, new_d, ff.val_arst[0], ff.sig_arst, ff.sig_q);
+ } else {
+ if (!ff.is_fine)
+ module->addMux(NEW_ID, ff.val_arst, new_d, ff.sig_arst, ff.sig_q);
+ else
+ module->addMuxGate(NEW_ID, ff.val_arst[0], new_d, ff.sig_arst, ff.sig_q);
+ }
} else {
- module->addMux(NEW_ID, sig_d, new_q, sig_en, sig_q);
+ module->connect(ff.sig_q, new_d);
}
- cell->setPort(ID::D, sig_q);
- cell->setPort(ID::Q, new_q);
- cell->unsetPort(ID::EN);
- cell->unsetParam(ID::EN_POLARITY);
- cell->type = ID($ff);
- continue;
+ ff.sig_d = new_d;
+ ff.sig_q = new_q;
+ ff.has_aload = false;
+ ff.has_arst = false;
+ ff.has_sr = false;
+ ff.has_gclk = true;
}
+ ff.emit();
}
-
- for (auto wire : module->wires())
- if (wire->attributes.count(ID::init) > 0)
- {
- bool delete_initattr = true;
- Const initval = wire->attributes.at(ID::init);
- SigSpec initsig = sigmap(wire);
-
- for (int i = 0; i < GetSize(initval) && i < GetSize(initsig); i++)
- if (del_initbits.count(initsig[i]) > 0)
- initval[i] = State::Sx;
- else if (initval[i] != State::Sx)
- delete_initattr = false;
-
- if (delete_initattr)
- wire->attributes.erase(ID::init);
- else
- wire->attributes.at(ID::init) = initval;
- }
}
}
} Async2syncPass;
diff --git a/passes/sat/clk2fflogic.cc b/passes/sat/clk2fflogic.cc
index e5c5d0486..a292941c8 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
@@ -19,6 +19,9 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
+#include "kernel/ffinit.h"
+#include "kernel/ff.h"
+#include "kernel/mem.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -36,6 +39,30 @@ struct Clk2fflogicPass : public Pass {
log("multiple clocks.\n");
log("\n");
}
+ SigSpec wrap_async_control(Module *module, SigSpec sig, bool polarity) {
+ Wire *past_sig = module->addWire(NEW_ID, GetSize(sig));
+ module->addFf(NEW_ID, sig, past_sig);
+ if (polarity)
+ sig = module->Or(NEW_ID, sig, past_sig);
+ else
+ sig = module->And(NEW_ID, sig, past_sig);
+ if (polarity)
+ return sig;
+ else
+ return module->Not(NEW_ID, sig);
+ }
+ SigSpec wrap_async_control_gate(Module *module, SigSpec sig, bool polarity) {
+ Wire *past_sig = module->addWire(NEW_ID);
+ module->addFfGate(NEW_ID, sig, past_sig);
+ if (polarity)
+ sig = module->OrGate(NEW_ID, sig, past_sig);
+ else
+ sig = module->AndGate(NEW_ID, sig, past_sig);
+ if (polarity)
+ return sig;
+ else
+ return module->NotGate(NEW_ID, sig);
+ }
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
// bool flag_noinit = false;
@@ -56,348 +83,174 @@ struct Clk2fflogicPass : public Pass {
for (auto module : design->selected_modules())
{
SigMap sigmap(module);
- dict<SigBit, State> initbits;
- pool<SigBit> del_initbits;
-
- for (auto wire : module->wires())
- if (wire->attributes.count(ID::init) > 0)
- {
- Const initval = wire->attributes.at(ID::init);
- SigSpec initsig = sigmap(wire);
+ FfInitVals initvals(&sigmap, module);
- for (int i = 0; i < GetSize(initval) && i < GetSize(initsig); i++)
- if (initval[i] == State::S0 || initval[i] == State::S1)
- initbits[initsig[i]] = initval[i];
+ for (auto &mem : Mem::get_selected_memories(module))
+ {
+ for (int i = 0; i < GetSize(mem.rd_ports); i++) {
+ auto &port = mem.rd_ports[i];
+ if (port.clk_enable)
+ log_error("Read port %d of memory %s.%s is clocked. This is not supported by \"clk2fflogic\"! "
+ "Call \"memory\" with -nordff to avoid this error.\n", i, log_id(mem.memid), log_id(module));
}
- for (auto cell : vector<Cell*>(module->selected_cells()))
- {
- if (cell->type.in(ID($mem)))
+ for (int i = 0; i < GetSize(mem.wr_ports); i++)
{
- int abits = cell->getParam(ID::ABITS).as_int();
- int width = cell->getParam(ID::WIDTH).as_int();
- int rd_ports = cell->getParam(ID::RD_PORTS).as_int();
- int wr_ports = cell->getParam(ID::WR_PORTS).as_int();
-
- for (int i = 0; i < rd_ports; i++) {
- if (cell->getParam(ID::RD_CLK_ENABLE).extract(i).as_bool())
- log_error("Read port %d of memory %s.%s is clocked. This is not supported by \"clk2fflogic\"! "
- "Call \"memory\" with -nordff to avoid this error.\n", i, log_id(cell), log_id(module));
- }
-
- Const wr_clk_en_param = cell->getParam(ID::WR_CLK_ENABLE);
- Const wr_clk_pol_param = cell->getParam(ID::WR_CLK_POLARITY);
-
- SigSpec wr_clk_port = cell->getPort(ID::WR_CLK);
- SigSpec wr_en_port = cell->getPort(ID::WR_EN);
- SigSpec wr_addr_port = cell->getPort(ID::WR_ADDR);
- SigSpec wr_data_port = cell->getPort(ID::WR_DATA);
-
- for (int wport = 0; wport < wr_ports; wport++)
- {
- bool clken = wr_clk_en_param[wport] == State::S1;
- bool clkpol = wr_clk_pol_param[wport] == State::S1;
-
- if (!clken)
- continue;
+ auto &port = mem.wr_ports[i];
- SigBit clk = wr_clk_port[wport];
- SigSpec en = wr_en_port.extract(wport*width, width);
- SigSpec addr = wr_addr_port.extract(wport*abits, abits);
- SigSpec data = wr_data_port.extract(wport*width, width);
-
- log("Modifying write port %d on memory %s.%s: CLK=%s, A=%s, D=%s\n",
- wport, log_id(module), log_id(cell), log_signal(clk),
- log_signal(addr), log_signal(data));
-
- Wire *past_clk = module->addWire(NEW_ID);
- past_clk->attributes[ID::init] = clkpol ? State::S1 : State::S0;
- module->addFf(NEW_ID, clk, past_clk);
-
- SigSpec clock_edge_pattern;
-
- if (clkpol) {
- clock_edge_pattern.append(State::S0);
- clock_edge_pattern.append(State::S1);
- } else {
- clock_edge_pattern.append(State::S1);
- clock_edge_pattern.append(State::S0);
- }
+ if (!port.clk_enable)
+ continue;
- SigSpec clock_edge = module->Eqx(NEW_ID, {clk, SigSpec(past_clk)}, clock_edge_pattern);
+ log("Modifying write port %d on memory %s.%s: CLK=%s, A=%s, D=%s\n",
+ i, log_id(module), log_id(mem.memid), log_signal(port.clk),
+ log_signal(port.addr), log_signal(port.data));
- SigSpec en_q = module->addWire(NEW_ID, GetSize(en));
- module->addFf(NEW_ID, en, en_q);
-
- SigSpec addr_q = module->addWire(NEW_ID, GetSize(addr));
- module->addFf(NEW_ID, addr, addr_q);
-
- SigSpec data_q = module->addWire(NEW_ID, GetSize(data));
- module->addFf(NEW_ID, data, data_q);
+ Wire *past_clk = module->addWire(NEW_ID);
+ past_clk->attributes[ID::init] = port.clk_polarity ? State::S1 : State::S0;
+ module->addFf(NEW_ID, port.clk, past_clk);
- wr_clk_port[wport] = State::S0;
- wr_en_port.replace(wport*width, module->Mux(NEW_ID, Const(0, GetSize(en_q)), en_q, clock_edge));
- wr_addr_port.replace(wport*abits, addr_q);
- wr_data_port.replace(wport*width, data_q);
+ SigSpec clock_edge_pattern;
- wr_clk_en_param[wport] = State::S0;
- wr_clk_pol_param[wport] = State::S0;
+ if (port.clk_polarity) {
+ clock_edge_pattern.append(State::S0);
+ clock_edge_pattern.append(State::S1);
+ } else {
+ clock_edge_pattern.append(State::S1);
+ clock_edge_pattern.append(State::S0);
}
- cell->setParam(ID::WR_CLK_ENABLE, wr_clk_en_param);
- cell->setParam(ID::WR_CLK_POLARITY, wr_clk_pol_param);
+ SigSpec clock_edge = module->Eqx(NEW_ID, {port.clk, SigSpec(past_clk)}, clock_edge_pattern);
- cell->setPort(ID::WR_CLK, wr_clk_port);
- cell->setPort(ID::WR_EN, wr_en_port);
- cell->setPort(ID::WR_ADDR, wr_addr_port);
- cell->setPort(ID::WR_DATA, wr_data_port);
- }
+ SigSpec en_q = module->addWire(NEW_ID, GetSize(port.en));
+ module->addFf(NEW_ID, port.en, en_q);
- if (cell->type.in(ID($dlatch), ID($dlatchsr)))
- {
- bool enpol = cell->parameters[ID::EN_POLARITY].as_bool();
+ SigSpec addr_q = module->addWire(NEW_ID, GetSize(port.addr));
+ module->addFf(NEW_ID, port.addr, addr_q);
- SigSpec sig_en = cell->getPort(ID::EN);
- SigSpec sig_d = cell->getPort(ID::D);
- SigSpec sig_q = cell->getPort(ID::Q);
+ SigSpec data_q = module->addWire(NEW_ID, GetSize(port.data));
+ module->addFf(NEW_ID, port.data, data_q);
- log("Replacing %s.%s (%s): EN=%s, D=%s, Q=%s\n",
- log_id(module), log_id(cell), log_id(cell->type),
- log_signal(sig_en), log_signal(sig_d), log_signal(sig_q));
+ port.clk = State::S0;
+ port.en = module->Mux(NEW_ID, Const(0, GetSize(en_q)), en_q, clock_edge);
+ port.addr = addr_q;
+ port.data = data_q;
- Wire *past_q = module->addWire(NEW_ID, GetSize(sig_q));
- module->addFf(NEW_ID, sig_q, past_q);
+ port.clk_enable = false;
+ port.clk_polarity = false;
+ }
- if (cell->type == ID($dlatch))
- {
- if (enpol)
- module->addMux(NEW_ID, past_q, sig_d, sig_en, sig_q);
- else
- module->addMux(NEW_ID, sig_d, past_q, sig_en, sig_q);
- }
- else
- {
- SigSpec t;
- if (enpol)
- t = module->Mux(NEW_ID, past_q, sig_d, sig_en);
- else
- t = module->Mux(NEW_ID, sig_d, past_q, sig_en);
+ mem.emit();
+ }
- SigSpec s = cell->getPort(ID::SET);
- if (!cell->parameters[ID::SET_POLARITY].as_bool())
- s = module->Not(NEW_ID, s);
- t = module->Or(NEW_ID, t, s);
+ for (auto cell : vector<Cell*>(module->selected_cells()))
+ {
+ SigSpec qval;
+ if (RTLIL::builtin_ff_cell_types().count(cell->type)) {
+ FfData ff(&initvals, cell);
- SigSpec c = cell->getPort(ID::CLR);
- if (cell->parameters[ID::CLR_POLARITY].as_bool())
- c = module->Not(NEW_ID, c);
- module->addAnd(NEW_ID, t, c, sig_q);
+ if (ff.has_gclk) {
+ // Already a $ff or $_FF_ cell.
+ continue;
}
- Const initval;
- bool assign_initval = false;
- for (int i = 0; i < GetSize(sig_d); i++) {
- SigBit qbit = sigmap(sig_q[i]);
- if (initbits.count(qbit)) {
- initval.bits.push_back(initbits.at(qbit));
- del_initbits.insert(qbit);
- } else
- initval.bits.push_back(State::Sx);
- if (initval.bits.back() != State::Sx)
- assign_initval = true;
+ 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));
}
- if (assign_initval)
- past_q->attributes[ID::init] = initval;
-
- module->remove(cell);
- continue;
- }
+ ff.remove();
- bool word_dff = cell->type.in(ID($dff), ID($adff), ID($dffsr));
- if (word_dff || cell->type.in(ID($_DFF_N_), ID($_DFF_P_),
- ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
- ID($_DFF_PP0_), ID($_DFF_PP1_), ID($_DFF_PN0_), ID($_DFF_PN1_),
- ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
- ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_)))
- {
- bool clkpol;
- SigSpec clk;
- if (word_dff) {
- clkpol = cell->parameters[ID::CLK_POLARITY].as_bool();
- clk = cell->getPort(ID::CLK);
- }
- else {
- if (cell->type.in(ID($_DFF_P_), ID($_DFF_N_),
- ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
- ID($_DFF_PP0_), ID($_DFF_PP1_), ID($_DFF_PN0_), ID($_DFF_PN1_)))
- clkpol = cell->type[6] == 'P';
- else 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_)))
- clkpol = cell->type[8] == 'P';
- else log_abort();
- clk = cell->getPort(ID::C);
+ Wire *past_q = module->addWire(NEW_ID, ff.width);
+ if (!ff.is_fine) {
+ module->addFf(NEW_ID, ff.sig_q, past_q);
+ } else {
+ module->addFfGate(NEW_ID, ff.sig_q, past_q);
}
+ if (!ff.val_init.is_fully_undef())
+ initvals.set_init(past_q, ff.val_init);
- Wire *past_clk = module->addWire(NEW_ID);
- past_clk->attributes[ID::init] = clkpol ? State::S1 : State::S0;
-
- if (word_dff)
- module->addFf(NEW_ID, clk, past_clk);
- else
- module->addFfGate(NEW_ID, clk, past_clk);
+ if (ff.has_clk) {
+ ff.unmap_ce_srst();
- SigSpec sig_d = cell->getPort(ID::D);
- SigSpec sig_q = cell->getPort(ID::Q);
-
- log("Replacing %s.%s (%s): CLK=%s, D=%s, Q=%s\n",
- log_id(module), log_id(cell), log_id(cell->type),
- log_signal(clk), log_signal(sig_d), log_signal(sig_q));
-
- SigSpec clock_edge_pattern;
+ Wire *past_clk = module->addWire(NEW_ID);
+ initvals.set_init(past_clk, ff.pol_clk ? State::S1 : State::S0);
- if (clkpol) {
- clock_edge_pattern.append(State::S0);
- clock_edge_pattern.append(State::S1);
- } else {
- clock_edge_pattern.append(State::S1);
- clock_edge_pattern.append(State::S0);
- }
+ if (!ff.is_fine)
+ module->addFf(NEW_ID, ff.sig_clk, past_clk);
+ else
+ module->addFfGate(NEW_ID, ff.sig_clk, past_clk);
- SigSpec clock_edge = module->Eqx(NEW_ID, {clk, SigSpec(past_clk)}, clock_edge_pattern);
+ SigSpec clock_edge_pattern;
- Wire *past_d = module->addWire(NEW_ID, GetSize(sig_d));
- Wire *past_q = module->addWire(NEW_ID, GetSize(sig_q));
- if (word_dff) {
- module->addFf(NEW_ID, sig_d, past_d);
- module->addFf(NEW_ID, sig_q, past_q);
- }
- else {
- module->addFfGate(NEW_ID, sig_d, past_d);
- module->addFfGate(NEW_ID, sig_q, past_q);
- }
+ if (ff.pol_clk) {
+ clock_edge_pattern.append(State::S0);
+ clock_edge_pattern.append(State::S1);
+ } else {
+ clock_edge_pattern.append(State::S1);
+ clock_edge_pattern.append(State::S0);
+ }
- if (cell->type == ID($adff))
- {
- SigSpec arst = cell->getPort(ID::ARST);
- SigSpec qval = module->Mux(NEW_ID, past_q, past_d, clock_edge);
- Const rstval = cell->parameters[ID::ARST_VALUE];
+ SigSpec clock_edge = module->Eqx(NEW_ID, {ff.sig_clk, SigSpec(past_clk)}, clock_edge_pattern);
- Wire *past_arst = module->addWire(NEW_ID);
- module->addFf(NEW_ID, arst, past_arst);
- if (cell->parameters[ID::ARST_POLARITY].as_bool())
- arst = module->LogicOr(NEW_ID, arst, past_arst);
+ Wire *past_d = module->addWire(NEW_ID, ff.width);
+ if (!ff.is_fine)
+ module->addFf(NEW_ID, ff.sig_d, past_d);
else
- arst = module->LogicAnd(NEW_ID, arst, past_arst);
+ module->addFfGate(NEW_ID, ff.sig_d, past_d);
- if (cell->parameters[ID::ARST_POLARITY].as_bool())
- module->addMux(NEW_ID, qval, rstval, arst, sig_q);
- else
- module->addMux(NEW_ID, rstval, qval, arst, sig_q);
- }
- else
- if (cell->type.in(ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
- ID($_DFF_PP0_), ID($_DFF_PP1_), ID($_DFF_PN0_), ID($_DFF_PN1_)))
- {
- SigSpec arst = cell->getPort(ID::R);
- SigSpec qval = module->MuxGate(NEW_ID, past_q, past_d, clock_edge);
- SigBit rstval = (cell->type[8] == '1');
-
- Wire *past_arst = module->addWire(NEW_ID);
- module->addFfGate(NEW_ID, arst, past_arst);
- if (cell->type[7] == 'P')
- arst = module->OrGate(NEW_ID, arst, past_arst);
- else
- arst = module->AndGate(NEW_ID, arst, past_arst);
+ if (!ff.val_init.is_fully_undef())
+ initvals.set_init(past_d, ff.val_init);
- if (cell->type[7] == 'P')
- module->addMuxGate(NEW_ID, qval, rstval, arst, sig_q);
+ if (!ff.is_fine)
+ qval = module->Mux(NEW_ID, past_q, past_d, clock_edge);
else
- module->addMuxGate(NEW_ID, rstval, qval, arst, sig_q);
+ qval = module->MuxGate(NEW_ID, past_q, past_d, clock_edge);
+ } else {
+ qval = past_q;
}
- else
- if (cell->type == ID($dffsr))
- {
- SigSpec qval = module->Mux(NEW_ID, past_q, past_d, clock_edge);
- SigSpec setval = cell->getPort(ID::SET);
- SigSpec clrval = cell->getPort(ID::CLR);
-
- if (!cell->parameters[ID::SET_POLARITY].as_bool())
- setval = module->Not(NEW_ID, setval);
-
- if (cell->parameters[ID::CLR_POLARITY].as_bool())
- clrval = module->Not(NEW_ID, clrval);
- qval = module->Or(NEW_ID, qval, setval);
- module->addAnd(NEW_ID, qval, clrval, sig_q);
- }
- else
- 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_)))
- {
- SigSpec qval = module->MuxGate(NEW_ID, past_q, past_d, clock_edge);
- SigSpec setval = cell->getPort(ID::S);
- SigSpec clrval = cell->getPort(ID::R);
-
- if (cell->type[9] != 'P')
- setval = module->Not(NEW_ID, setval);
-
- if (cell->type[10] == 'P')
- clrval = module->Not(NEW_ID, clrval);
+ if (ff.has_aload) {
+ SigSpec sig_aload = wrap_async_control(module, ff.sig_aload, ff.pol_aload);
- qval = module->OrGate(NEW_ID, qval, setval);
- module->addAndGate(NEW_ID, qval, clrval, sig_q);
- }
- else if (cell->type == ID($dff))
- {
- module->addMux(NEW_ID, past_q, past_d, clock_edge, sig_q);
- }
- else
- {
- module->addMuxGate(NEW_ID, past_q, past_d, clock_edge, sig_q);
- }
-
- Const initval;
- bool assign_initval = false;
- for (int i = 0; i < GetSize(sig_d); i++) {
- SigBit qbit = sigmap(sig_q[i]);
- if (initbits.count(qbit)) {
- initval.bits.push_back(initbits.at(qbit));
- del_initbits.insert(qbit);
- } else
- initval.bits.push_back(State::Sx);
- if (initval.bits.back() != State::Sx)
- assign_initval = true;
+ if (!ff.is_fine)
+ qval = module->Mux(NEW_ID, qval, ff.sig_ad, sig_aload);
+ else
+ qval = module->MuxGate(NEW_ID, qval, ff.sig_ad, sig_aload);
}
- if (assign_initval) {
- past_d->attributes[ID::init] = initval;
- past_q->attributes[ID::init] = initval;
+ if (ff.has_sr) {
+ SigSpec setval = wrap_async_control(module, ff.sig_set, ff.pol_set);
+ SigSpec clrval = wrap_async_control(module, ff.sig_clr, ff.pol_clr);
+ if (!ff.is_fine) {
+ clrval = module->Not(NEW_ID, clrval);
+ qval = module->Or(NEW_ID, qval, setval);
+ module->addAnd(NEW_ID, qval, clrval, ff.sig_q);
+ } else {
+ clrval = module->NotGate(NEW_ID, clrval);
+ qval = module->OrGate(NEW_ID, qval, setval);
+ module->addAndGate(NEW_ID, qval, clrval, ff.sig_q);
+ }
+ } else if (ff.has_arst) {
+ SigSpec arst = wrap_async_control(module, ff.sig_arst, ff.pol_arst);
+ if (!ff.is_fine)
+ module->addMux(NEW_ID, qval, ff.val_arst, arst, ff.sig_q);
+ else
+ module->addMuxGate(NEW_ID, qval, ff.val_arst[0], arst, ff.sig_q);
+ } else {
+ module->connect(ff.sig_q, qval);
}
-
- module->remove(cell);
- continue;
}
}
-
- for (auto wire : module->wires())
- if (wire->attributes.count(ID::init) > 0)
- {
- bool delete_initattr = true;
- Const initval = wire->attributes.at(ID::init);
- SigSpec initsig = sigmap(wire);
-
- for (int i = 0; i < GetSize(initval) && i < GetSize(initsig); i++)
- if (del_initbits.count(initsig[i]) > 0)
- initval[i] = State::Sx;
- else if (initval[i] != State::Sx)
- delete_initattr = false;
-
- if (delete_initattr)
- wire->attributes.erase(ID::init);
- else
- wire->attributes.at(ID::init) = initval;
- }
}
}
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 5694a7473..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
@@ -114,8 +114,7 @@ struct FmcombineWorker
Cell *gold = import_prim_cell(cell, "_gold");
Cell *gate = import_prim_cell(cell, "_gate");
if (opts.initeq) {
- if (cell->type.in(ID($ff), ID($dff), ID($dffe),
- ID($dffsr), ID($adff), ID($dlatch), ID($dlatchsr))) {
+ if (RTLIL::builtin_ff_cell_types().count(cell->type)) {
SigSpec gold_q = gold->getPort(ID::Q);
SigSpec gate_q = gate->getPort(ID::Q);
SigSpec en = module->Initstate(NEW_ID);
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 762edfdfb..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
@@ -27,6 +27,7 @@
#include <stdio.h>
#include <string.h>
#include <algorithm>
+#include <limits>
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
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 15abee73e..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
@@ -439,7 +439,7 @@ void mutate_list(Design *design, const mutate_opts_t &opts, const string &filena
dict<SigBit, int> bit_user_cnt;
for (auto wire : module->wires()) {
- if (wire->name[0] == '\\' && wire->attributes.count(ID::src))
+ if (wire->name.isPublic() && wire->attributes.count(ID::src))
sigmap.add(wire);
}
@@ -468,7 +468,7 @@ void mutate_list(Design *design, const mutate_opts_t &opts, const string &filena
}
if (!bit.wire->name[0] != !sigbit.wire->name[0]) {
- if (bit.wire->name[0] == '\\')
+ if (bit.wire->name.isPublic())
sigmap.add(bit);
continue;
}
@@ -493,7 +493,7 @@ void mutate_list(Design *design, const mutate_opts_t &opts, const string &filena
entry.src.insert(s);
SigBit bit = sigmap(conn.second[i]);
- if (bit.wire && bit.wire->name[0] == '\\' && (cell->output(conn.first) || bit_user_cnt[bit] == 1)) {
+ if (bit.wire && bit.wire->name.isPublic() && (cell->output(conn.first) || bit_user_cnt[bit] == 1)) {
for (auto &s : bit.wire->get_strpool_attribute(ID::src))
entry.src.insert(s);
entry.wire = bit.wire->name;
diff --git a/passes/sat/qbfsat.cc b/passes/sat/qbfsat.cc
index 136259558..6db7d4b64 100644
--- a/passes/sat/qbfsat.cc
+++ b/passes/sat/qbfsat.cc
@@ -1,4 +1,4 @@
-/*
+/* -*- c++ -*-
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2020 Alberto Gonzalez <boqwxp@airmail.cc>
@@ -18,13 +18,8 @@
*/
#include "kernel/yosys.h"
-#include "kernel/celltypes.h"
#include "kernel/consteval.h"
-#include "kernel/log.h"
-#include "kernel/rtlil.h"
-#include "kernel/register.h"
-#include <algorithm>
-#include <numeric>
+#include "qbfsat.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -36,156 +31,7 @@ static inline unsigned int difference(unsigned int a, unsigned int b) {
return a - b;
}
-struct QbfSolutionType {
- std::vector<std::string> stdout_lines;
- dict<pool<std::string>, std::string> hole_to_value;
- double solver_time;
- bool sat;
- bool unknown; //true if neither 'sat' nor 'unsat'
-
- QbfSolutionType() : solver_time(0.0), sat(false), unknown(true) {}
-};
-
-struct QbfSolveOptions {
- bool specialize, specialize_from_file, write_solution, nocleanup, dump_final_smt2, assume_outputs, assume_neg;
- bool nooptimize, nobisection;
- bool sat, unsat, show_smtbmc;
- enum Solver{Z3, Yices, CVC4} solver;
- enum OptimizationLevel{O0, O1, O2} oflag;
- int timeout;
- std::string specialize_soln_file;
- std::string write_soln_soln_file;
- std::string dump_final_smt2_file;
- size_t argidx;
- QbfSolveOptions() : specialize(false), specialize_from_file(false), write_solution(false),
- nocleanup(false), dump_final_smt2(false), assume_outputs(false), assume_neg(false),
- nooptimize(false), nobisection(false), sat(false), unsat(false), show_smtbmc(false),
- solver(Yices), oflag(O0), timeout(0), argidx(0) {};
-};
-
-std::string get_solver_name(const QbfSolveOptions &opt) {
- if (opt.solver == opt.Solver::Z3)
- return "z3";
- else if (opt.solver == opt.Solver::Yices)
- return "yices";
- else if (opt.solver == opt.Solver::CVC4)
- return "cvc4";
- else
- log_cmd_error("unknown solver specified.\n");
- return "";
-}
-
-void recover_solution(QbfSolutionType &sol) {
- YS_REGEX_TYPE sat_regex = YS_REGEX_COMPILE("Status: PASSED");
- YS_REGEX_TYPE unsat_regex = YS_REGEX_COMPILE("Solver Error.*model is not available");
- YS_REGEX_TYPE unsat_regex2 = YS_REGEX_COMPILE("Status: FAILED");
- YS_REGEX_TYPE timeout_regex = YS_REGEX_COMPILE("No solution found! \\(timeout\\)");
- YS_REGEX_TYPE timeout_regex2 = YS_REGEX_COMPILE("No solution found! \\(interrupted\\)");
- YS_REGEX_TYPE unknown_regex = YS_REGEX_COMPILE("No solution found! \\(unknown\\)");
- YS_REGEX_TYPE unknown_regex2 = YS_REGEX_COMPILE("Unexpected EOF response from solver");
- YS_REGEX_TYPE memout_regex = YS_REGEX_COMPILE("Solver Error:.*error \"out of memory\"");
- YS_REGEX_TYPE hole_value_regex = YS_REGEX_COMPILE_WITH_SUBS("Value for anyconst in [a-zA-Z0-9_]* \\(([^:]*:[^\\)]*)\\): (.*)");
-#ifndef NDEBUG
- YS_REGEX_TYPE hole_loc_regex = YS_REGEX_COMPILE("[^:]*:[0-9]+.[0-9]+-[0-9]+.[0-9]+");
- YS_REGEX_TYPE hole_val_regex = YS_REGEX_COMPILE("[0-9]+");
-#endif
- YS_REGEX_MATCH_TYPE m;
- bool sat_regex_found = false;
- bool unsat_regex_found = false;
- dict<std::string, bool> hole_value_recovered;
- for (const std::string &x : sol.stdout_lines) {
- if(YS_REGEX_NS::regex_search(x, m, hole_value_regex)) {
- std::string loc = m[1].str();
- std::string val = m[2].str();
-#ifndef NDEBUG
- log_assert(YS_REGEX_NS::regex_search(loc, hole_loc_regex));
- log_assert(YS_REGEX_NS::regex_search(val, hole_val_regex));
-#endif
- auto locs = split_tokens(loc, "|");
- pool<std::string> loc_pool(locs.begin(), locs.end());
- sol.hole_to_value[loc_pool] = val;
- }
- else if (YS_REGEX_NS::regex_search(x, sat_regex)) {
- sat_regex_found = true;
- sol.sat = true;
- sol.unknown = false;
- }
- else if (YS_REGEX_NS::regex_search(x, unsat_regex)) {
- unsat_regex_found = true;
- sol.sat = false;
- sol.unknown = false;
- }
- else if (YS_REGEX_NS::regex_search(x, memout_regex)) {
- sol.unknown = true;
- log_warning("solver ran out of memory\n");
- }
- else if (YS_REGEX_NS::regex_search(x, timeout_regex)) {
- sol.unknown = true;
- log_warning("solver timed out\n");
- }
- else if (YS_REGEX_NS::regex_search(x, timeout_regex2)) {
- sol.unknown = true;
- log_warning("solver timed out\n");
- }
- else if (YS_REGEX_NS::regex_search(x, unknown_regex)) {
- sol.unknown = true;
- log_warning("solver returned \"unknown\"\n");
- }
- else if (YS_REGEX_NS::regex_search(x, unsat_regex2)) {
- unsat_regex_found = true;
- sol.sat = false;
- sol.unknown = false;
- }
- else if (YS_REGEX_NS::regex_search(x, unknown_regex2)) {
- sol.unknown = true;
- }
- }
-#ifndef NDEBUG
- log_assert(!sol.unknown && sol.sat? sat_regex_found : true);
- log_assert(!sol.unknown && !sol.sat? unsat_regex_found : true);
-#endif
-}
-
-dict<std::pair<pool<std::string>, int>, RTLIL::SigBit> get_hole_loc_idx_sigbit_map(RTLIL::Module *module, const QbfSolutionType &sol) {
- dict<std::pair<pool<std::string>, int>, RTLIL::SigBit> hole_loc_idx_to_sigbit;
- pool<RTLIL::SigBit> anyconst_sigbits;
- dict<RTLIL::SigBit, RTLIL::SigBit> anyconst_sigbit_to_wire_sigbit;
-
- for (auto cell : module->cells()) {
- pool<std::string> cell_src = cell->get_strpool_attribute(ID::src);
- auto pos = sol.hole_to_value.find(cell_src);
- if (pos != sol.hole_to_value.end() && cell->type.in("$anyconst", "$anyseq")) {
- RTLIL::SigSpec port_y = cell->getPort(ID::Y);
- for (int i = GetSize(port_y) - 1; i >= 0; --i) {
- hole_loc_idx_to_sigbit[std::make_pair(pos->first, i)] = port_y[i];
- anyconst_sigbits.insert(port_y[i]);
- }
- }
- }
-
- for (auto &conn : module->connections()) {
- auto lhs = conn.first;
- auto rhs = conn.second;
- for (auto i = 0; i < GetSize(rhs); ++i) {
- if (anyconst_sigbits[rhs[i]]) {
- auto pos = anyconst_sigbit_to_wire_sigbit.find(rhs[i]);
- if (pos != anyconst_sigbit_to_wire_sigbit.end())
- log_cmd_error("conflicting names for hole $anyconst sigbit %s\n", log_signal(rhs[i]));
- anyconst_sigbit_to_wire_sigbit[rhs[i]] = lhs[i];
- }
- }
- }
-
- for (auto &it : hole_loc_idx_to_sigbit) {
- auto pos = anyconst_sigbit_to_wire_sigbit.find(it.second);
- if (pos != anyconst_sigbit_to_wire_sigbit.end())
- it.second = pos->second;
- }
-
- return hole_loc_idx_to_sigbit;
-}
-
-pool<std::string> validate_design_and_get_inputs(RTLIL::Module *module, const QbfSolveOptions &opt) {
+pool<std::string> validate_design_and_get_inputs(RTLIL::Module *module, bool assume_outputs) {
bool found_input = false;
bool found_hole = false;
bool found_1bit_output = false;
@@ -213,53 +59,16 @@ pool<std::string> validate_design_and_get_inputs(RTLIL::Module *module, const Qb
log_cmd_error("Did not find any existentially-quantified variables. Use 'sat' instead.\n");
if (!found_1bit_output && !found_assert_assume)
log_cmd_error("Did not find any single-bit outputs or $assert/$assume cells. Is this a miter circuit?\n");
- if (!found_assert_assume && !opt.assume_outputs)
+ if (!found_assert_assume && !assume_outputs)
log_cmd_error("Did not find any $assert/$assume cells. Single-bit outputs were found, but `-assume-outputs` was not specified.\n");
return input_wires;
}
-void write_solution(RTLIL::Module *module, const QbfSolutionType &sol, const std::string &file) {
- std::ofstream fout(file.c_str());
- if (!fout)
- log_cmd_error("could not open solution file for writing.\n");
-
- //There is a question here: How exactly shall we identify holes?
- //There are at least two reasonable options:
- //1. By the source location of the $anyconst cells
- //2. By the name(s) of the wire(s) connected to each SigBit of the $anyconst cell->getPort(ID::Y) SigSpec.
- //
- //Option 1 has the benefit of being very precise. There is very limited potential for confusion, as long
- //as the source attribute has been set. However, if the source attribute is not set, this won't work.
- //More importantly, we want to have the ability to port hole assignments to other modules with compatible
- //hole names and widths. Obviously in those cases source locations of the $anyconst cells will not match.
- //
- //Option 2 has the benefits previously described, but wire names can be changed automatically by
- //optimization or techmapping passes, especially when (ex/im)porting from BLIF for optimization with ABC.
- //
- //The approach taken here is to allow both options. We write the assignment information for each bit of
- //the solution on a separate line. Each line is of one of two forms:
- //
- //location bit name = value
- //location bit name [offset] = value
- //
- //where '[', ']', and '=' are literal symbols, "location" is the $anyconst cell source location attribute,
- //"bit" is the index of the $anyconst cell, "name" is the `wire->name` field of the SigBit corresponding
- //to the current bit of the $anyconst cell->getPort(ID::Y), "offset" is the `offset` field of that same
- //SigBit, and "value", which is either '0' or '1', represents the assignment for that bit.
- dict<std::pair<pool<std::string>, int>, RTLIL::SigBit> hole_loc_idx_to_sigbit = get_hole_loc_idx_sigbit_map(module, sol);
- for (auto &x : sol.hole_to_value) {
- std::string src_as_str = std::accumulate(x.first.begin(), x.first.end(), std::string(), [](const std::string &a, const std::string &b){return a + "|" + b;});
- for (auto i = 0; i < GetSize(x.second); ++i)
- fout << src_as_str.c_str() << " " << i << " " << log_signal(hole_loc_idx_to_sigbit[std::make_pair(x.first, i)]) << " = " << x.second[GetSize(x.second) - 1 - i] << std::endl;
- }
-}
-
void specialize_from_file(RTLIL::Module *module, const std::string &file) {
YS_REGEX_TYPE hole_bit_assn_regex = YS_REGEX_COMPILE_WITH_SUBS("^(.+) ([0-9]+) ([^ ]+) \\[([0-9]+)] = ([01])$");
YS_REGEX_TYPE hole_assn_regex = YS_REGEX_COMPILE_WITH_SUBS("^(.+) ([0-9]+) ([^ ]+) = ([01])$"); //if no index specified
YS_REGEX_MATCH_TYPE bit_m, m;
- //(hole_loc, hole_bit, hole_name, hole_offset) -> (value, found)
dict<pool<std::string>, RTLIL::Cell*> anyconst_loc_to_cell;
dict<RTLIL::SigBit, RTLIL::State> hole_assignments;
@@ -318,7 +127,7 @@ void specialize_from_file(RTLIL::Module *module, const std::string &file) {
}
void specialize(RTLIL::Module *module, const QbfSolutionType &sol, bool quiet = false) {
- dict<std::pair<pool<std::string>, int>, RTLIL::SigBit> hole_loc_idx_to_sigbit = get_hole_loc_idx_sigbit_map(module, sol);
+ auto hole_loc_idx_to_sigbit = sol.get_hole_loc_idx_sigbit_map(module);
pool<RTLIL::Cell *> anyconsts_to_remove;
for (auto cell : module->cells())
if (cell->type == "$anyconst")
@@ -348,30 +157,10 @@ void specialize(RTLIL::Module *module, const QbfSolutionType &sol, bool quiet =
}
}
-void dump_model(RTLIL::Module *module, const QbfSolutionType &sol) {
- log("Satisfiable model:\n");
- dict<std::pair<pool<std::string>, int>, RTLIL::SigBit> hole_loc_idx_to_sigbit = get_hole_loc_idx_sigbit_map(module, sol);
- for (auto &it : sol.hole_to_value) {
- pool<std::string> hole_loc = it.first;
- std::string hole_value = it.second;
-
- for (unsigned int i = 0; i < hole_value.size(); ++i) {
- int bit_idx = GetSize(hole_value) - 1 - i;
- auto it = hole_loc_idx_to_sigbit.find(std::make_pair(hole_loc, i));
- log_assert(it != hole_loc_idx_to_sigbit.end());
-
- RTLIL::SigBit hole_sigbit = it->second;
- log("\t%s = 1'b%c\n", log_signal(hole_sigbit), hole_value[bit_idx]);
- }
- }
-}
-
void allconstify_inputs(RTLIL::Module *module, const pool<std::string> &input_wires) {
for (auto &n : input_wires) {
RTLIL::Wire *input = module->wire(n);
-#ifndef NDEBUG
log_assert(input != nullptr);
-#endif
RTLIL::Cell *allconst = module->addCell("$allconst$" + n, "$allconst");
allconst->setParam(ID(WIDTH), input->width);
@@ -383,7 +172,7 @@ void allconstify_inputs(RTLIL::Module *module, const pool<std::string> &input_wi
module->fixup_ports();
}
-void assume_miter_outputs(RTLIL::Module *module, const QbfSolveOptions &opt) {
+void assume_miter_outputs(RTLIL::Module *module, bool assume_neg) {
std::vector<RTLIL::Wire *> wires_to_assume;
for (auto w : module->wires())
if (w->port_output && w->width == 1)
@@ -398,7 +187,7 @@ void assume_miter_outputs(RTLIL::Module *module, const QbfSolveOptions &opt) {
log("\n");
}
- if (opt.assume_neg) {
+ if (assume_neg) {
for (unsigned int i = 0; i < wires_to_assume.size(); ++i) {
RTLIL::SigSpec n_wire = module->LogicNot(wires_to_assume[i]->name.str() + "__n__qbfsat", wires_to_assume[i], false, wires_to_assume[i]->get_src_attribute());
wires_to_assume[i] = n_wire.as_wire();
@@ -418,9 +207,7 @@ void assume_miter_outputs(RTLIL::Module *module, const QbfSolveOptions &opt) {
wires_to_assume.swap(buf);
}
-#ifndef NDEBUG
log_assert(wires_to_assume.size() == 1);
-#endif
module->addAssume("$assume_qbfsat_miter_outputs", wires_to_assume[0], RTLIL::S1);
}
@@ -428,10 +215,17 @@ QbfSolutionType call_qbf_solver(RTLIL::Module *mod, const QbfSolveOptions &opt,
//Execute and capture stdout from `yosys-smtbmc -s z3 -t 1 -g --binary [--dump-smt2 <file>]`
QbfSolutionType ret;
const std::string yosys_smtbmc_exe = proc_self_dirname() + "yosys-smtbmc";
- const std::string smt2_command = "write_smt2 -stbv -wires " + tempdir_name + "/problem" + (iter_num != 0? stringf("%d", iter_num) : "") + ".smt2";
const std::string smtbmc_warning = "z3: WARNING:";
- const std::string smtbmc_cmd = yosys_smtbmc_exe + " -s " + (get_solver_name(opt)) + (opt.timeout != 0? stringf(" --timeout %d", opt.timeout) : "") + " -t 1 -g --binary " + (opt.dump_final_smt2? "--dump-smt2 " + opt.dump_final_smt2_file + " " : "") + tempdir_name + "/problem" + (iter_num != 0? stringf("%d", iter_num) : "") + ".smt2 2>&1";
-
+ const std::string smtbmc_cmd = stringf("%s -s %s %s -t 1 -g --binary %s %s/problem%d.smt2 2>&1",
+ yosys_smtbmc_exe.c_str(), opt.get_solver_name().c_str(),
+ (opt.timeout != 0? stringf("--timeout %d", opt.timeout) : "").c_str(),
+ (opt.dump_final_smt2? "--dump-smt2 " + opt.dump_final_smt2_file : "").c_str(),
+ tempdir_name.c_str(), iter_num);
+
+ std::string smt2_command = "write_smt2 -stbv -wires ";
+ for (auto &solver_opt : opt.solver_options)
+ smt2_command += stringf("-solver-option %s %s ", solver_opt.first.c_str(), solver_opt.second.c_str());
+ smt2_command += stringf("%s/problem%d.smt2", tempdir_name.c_str(), iter_num);
Pass::call(mod->design, smt2_command);
auto process_line = [&ret, &smtbmc_warning, &opt, &quiet](const std::string &line) {
@@ -451,13 +245,13 @@ QbfSolutionType call_qbf_solver(RTLIL::Module *mod, const QbfSolveOptions &opt,
ret.solver_time = (end - begin) / 1e9f;
if (!quiet) log("Solver finished in %.3f seconds.\n", ret.solver_time);
- recover_solution(ret);
+ ret.recover_solution();
return ret;
}
QbfSolutionType qbf_solve(RTLIL::Module *mod, const QbfSolveOptions &opt) {
QbfSolutionType ret, best_soln;
- const std::string tempdir_name = make_temp_dir("/tmp/yosys-z3-XXXXXX");
+ const std::string tempdir_name = make_temp_dir("/tmp/yosys-qbfsat-XXXXXX");
RTLIL::Module *module = mod;
RTLIL::Design *design = module->design;
std::string module_name = module->name.str();
@@ -468,10 +262,10 @@ QbfSolutionType qbf_solve(RTLIL::Module *mod, const QbfSolveOptions &opt) {
Pass::call(design, "design -push-copy");
//Replace input wires with wires assigned $allconst cells:
- pool<std::string> input_wires = validate_design_and_get_inputs(module, opt);
+ pool<std::string> input_wires = validate_design_and_get_inputs(module, opt.assume_outputs);
allconstify_inputs(module, input_wires);
if (opt.assume_outputs)
- assume_miter_outputs(module, opt);
+ assume_miter_outputs(module, opt.assume_neg);
//Find the wire to be optimized, if any:
for (auto wire : module->wires()) {
@@ -628,6 +422,13 @@ QbfSolveOptions parse_args(const std::vector<std::string> &args) {
}
continue;
}
+ else if (args[opt.argidx] == "-solver-option") {
+ if (args.size() <= opt.argidx + 2)
+ log_cmd_error("solver option name and value not fully specified.\n");
+ opt.solver_options.emplace(args[opt.argidx+1], args[opt.argidx+2]);
+ opt.argidx += 2;
+ continue;
+ }
else if (args[opt.argidx] == "-timeout") {
if (args.size() <= opt.argidx + 1)
log_cmd_error("timeout not specified.\n");
@@ -699,33 +500,6 @@ QbfSolveOptions parse_args(const std::vector<std::string> &args) {
return opt;
}
-void print_proof_failed()
-{
- log("\n");
- log(" ______ ___ ___ _ _ _ _ \n");
- log(" (_____ \\ / __) / __) (_) | | | |\n");
- log(" _____) )___ ___ ___ _| |__ _| |__ _____ _| | _____ __| | |\n");
- log(" | ____/ ___) _ \\ / _ (_ __) (_ __|____ | | || ___ |/ _ |_|\n");
- log(" | | | | | |_| | |_| || | | | / ___ | | || ____( (_| |_ \n");
- log(" |_| |_| \\___/ \\___/ |_| |_| \\_____|_|\\_)_____)\\____|_|\n");
- log("\n");
-}
-
-void print_qed()
-{
- log("\n");
- log(" /$$$$$$ /$$$$$$$$ /$$$$$$$ \n");
- log(" /$$__ $$ | $$_____/ | $$__ $$ \n");
- log(" | $$ \\ $$ | $$ | $$ \\ $$ \n");
- log(" | $$ | $$ | $$$$$ | $$ | $$ \n");
- log(" | $$ | $$ | $$__/ | $$ | $$ \n");
- log(" | $$/$$ $$ | $$ | $$ | $$ \n");
- log(" | $$$$$$/ /$$| $$$$$$$$ /$$| $$$$$$$//$$\n");
- log(" \\____ $$$|__/|________/|__/|_______/|__/\n");
- log(" \\__/ \n");
- log("\n");
-}
-
struct QbfSatPass : public Pass {
QbfSatPass() : Pass("qbfsat", "solve a 2QBF-SAT problem in the circuit") { }
void help() override
@@ -767,9 +541,14 @@ struct QbfSatPass : public Pass {
log("\n");
log(" -solver <solver>\n");
log(" Use a particular solver. Choose one of: \"z3\", \"yices\", and \"cvc4\".\n");
+ log(" (default: yices)\n");
+ log("\n");
+ log(" -solver-option <name> <value>\n");
+ log(" Set the specified solver option in the SMT-LIBv2 problem file.\n");
log("\n");
log(" -timeout <value>\n");
log(" Set the per-iteration timeout in seconds.\n");
+ log(" (default: no timeout)\n");
log("\n");
log(" -O0, -O1, -O2\n");
log(" Control the use of ABC to simplify the QBF-SAT problem before solving.\n");
@@ -827,12 +606,12 @@ struct QbfSatPass : public Pass {
else if (ret.sat) {
print_qed();
if (opt.write_solution) {
- write_solution(module, ret, opt.write_soln_soln_file);
+ ret.write_solution(module, opt.write_soln_soln_file);
}
if (opt.specialize) {
specialize(module, ret);
} else {
- dump_model(module, ret);
+ ret.dump_model(module);
}
if (opt.unsat)
log_cmd_error("expected problem to be UNSAT\n");
diff --git a/passes/sat/qbfsat.h b/passes/sat/qbfsat.h
new file mode 100644
index 000000000..c96c6f818
--- /dev/null
+++ b/passes/sat/qbfsat.h
@@ -0,0 +1,253 @@
+/* -*- c++ -*-
+ * 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.
+ *
+ */
+
+#ifndef QBFSAT_H
+#define QBFSAT_H
+
+#include "kernel/yosys.h"
+#include <numeric>
+
+YOSYS_NAMESPACE_BEGIN
+
+struct QbfSolveOptions {
+ bool specialize = false, specialize_from_file = false, write_solution = false, nocleanup = false;
+ bool dump_final_smt2 = false, assume_outputs = false, assume_neg = false, nooptimize = false;
+ bool nobisection = false, sat = false, unsat = false, show_smtbmc = false;
+ enum Solver{Z3, Yices, CVC4} solver = Yices;
+ enum OptimizationLevel{O0, O1, O2} oflag = O0;
+ dict<std::string, std::string> solver_options;
+ int timeout = 0;
+ std::string specialize_soln_file = "";
+ std::string write_soln_soln_file = "";
+ std::string dump_final_smt2_file = "";
+ size_t argidx = 0;
+
+ std::string get_solver_name() const {
+ if (solver == Solver::Z3)
+ return "z3";
+ else if (solver == Solver::Yices)
+ return "yices";
+ else if (solver == Solver::CVC4)
+ return "cvc4";
+
+ log_cmd_error("unknown solver specified.\n");
+ return "";
+ }
+};
+
+struct QbfSolutionType {
+ std::vector<std::string> stdout_lines = {};
+ dict<pool<std::string>, std::string> hole_to_value = {};
+ double solver_time = 0;
+ bool sat = false;
+ bool unknown = true; //true if neither 'sat' nor 'unsat'
+
+ dict<std::pair<pool<std::string>, int>, RTLIL::SigBit> get_hole_loc_idx_sigbit_map(RTLIL::Module *module) const {
+ dict<std::pair<pool<std::string>, int>, RTLIL::SigBit> hole_loc_idx_to_sigbit;
+ pool<RTLIL::SigBit> anyconst_sigbits;
+ dict<RTLIL::SigBit, RTLIL::SigBit> anyconst_sigbit_to_wire_sigbit;
+
+ for (auto cell : module->cells()) {
+ pool<std::string> cell_src = cell->get_strpool_attribute(ID::src);
+ auto pos = hole_to_value.find(cell_src);
+ if (pos != hole_to_value.end() && cell->type.in("$anyconst", "$anyseq")) {
+ RTLIL::SigSpec port_y = cell->getPort(ID::Y);
+ for (int i = GetSize(port_y) - 1; i >= 0; --i) {
+ hole_loc_idx_to_sigbit[std::make_pair(pos->first, i)] = port_y[i];
+ anyconst_sigbits.insert(port_y[i]);
+ }
+ }
+ }
+
+ for (auto &conn : module->connections()) {
+ auto lhs = conn.first;
+ auto rhs = conn.second;
+ for (auto i = 0; i < GetSize(rhs); ++i) {
+ if (anyconst_sigbits[rhs[i]]) {
+ auto pos = anyconst_sigbit_to_wire_sigbit.find(rhs[i]);
+ if (pos != anyconst_sigbit_to_wire_sigbit.end())
+ log_cmd_error("conflicting names for hole $anyconst sigbit %s\n", log_signal(rhs[i]));
+ anyconst_sigbit_to_wire_sigbit[rhs[i]] = lhs[i];
+ }
+ }
+ }
+
+ for (auto &it : hole_loc_idx_to_sigbit) {
+ auto pos = anyconst_sigbit_to_wire_sigbit.find(it.second);
+ if (pos != anyconst_sigbit_to_wire_sigbit.end())
+ it.second = pos->second;
+ }
+
+ return hole_loc_idx_to_sigbit;
+ }
+
+ void dump_model(RTLIL::Module *module) const {
+ log("Satisfiable model:\n");
+ auto hole_loc_idx_to_sigbit = get_hole_loc_idx_sigbit_map(module);
+ for (auto &it : hole_to_value) {
+ pool<std::string> hole_loc = it.first;
+ std::string hole_value = it.second;
+
+ for (unsigned int i = 0; i < hole_value.size(); ++i) {
+ int bit_idx = GetSize(hole_value) - 1 - i;
+ auto it = hole_loc_idx_to_sigbit.find(std::make_pair(hole_loc, i));
+ log_assert(it != hole_loc_idx_to_sigbit.end());
+
+ RTLIL::SigBit hole_sigbit = it->second;
+ log("\t%s = 1'b%c\n", log_signal(hole_sigbit), hole_value[bit_idx]);
+ }
+ }
+ }
+
+ void write_solution(RTLIL::Module *module, const std::string &file) const {
+ std::ofstream fout(file.c_str());
+ if (!fout)
+ log_cmd_error("could not open solution file for writing.\n");
+
+ //There is a question here: How exactly shall we identify holes?
+ //There are at least two reasonable options:
+ //1. By the source location of the $anyconst cells
+ //2. By the name(s) of the wire(s) connected to each SigBit of the $anyconst cell->getPort(ID::Y) SigSpec.
+ //
+ //Option 1 has the benefit of being very precise. There is very limited potential for confusion, as long
+ //as the source attribute has been set. However, if the source attribute is not set, this won't work.
+ //More importantly, we want to have the ability to port hole assignments to other modules with compatible
+ //hole names and widths. Obviously in those cases source locations of the $anyconst cells will not match.
+ //
+ //Option 2 has the benefits previously described, but wire names can be changed automatically by
+ //optimization or techmapping passes, especially when (ex/im)porting from BLIF for optimization with ABC.
+ //
+ //The approach taken here is to allow both options. We write the assignment information for each bit of
+ //the solution on a separate line. Each line is of one of two forms:
+ //
+ //location bit name = value
+ //location bit name [offset] = value
+ //
+ //where '[', ']', and '=' are literal symbols, "location" is the $anyconst cell source location attribute,
+ //"bit" is the index of the $anyconst cell, "name" is the `wire->name` field of the SigBit corresponding
+ //to the current bit of the $anyconst cell->getPort(ID::Y), "offset" is the `offset` field of that same
+ //SigBit, and "value", which is either '0' or '1', represents the assignment for that bit.
+ auto hole_loc_idx_to_sigbit = get_hole_loc_idx_sigbit_map(module);
+ for (auto &x : hole_to_value) {
+ std::string src_as_str = std::accumulate(x.first.begin(), x.first.end(), std::string(), [](const std::string &a, const std::string &b){return a + "|" + b;});
+ for (auto i = 0; i < GetSize(x.second); ++i)
+ fout << src_as_str.c_str() << " " << i << " " << log_signal(hole_loc_idx_to_sigbit[std::make_pair(x.first, i)]) << " = " << x.second[GetSize(x.second) - 1 - i] << std::endl;
+ }
+ }
+
+ void recover_solution() {
+ YS_REGEX_TYPE sat_regex = YS_REGEX_COMPILE("Status: PASSED");
+ YS_REGEX_TYPE unsat_regex = YS_REGEX_COMPILE("Solver Error.*model is not available");
+ YS_REGEX_TYPE unsat_regex2 = YS_REGEX_COMPILE("Status: FAILED");
+ YS_REGEX_TYPE timeout_regex = YS_REGEX_COMPILE("No solution found! \\(timeout\\)");
+ YS_REGEX_TYPE timeout_regex2 = YS_REGEX_COMPILE("No solution found! \\(interrupted\\)");
+ YS_REGEX_TYPE unknown_regex = YS_REGEX_COMPILE("No solution found! \\(unknown\\)");
+ YS_REGEX_TYPE unknown_regex2 = YS_REGEX_COMPILE("Unexpected EOF response from solver");
+ YS_REGEX_TYPE memout_regex = YS_REGEX_COMPILE("Solver Error:.*error \"out of memory\"");
+ YS_REGEX_TYPE hole_value_regex = YS_REGEX_COMPILE_WITH_SUBS("Value for anyconst in [a-zA-Z0-9_]* \\(([^:]*:[^\\)]*)\\): (.*)");
+#ifndef NDEBUG
+ YS_REGEX_TYPE hole_loc_regex = YS_REGEX_COMPILE("[^:]*:[0-9]+.[0-9]+-[0-9]+.[0-9]+");
+ YS_REGEX_TYPE hole_val_regex = YS_REGEX_COMPILE("[0-9]+");
+#endif
+ YS_REGEX_MATCH_TYPE m;
+ bool sat_regex_found = false;
+ bool unsat_regex_found = false;
+ dict<std::string, bool> hole_value_recovered;
+ for (const std::string &x : stdout_lines) {
+ if(YS_REGEX_NS::regex_search(x, m, hole_value_regex)) {
+ std::string loc = m[1].str();
+ std::string val = m[2].str();
+#ifndef NDEBUG
+ log_assert(YS_REGEX_NS::regex_search(loc, hole_loc_regex));
+ log_assert(YS_REGEX_NS::regex_search(val, hole_val_regex));
+#endif
+ auto locs = split_tokens(loc, "|");
+ pool<std::string> loc_pool(locs.begin(), locs.end());
+ hole_to_value[loc_pool] = val;
+ }
+ else if (YS_REGEX_NS::regex_search(x, sat_regex)) {
+ sat_regex_found = true;
+ sat = true;
+ unknown = false;
+ }
+ else if (YS_REGEX_NS::regex_search(x, unsat_regex)) {
+ unsat_regex_found = true;
+ sat = false;
+ unknown = false;
+ }
+ else if (YS_REGEX_NS::regex_search(x, memout_regex)) {
+ unknown = true;
+ log_warning("solver ran out of memory\n");
+ }
+ else if (YS_REGEX_NS::regex_search(x, timeout_regex)) {
+ unknown = true;
+ log_warning("solver timed out\n");
+ }
+ else if (YS_REGEX_NS::regex_search(x, timeout_regex2)) {
+ unknown = true;
+ log_warning("solver timed out\n");
+ }
+ else if (YS_REGEX_NS::regex_search(x, unknown_regex)) {
+ unknown = true;
+ log_warning("solver returned \"unknown\"\n");
+ }
+ else if (YS_REGEX_NS::regex_search(x, unsat_regex2)) {
+ unsat_regex_found = true;
+ sat = false;
+ unknown = false;
+ }
+ else if (YS_REGEX_NS::regex_search(x, unknown_regex2)) {
+ unknown = true;
+ }
+ }
+ log_assert(!unknown && sat? sat_regex_found : true);
+ log_assert(!unknown && !sat? unsat_regex_found : true);
+ }
+};
+
+void print_proof_failed()
+{
+ log("\n");
+ log(" ______ ___ ___ _ _ _ _ \n");
+ log(" (_____ \\ / __) / __) (_) | | | |\n");
+ log(" _____) )___ ___ ___ _| |__ _| |__ _____ _| | _____ __| | |\n");
+ log(" | ____/ ___) _ \\ / _ (_ __) (_ __|____ | | || ___ |/ _ |_|\n");
+ log(" | | | | | |_| | |_| || | | | / ___ | | || ____( (_| |_ \n");
+ log(" |_| |_| \\___/ \\___/ |_| |_| \\_____|_|\\_)_____)\\____|_|\n");
+ log("\n");
+}
+
+void print_qed()
+{
+ log("\n");
+ log(" /$$$$$$ /$$$$$$$$ /$$$$$$$ \n");
+ log(" /$$__ $$ | $$_____/ | $$__ $$ \n");
+ log(" | $$ \\ $$ | $$ | $$ \\ $$ \n");
+ log(" | $$ | $$ | $$$$$ | $$ | $$ \n");
+ log(" | $$ | $$ | $$__/ | $$ | $$ \n");
+ log(" | $$/$$ $$ | $$ | $$ | $$ \n");
+ log(" | $$$$$$/ /$$| $$$$$$$$ /$$| $$$$$$$//$$\n");
+ log(" \\____ $$$|__/|________/|__/|_______/|__/\n");
+ log(" \\__/ \n");
+ log("\n");
+}
+
+YOSYS_NAMESPACE_END
+
+#endif
diff --git a/passes/sat/sat.cc b/passes/sat/sat.cc
index d7bf125d1..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
@@ -1365,7 +1365,7 @@ struct SatPass : public Pass {
if (show_public) {
for (auto wire : module->wires())
- if (wire->name[0] == '\\')
+ if (wire->name.isPublic())
shows.push_back(wire->name.str());
}
diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc
index fb496ff87..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
@@ -20,10 +20,50 @@
#include "kernel/yosys.h"
#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;
@@ -31,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)
@@ -48,7 +93,8 @@ void zinit(Const &v)
struct SimInstance
{
SimShared *shared;
-
+
+ std::string scope;
Module *module;
Cell *instance;
@@ -62,6 +108,7 @@ struct SimInstance
pool<SigBit> dirty_bits;
pool<Cell*> dirty_cells;
+ pool<IdString> dirty_memories;
pool<SimInstance*, hash_ptr_ops> dirty_children;
struct ff_state_t
@@ -72,21 +119,27 @@ struct SimInstance
struct mem_state_t
{
- Const past_wr_clk;
- Const past_wr_en;
- Const past_wr_addr;
- Const past_wr_data;
+ Mem *mem;
+ std::vector<Const> past_wr_clk;
+ std::vector<Const> past_wr_en;
+ std::vector<Const> past_wr_addr;
+ std::vector<Const> past_wr_data;
Const data;
};
dict<Cell*, ff_state_t> ff_database;
- dict<Cell*, mem_state_t> mem_database;
+ dict<IdString, mem_state_t> mem_database;
pool<Cell*> formal_database;
+ dict<Cell*, IdString> mem_cells;
+
+ 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);
@@ -108,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++)
@@ -118,12 +178,25 @@ struct SimInstance
}
}
+ memories = Mem::get_all_memories(module);
+ for (auto &mem : memories) {
+ auto &mdb = mem_database[mem.memid];
+ mdb.mem = &mem;
+ for (auto &port : mem.wr_ports) {
+ mdb.past_wr_clk.push_back(Const(State::Sx));
+ mdb.past_wr_en.push_back(Const(State::Sx, GetSize(port.en)));
+ mdb.past_wr_addr.push_back(Const(State::Sx, GetSize(port.addr)));
+ mdb.past_wr_data.push_back(Const(State::Sx, GetSize(port.data)));
+ }
+ mdb.data = mem.get_init_data();
+ }
+
for (auto cell : module->cells())
{
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()) {
@@ -143,29 +216,9 @@ struct SimInstance
ff_database[cell] = ff;
}
- if (cell->type == ID($mem))
+ if (cell->is_mem_cell())
{
- mem_state_t mem;
-
- mem.past_wr_clk = Const(State::Sx, GetSize(cell->getPort(ID::WR_CLK)));
- mem.past_wr_en = Const(State::Sx, GetSize(cell->getPort(ID::WR_EN)));
- mem.past_wr_addr = Const(State::Sx, GetSize(cell->getPort(ID::WR_ADDR)));
- mem.past_wr_data = Const(State::Sx, GetSize(cell->getPort(ID::WR_DATA)));
-
- mem.data = cell->getParam(ID::INIT);
- int sz = cell->getParam(ID::SIZE).as_int() * cell->getParam(ID::WIDTH).as_int();
-
- if (GetSize(mem.data) > sz)
- mem.data.bits.resize(sz);
-
- while (GetSize(mem.data) < sz)
- mem.data.bits.push_back(State::Sx);
-
- mem_database[cell] = mem;
- }
- if (cell->type.in(ID($memwr),ID($memrd)))
- {
- log_error("$memrd and $memwr cells have to be merged to stand-alone $mem cells (execute memory_collect pass)\n");
+ mem_cells[cell] = cell->parameters.at(ID::MEMID).decode_string();
}
if (cell->type.in(ID($assert), ID($cover), ID($assume))) {
formal_database.insert(cell);
@@ -188,7 +241,8 @@ struct SimInstance
for (auto &it : mem_database) {
mem_state_t &mem = it.second;
- zinit(mem.past_wr_en);
+ for (auto &val : mem.past_wr_en)
+ zinit(val);
zinit(mem.data);
}
}
@@ -259,37 +313,9 @@ struct SimInstance
if (formal_database.count(cell))
return;
- if (mem_database.count(cell))
+ if (mem_cells.count(cell))
{
- mem_state_t &mem = mem_database.at(cell);
-
- int num_rd_ports = cell->getParam(ID::RD_PORTS).as_int();
-
- int size = cell->getParam(ID::SIZE).as_int();
- int offset = cell->getParam(ID::OFFSET).as_int();
- int abits = cell->getParam(ID::ABITS).as_int();
- int width = cell->getParam(ID::WIDTH).as_int();
-
- if (cell->getParam(ID::RD_CLK_ENABLE).as_bool())
- log_error("Memory %s.%s has clocked read ports. Run 'memory' with -nordff.\n", log_id(module), log_id(cell));
-
- SigSpec rd_addr_sig = cell->getPort(ID::RD_ADDR);
- SigSpec rd_data_sig = cell->getPort(ID::RD_DATA);
-
- for (int port_idx = 0; port_idx < num_rd_ports; port_idx++)
- {
- Const addr = get_state(rd_addr_sig.extract(port_idx*abits, abits));
- Const data = Const(State::Sx, width);
-
- if (addr.is_fully_def()) {
- int index = addr.as_int() - offset;
- if (index >= 0 && index < size)
- data = mem.data.extract(index*width, width);
- }
-
- set_state(rd_data_sig.extract(port_idx*width, width), data);
- }
-
+ dirty_memories.insert(mem_cells[cell]);
return;
}
@@ -297,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);
}
@@ -339,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)));
@@ -352,6 +384,29 @@ struct SimInstance
log_error("Unsupported cell type: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell));
}
+ void update_memory(IdString id) {
+ auto &mdb = mem_database[id];
+ auto &mem = *mdb.mem;
+
+ for (int port_idx = 0; port_idx < GetSize(mem.rd_ports); port_idx++)
+ {
+ auto &port = mem.rd_ports[port_idx];
+ Const addr = get_state(port.addr);
+ 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));
+
+ 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 << port.wide_log2);
+ }
+
+ set_state(port.data, data);
+ }
+ }
+
void update_ph1()
{
pool<Cell*> queue_cells;
@@ -383,6 +438,10 @@ struct SimInstance
continue;
}
+ for (auto &memid : dirty_memories)
+ update_memory(memid);
+ dirty_memories.clear();
+
for (auto wire : queue_outports)
if (instance->hasPort(wire->name)) {
Const value = get_state(wire);
@@ -426,50 +485,40 @@ struct SimInstance
for (auto &it : mem_database)
{
- Cell *cell = it.first;
- mem_state_t &mem = it.second;
-
- int num_wr_ports = cell->getParam(ID::WR_PORTS).as_int();
-
- int size = cell->getParam(ID::SIZE).as_int();
- int offset = cell->getParam(ID::OFFSET).as_int();
- int abits = cell->getParam(ID::ABITS).as_int();
- int width = cell->getParam(ID::WIDTH).as_int();
+ mem_state_t &mdb = it.second;
+ auto &mem = *mdb.mem;
- Const wr_clk_enable = cell->getParam(ID::WR_CLK_ENABLE);
- Const wr_clk_polarity = cell->getParam(ID::WR_CLK_POLARITY);
- Const current_wr_clk = get_state(cell->getPort(ID::WR_CLK));
-
- for (int port_idx = 0; port_idx < num_wr_ports; port_idx++)
+ for (int port_idx = 0; port_idx < GetSize(mem.wr_ports); port_idx++)
{
+ auto &port = mem.wr_ports[port_idx];
Const addr, data, enable;
- if (wr_clk_enable[port_idx] == State::S0)
+ if (!port.clk_enable)
{
- addr = get_state(cell->getPort(ID::WR_ADDR).extract(port_idx*abits, abits));
- data = get_state(cell->getPort(ID::WR_DATA).extract(port_idx*width, width));
- enable = get_state(cell->getPort(ID::WR_EN).extract(port_idx*width, width));
+ addr = get_state(port.addr);
+ data = get_state(port.data);
+ enable = get_state(port.en);
}
else
{
- if (wr_clk_polarity[port_idx] == State::S1 ?
- (mem.past_wr_clk[port_idx] == State::S1 || current_wr_clk[port_idx] != State::S1) :
- (mem.past_wr_clk[port_idx] == State::S0 || current_wr_clk[port_idx] != State::S0))
+ if (port.clk_polarity ?
+ (mdb.past_wr_clk[port_idx] == State::S1 || get_state(port.clk) != State::S1) :
+ (mdb.past_wr_clk[port_idx] == State::S0 || get_state(port.clk) != State::S0))
continue;
- addr = mem.past_wr_addr.extract(port_idx*abits, abits);
- data = mem.past_wr_data.extract(port_idx*width, width);
- enable = mem.past_wr_en.extract(port_idx*width, width);
+ addr = mdb.past_wr_addr[port_idx];
+ data = mdb.past_wr_data[port_idx];
+ enable = mdb.past_wr_en[port_idx];
}
if (addr.is_fully_def())
{
- int index = addr.as_int() - offset;
- if (index >= 0 && index < size)
- for (int i = 0; i < width; i++)
- if (enable[i] == State::S1 && mem.data.bits.at(index*width+i) != data[i]) {
- mem.data.bits.at(index*width+i) = data[i];
- dirty_cells.insert(cell);
+ int index = addr.as_int() - mem.start_offset;
+ if (index >= 0 && index < mem.size)
+ 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);
did_something = true;
}
}
@@ -500,13 +549,15 @@ struct SimInstance
for (auto &it : mem_database)
{
- Cell *cell = it.first;
mem_state_t &mem = it.second;
- mem.past_wr_clk = get_state(cell->getPort(ID::WR_CLK));
- mem.past_wr_en = get_state(cell->getPort(ID::WR_EN));
- mem.past_wr_addr = get_state(cell->getPort(ID::WR_ADDR));
- mem.past_wr_data = get_state(cell->getPort(ID::WR_DATA));
+ for (int i = 0; i < GetSize(mem.mem->wr_ports); i++) {
+ auto &port = mem.mem->wr_ports[i];
+ mem.past_wr_clk[i] = get_state(port.clk);
+ mem.past_wr_en[i] = get_state(port.en);
+ mem.past_wr_addr[i] = get_state(port.addr);
+ mem.past_wr_data[i] = get_state(port.data);
+ }
}
for (auto cell : formal_database)
@@ -561,17 +612,14 @@ struct SimInstance
for (auto &it : mem_database)
{
- Cell *cell = it.first;
mem_state_t &mem = it.second;
- Const initval = mem.data;
-
- while (GetSize(initval) >= 2) {
- if (initval[GetSize(initval)-1] != State::Sx) break;
- if (initval[GetSize(initval)-2] != State::Sx) break;
- initval.bits.pop_back();
- }
-
- cell->setParam(ID::INIT, initval);
+ mem.mem->clear_inits();
+ 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();
}
for (auto it : children)
@@ -626,13 +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()
{
@@ -641,8 +801,16 @@ 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);
+ char mbstr[255];
+ if (std::strftime(mbstr, sizeof(mbstr), "%c", std::localtime(&t))) {
+ vcdfile << stringf("$date ") << mbstr << stringf(" $end\n");
+ }
+
+ if (!timescale.empty())
+ vcdfile << stringf("$timescale %s $end\n", timescale.c_str());
int id = 1;
top->write_vcd_header(vcdfile, id);
@@ -652,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)
@@ -697,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");
@@ -712,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);
@@ -740,16 +949,137 @@ 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);
+ }
+ }
};
struct SimPass : public Pass {
@@ -765,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");
@@ -783,15 +1116,45 @@ struct SimPass : public Pass {
log(" -zinit\n");
log(" zero-initialize all uninitialized regs and memories\n");
log("\n");
+ log(" -timescale <string>\n");
+ 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");
@@ -800,17 +1163,27 @@ 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");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
if (args[argidx] == "-vcd" && argidx+1 < args.size()) {
- worker.vcdfile.open(args[++argidx].c_str());
+ std::string vcd_filename = args[++argidx];
+ rewrite_filename(vcd_filename);
+ 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()) {
@@ -833,6 +1206,10 @@ struct SimPass : public Pass {
worker.resetn.insert(RTLIL::escape_id(args[++argidx]));
continue;
}
+ if (args[argidx] == "-timescale" && argidx+1 < args.size()) {
+ worker.timescale = args[++argidx];
+ continue;
+ }
if (args[argidx] == "-a") {
worker.hide_internal = false;
continue;
@@ -849,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;
@@ -867,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 a54b4913d..98ccfc303 100644
--- a/passes/techmap/Makefile.inc
+++ b/passes/techmap/Makefile.inc
@@ -27,9 +27,10 @@ OBJS += passes/techmap/extract_fa.o
OBJS += passes/techmap/extract_counter.o
OBJS += passes/techmap/extract_reduce.o
OBJS += passes/techmap/alumacc.o
-OBJS += passes/techmap/dff2dffe.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
@@ -41,7 +42,8 @@ OBJS += passes/techmap/insbuf.o
OBJS += passes/techmap/attrmvcp.o
OBJS += passes/techmap/attrmap.o
OBJS += passes/techmap/zinit.o
-OBJS += passes/techmap/dff2dffs.o
+OBJS += passes/techmap/dfflegalize.o
+OBJS += passes/techmap/dffunmap.o
OBJS += passes/techmap/flowmap.o
OBJS += passes/techmap/extractinv.o
endif
diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc
index 0a58fdcc0..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
@@ -38,12 +38,13 @@
#define ABC_FAST_COMMAND_LIB "strash; dretime; map {D}"
#define ABC_FAST_COMMAND_CTR "strash; dretime; map {D}; buffer; upsize {D}; dnsize {D}; stime -p"
#define ABC_FAST_COMMAND_LUT "strash; dretime; if"
-#define ABC_FAST_COMMAND_SOP "strash; dretime; cover -I {I} -P {P}"
+#define ABC_FAST_COMMAND_SOP "strash; dretime; cover {I} {P}"
#define ABC_FAST_COMMAND_DFL "strash; dretime; map"
#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
+#include "kernel/ffinit.h"
#include "kernel/cost.h"
#include "kernel/log.h"
#include <stdlib.h>
@@ -53,6 +54,7 @@
#include <cerrno>
#include <sstream>
#include <climits>
+#include <vector>
#ifndef _WIN32
# include <unistd.h>
@@ -111,7 +113,7 @@ SigMap assign_map;
RTLIL::Module *module;
std::vector<gate_t> signal_list;
std::map<RTLIL::SigBit, int> signal_map;
-std::map<RTLIL::SigBit, RTLIL::State> signal_init;
+FfInitVals initvals;
pool<std::string> enabled_gates;
bool recover_init, cmos_cost;
@@ -133,10 +135,7 @@ int map_signal(RTLIL::SigBit bit, gate_type_t gate_type = G(NONE), int in1 = -1,
gate.in4 = -1;
gate.is_port = false;
gate.bit = bit;
- if (signal_init.count(bit))
- gate.init = signal_init.at(bit);
- else
- gate.init = State::Sx;
+ gate.init = initvals(bit);
signal_list.push_back(gate);
signal_map[bit] = gate.id;
}
@@ -656,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::string liberty_file, 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;
@@ -711,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_file.empty()) {
- 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
@@ -740,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_file.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;
@@ -1021,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_file.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);
@@ -1303,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");
@@ -1325,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");
@@ -1344,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");
@@ -1391,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");
@@ -1447,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");
@@ -1468,16 +1476,13 @@ struct AbcPass : public Pass {
assign_map.clear();
signal_list.clear();
signal_map.clear();
- signal_init.clear();
+ initvals.clear();
pi_map.clear();
po_map.clear();
-#ifdef ABCEXTERNAL
- std::string exe_file = ABCEXTERNAL;
-#else
- std::string exe_file = proc_self_dirname() + proc_program_prefix() + "yosys-abc";
-#endif
- std::string script_file, liberty_file, constr_file, clk_str;
+ std::string exe_file = yosys_abc_executable;
+ std::string script_file, default_liberty_file, constr_file, clk_str;
+ 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;
@@ -1491,18 +1496,11 @@ struct AbcPass : public Pass {
enabled_gates.clear();
cmos_cost = false;
-#ifdef _WIN32
-#ifndef ABCEXTERNAL
- if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\" + proc_program_prefix()+ "yosys-abc.exe"))
- exe_file = proc_self_dirname() + "..\\" + proc_program_prefix() + "yosys-abc";
-#endif
-#endif
-
// get arguments from scratchpad first, then override by command arguments
std::string lut_arg, luts_arg, g_arg;
exe_file = design->scratchpad_get_string("abc.exe", exe_file /* inherit default value if not set */);
script_file = design->scratchpad_get_string("abc.script", script_file);
- liberty_file = design->scratchpad_get_string("abc.liberty", liberty_file);
+ default_liberty_file = design->scratchpad_get_string("abc.liberty", default_liberty_file);
constr_file = design->scratchpad_get_string("abc.constr", constr_file);
if (design->scratchpad.count("abc.D")) {
delay_target = "-D " + design->scratchpad_get_string("abc.D");
@@ -1564,7 +1562,11 @@ struct AbcPass : public Pass {
continue;
}
if (arg == "-liberty" && argidx+1 < args.size()) {
- liberty_file = args[++argidx];
+ 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()) {
@@ -1656,12 +1658,22 @@ struct AbcPass : public Pass {
}
extra_args(args, argidx, design);
+ 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] != '+')
script_file = std::string(pwd) + "/" + script_file;
- rewrite_filename(liberty_file);
- if (!liberty_file.empty() && !is_absolute_path(liberty_file))
- liberty_file = std::string(pwd) + "/" + liberty_file;
+ for (int i = 0; i < GetSize(liberty_files); i++) {
+ rewrite_filename(liberty_files[i]);
+ 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;
@@ -1807,6 +1819,7 @@ struct AbcPass : public Pass {
gate_list.push_back("OAI4");
gate_list.push_back("MUX");
gate_list.push_back("NMUX");
+ goto ok_alias;
}
if (g_arg_from_cmd)
cmd_error(args, g_argidx, stringf("Unsupported gate type: %s", g.c_str()));
@@ -1824,10 +1837,10 @@ struct AbcPass : public Pass {
}
}
- if (!lut_costs.empty() && !liberty_file.empty())
- log_cmd_error("Got -lut and -liberty! These two options are exclusive.\n");
- if (!constr_file.empty() && liberty_file.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");
@@ -1854,27 +1867,10 @@ struct AbcPass : public Pass {
}
assign_map.set(mod);
- signal_init.clear();
-
- for (Wire *wire : mod->wires())
- if (wire->attributes.count(ID::init)) {
- SigSpec initsig = assign_map(wire);
- Const initval = wire->attributes.at(ID::init);
- for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++)
- switch (initval[i]) {
- case State::S0:
- signal_init[initsig[i]] = State::S0;
- break;
- case State::S1:
- signal_init[initsig[i]] = State::S1;
- break;
- default:
- break;
- }
- }
+ initvals.set(&assign_map, mod);
if (!dff_mode || !clk_str.empty()) {
- abc_module(design, mod, script_file, exe_file, liberty_file, 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;
}
@@ -2019,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_file, 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);
}
@@ -2028,7 +2024,7 @@ struct AbcPass : public Pass {
assign_map.clear();
signal_list.clear();
signal_map.clear();
- signal_init.clear();
+ initvals.clear();
pi_map.clear();
po_map.clear();
diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc
index 127f8934e..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)");
@@ -294,8 +301,8 @@ struct Abc9Pass : public ScriptPass
run("design -load $abc9_map");
run("proc");
run("wbflip");
- run("techmap");
- run("opt");
+ run("techmap -wb -map %$abc9 -map +/techmap.v A:abc9_flop");
+ run("opt -nodffe -nosdff");
if (dff_mode || help_mode) {
if (!help_mode)
active_design->scratchpad_unset("abc9_ops.prep_dff_submod.did_something");
@@ -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 -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 7355840aa..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
@@ -379,11 +379,7 @@ struct Abc9ExePass : public Pass {
{
log_header(design, "Executing ABC9_EXE pass (technology mapping using ABC9).\n");
-#ifdef ABCEXTERNAL
- std::string exe_file = ABCEXTERNAL;
-#else
- std::string exe_file = proc_self_dirname() + proc_program_prefix()+ "yosys-abc";
-#endif
+ std::string exe_file = yosys_abc_executable;
std::string script_file, clk_str, box_file, lut_file;
std::string delay_target, lutin_shared = "-S 1", wire_delay;
std::string tempdir_name;
@@ -396,13 +392,6 @@ struct Abc9ExePass : public Pass {
show_tempdir = true;
#endif
-#ifdef _WIN32
-#ifndef ABCEXTERNAL
- if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\" + proc_program_prefix() + "yosys-abc.exe"))
- exe_file = proc_self_dirname() + "..\\" + proc_program_prefix() + "yosys-abc";
-#endif
-#endif
-
std::string lut_arg, luts_arg;
exe_file = design->scratchpad_get_string("abc9.exe", exe_file /* inherit default value if not set */);
script_file = design->scratchpad_get_string("abc9.script", script_file);
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 451325fee..a7b96a9c6 100644
--- a/passes/techmap/clkbufmap.cc
+++ b/passes/techmap/clkbufmap.cc
@@ -1,8 +1,8 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- * Copyright (C) 2019 Marcin Kościelnicki <mwk@0x04.net>
+ * 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
* purpose with or without fee is hereby granted, provided that the above
@@ -34,33 +34,34 @@ void split_portname_pair(std::string &port1, std::string &port2)
}
struct ClkbufmapPass : public Pass {
- ClkbufmapPass() : Pass("clkbufmap", "insert global buffers on clock networks") { }
+ ClkbufmapPass() : Pass("clkbufmap", "insert clock buffers on clock networks") { }
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" clkbufmap [options] [selection]\n");
log("\n");
- log("Inserts global buffers between nets connected to clock inputs and their drivers.\n");
+ log("Inserts clock buffers between nets connected to clock inputs and their drivers.\n");
log("\n");
log("In the absence of any selection, all wires without the 'clkbuf_inhibit'\n");
- log("attribute will be considered for global buffer insertion.\n");
+ log("attribute will be considered for clock buffer insertion.\n");
log("Alternatively, to consider all wires without the 'buffer_type' attribute set to\n");
log("'none' or 'bufr' one would specify:\n");
log(" 'w:* a:buffer_type=none a:buffer_type=bufr %%u %%d'\n");
log("as the selection.\n");
log("\n");
log(" -buf <celltype> <portname_out>:<portname_in>\n");
- log(" Specifies the cell type to use for the global buffers\n");
+ log(" Specifies the cell type to use for the clock buffers\n");
log(" and its port names. The first port will be connected to\n");
log(" the clock network sinks, and the second will be connected\n");
- log(" to the actual clock source. This option is required.\n");
+ log(" to the actual clock source.\n");
log("\n");
log(" -inpad <celltype> <portname_out>:<portname_in>\n");
log(" If specified, a PAD cell of the given type is inserted on\n");
log(" clock nets that are also top module's inputs (in addition\n");
- log(" to the global buffer).\n");
+ log(" to the clock buffer, if any).\n");
log("\n");
+ log("At least one of -buf or -inpad should be specified.\n");
}
void module_queue(Design *design, Module *module, std::vector<Module *> &modules_sorted, pool<Module *> &modules_processed) {
@@ -78,7 +79,7 @@ struct ClkbufmapPass : public Pass {
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
- log_header(design, "Executing CLKBUFMAP pass (inserting global clock buffers).\n");
+ log_header(design, "Executing CLKBUFMAP pass (inserting clock buffers).\n");
std::string buf_celltype, buf_portname, buf_portname2;
std::string inpad_celltype, inpad_portname, inpad_portname2;
@@ -109,8 +110,8 @@ struct ClkbufmapPass : public Pass {
extra_args(args, argidx, design);
}
- if (buf_celltype.empty())
- log_error("The -buf option is required.\n");
+ if (buf_celltype.empty() && inpad_celltype.empty())
+ log_error("Either the -buf option or -inpad option is required.\n");
// Cell type, port name, bit index.
pool<pair<IdString, pair<IdString, int>>> sink_ports;
@@ -118,6 +119,16 @@ struct ClkbufmapPass : public Pass {
dict<pair<IdString, pair<IdString, int>>, pair<IdString, int>> inv_ports_out;
dict<pair<IdString, pair<IdString, int>>, pair<IdString, int>> inv_ports_in;
+ // If true, use both ther -buf and -inpad cell for input ports that are clocks.
+ bool buffer_inputs = true;
+
+ Module *inpad_mod = design->module(RTLIL::escape_id(inpad_celltype));
+ if (inpad_mod) {
+ Wire *buf_wire = inpad_mod->wire(RTLIL::escape_id(buf_portname));
+ if (buf_wire && buf_wire->get_bool_attribute(ID::clkbuf_driver))
+ buffer_inputs = false;
+ }
+
// Process submodules before module using them.
std::vector<Module *> modules_sorted;
pool<Module *> modules_processed;
@@ -242,19 +253,30 @@ struct ClkbufmapPass : public Pass {
// Clock network not yet buffered, driven by one of
// our cells or a top-level input -- buffer it.
- log("Inserting %s on %s.%s[%d].\n", buf_celltype.c_str(), log_id(module), log_id(wire), i);
- RTLIL::Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(buf_celltype));
- Wire *iwire = module->addWire(NEW_ID);
- cell->setPort(RTLIL::escape_id(buf_portname), mapped_wire_bit);
- cell->setPort(RTLIL::escape_id(buf_portname2), iwire);
- if (wire->port_input && !inpad_celltype.empty() && module->get_bool_attribute(ID::top)) {
+ Wire *iwire = nullptr;
+ RTLIL::Cell *cell = nullptr;
+ bool is_input = wire->port_input && !inpad_celltype.empty() && module->get_bool_attribute(ID::top);
+ if (!buf_celltype.empty() && (!is_input || buffer_inputs)) {
+ log("Inserting %s on %s.%s[%d].\n", buf_celltype.c_str(), log_id(module), log_id(wire), i);
+ cell = module->addCell(NEW_ID, RTLIL::escape_id(buf_celltype));
+ iwire = module->addWire(NEW_ID);
+ cell->setPort(RTLIL::escape_id(buf_portname), mapped_wire_bit);
+ cell->setPort(RTLIL::escape_id(buf_portname2), iwire);
+ }
+ if (is_input) {
log("Inserting %s on %s.%s[%d].\n", inpad_celltype.c_str(), log_id(module), log_id(wire), i);
RTLIL::Cell *cell2 = module->addCell(NEW_ID, RTLIL::escape_id(inpad_celltype));
- cell2->setPort(RTLIL::escape_id(inpad_portname), iwire);
+ if (iwire) {
+ cell2->setPort(RTLIL::escape_id(inpad_portname), iwire);
+ } else {
+ cell2->setPort(RTLIL::escape_id(inpad_portname), mapped_wire_bit);
+ cell = cell2;
+ }
iwire = module->addWire(NEW_ID);
cell2->setPort(RTLIL::escape_id(inpad_portname2), iwire);
}
- buffered_bits[mapped_wire_bit] = make_pair(cell, iwire);
+ if (iwire)
+ buffered_bits[mapped_wire_bit] = make_pair(cell, iwire);
if (wire->port_input) {
input_bits.insert(i);
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/dff2dffe.cc b/passes/techmap/dff2dffe.cc
deleted file mode 100644
index 62ee3fea6..000000000
--- a/passes/techmap/dff2dffe.cc
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * yosys -- Yosys Open SYnthesis Suite
- *
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#include "kernel/yosys.h"
-#include "kernel/sigtools.h"
-#include "kernel/celltypes.h"
-#include "passes/techmap/simplemap.h"
-
-USING_YOSYS_NAMESPACE
-PRIVATE_NAMESPACE_BEGIN
-
-struct Dff2dffeWorker
-{
- const dict<IdString, IdString> &direct_dict;
-
- RTLIL::Module *module;
- SigMap sigmap;
- CellTypes ct;
-
- typedef std::pair<RTLIL::Cell*, int> cell_int_t;
- std::map<RTLIL::SigBit, cell_int_t> bit2mux;
- std::vector<RTLIL::Cell*> dff_cells;
- std::map<RTLIL::SigBit, int> bitusers;
-
- typedef std::map<RTLIL::SigBit, bool> pattern_t;
- typedef std::set<pattern_t> patterns_t;
-
-
- Dff2dffeWorker(RTLIL::Module *module, const dict<IdString, IdString> &direct_dict) :
- direct_dict(direct_dict), module(module), sigmap(module), ct(module->design)
- {
- for (auto wire : module->wires()) {
- if (wire->port_output)
- for (auto bit : sigmap(wire))
- bitusers[bit]++;
- }
-
- for (auto cell : module->cells()) {
- if (cell->type.in(ID($mux), ID($pmux), ID($_MUX_))) {
- RTLIL::SigSpec sig_y = sigmap(cell->getPort(ID::Y));
- for (int i = 0; i < GetSize(sig_y); i++)
- bit2mux[sig_y[i]] = cell_int_t(cell, i);
- }
- if (direct_dict.empty()) {
- if (cell->type.in(ID($dff), ID($_DFF_N_), ID($_DFF_P_)))
- dff_cells.push_back(cell);
- } else {
- if (direct_dict.count(cell->type))
- dff_cells.push_back(cell);
- }
- for (auto conn : cell->connections()) {
- if (ct.cell_output(cell->type, conn.first))
- continue;
- for (auto bit : sigmap(conn.second))
- bitusers[bit]++;
- }
- }
- }
-
- patterns_t find_muxtree_feedback_patterns(RTLIL::SigBit d, RTLIL::SigBit q, pattern_t path)
- {
- patterns_t ret;
-
- if (d == q) {
- ret.insert(path);
- return ret;
- }
-
- if (bit2mux.count(d) == 0 || bitusers[d] > 1)
- return ret;
-
- cell_int_t mux_cell_int = bit2mux.at(d);
- RTLIL::SigSpec sig_a = sigmap(mux_cell_int.first->getPort(ID::A));
- RTLIL::SigSpec sig_b = sigmap(mux_cell_int.first->getPort(ID::B));
- RTLIL::SigSpec sig_s = sigmap(mux_cell_int.first->getPort(ID::S));
- int width = GetSize(sig_a), index = mux_cell_int.second;
-
- for (int i = 0; i < GetSize(sig_s); i++)
- if (path.count(sig_s[i]) && path.at(sig_s[i]))
- {
- ret = find_muxtree_feedback_patterns(sig_b[i*width + index], q, path);
-
- if (sig_b[i*width + index] == q) {
- RTLIL::SigSpec s = mux_cell_int.first->getPort(ID::B);
- s[i*width + index] = RTLIL::Sx;
- mux_cell_int.first->setPort(ID::B, s);
- }
-
- return ret;
- }
-
- pattern_t path_else = path;
-
- for (int i = 0; i < GetSize(sig_s); i++)
- {
- if (path.count(sig_s[i]))
- continue;
-
- pattern_t path_this = path;
- path_else[sig_s[i]] = false;
- path_this[sig_s[i]] = true;
-
- for (auto &pat : find_muxtree_feedback_patterns(sig_b[i*width + index], q, path_this))
- ret.insert(pat);
-
- if (sig_b[i*width + index] == q) {
- RTLIL::SigSpec s = mux_cell_int.first->getPort(ID::B);
- s[i*width + index] = RTLIL::Sx;
- mux_cell_int.first->setPort(ID::B, s);
- }
- }
-
- for (auto &pat : find_muxtree_feedback_patterns(sig_a[index], q, path_else))
- ret.insert(pat);
-
- if (sig_a[index] == q) {
- RTLIL::SigSpec s = mux_cell_int.first->getPort(ID::A);
- s[index] = RTLIL::Sx;
- mux_cell_int.first->setPort(ID::A, s);
- }
-
- return ret;
- }
-
- void simplify_patterns(patterns_t&)
- {
- // TBD
- }
-
- RTLIL::SigSpec make_patterns_logic(patterns_t patterns, bool make_gates)
- {
- RTLIL::SigSpec or_input;
-
- for (auto pat : patterns)
- {
- RTLIL::SigSpec s1, s2;
- for (auto it : pat) {
- s1.append(it.first);
- s2.append(it.second);
- }
-
- RTLIL::SigSpec y = module->addWire(NEW_ID);
- RTLIL::Cell *c = module->addNe(NEW_ID, s1, s2, y);
-
- if (make_gates) {
- simplemap(module, c);
- module->remove(c);
- }
-
- or_input.append(y);
- }
-
- if (GetSize(or_input) == 0)
- return State::S1;
-
- if (GetSize(or_input) == 1)
- return or_input;
-
- RTLIL::SigSpec y = module->addWire(NEW_ID);
- RTLIL::Cell *c = module->addReduceAnd(NEW_ID, or_input, y);
-
- if (make_gates) {
- simplemap(module, c);
- module->remove(c);
- }
-
- return y;
- }
-
- void handle_dff_cell(RTLIL::Cell *dff_cell)
- {
- RTLIL::SigSpec sig_d = sigmap(dff_cell->getPort(ID::D));
- RTLIL::SigSpec sig_q = sigmap(dff_cell->getPort(ID::Q));
-
- std::map<patterns_t, std::set<int>> grouped_patterns;
- std::set<int> remaining_indices;
-
- for (int i = 0 ; i < GetSize(sig_d); i++) {
- patterns_t patterns = find_muxtree_feedback_patterns(sig_d[i], sig_q[i], pattern_t());
- if (!patterns.empty()) {
- simplify_patterns(patterns);
- grouped_patterns[patterns].insert(i);
- } else
- remaining_indices.insert(i);
- }
-
- for (auto &it : grouped_patterns) {
- RTLIL::SigSpec new_sig_d, new_sig_q;
- for (int i : it.second) {
- new_sig_d.append(sig_d[i]);
- new_sig_q.append(sig_q[i]);
- }
- if (!direct_dict.empty()) {
- log(" converting %s cell %s to %s for %s -> %s.\n", log_id(dff_cell->type), log_id(dff_cell), log_id(direct_dict.at(dff_cell->type)), log_signal(new_sig_d), log_signal(new_sig_q));
- dff_cell->setPort(ID::E, make_patterns_logic(it.first, true));
- dff_cell->type = direct_dict.at(dff_cell->type);
- } else
- if (dff_cell->type == ID($dff)) {
- RTLIL::Cell *new_cell = module->addDffe(NEW_ID, dff_cell->getPort(ID::CLK), make_patterns_logic(it.first, false),
- new_sig_d, new_sig_q, dff_cell->getParam(ID::CLK_POLARITY).as_bool(), true);
- log(" created $dffe cell %s for %s -> %s.\n", log_id(new_cell), log_signal(new_sig_d), log_signal(new_sig_q));
- } else {
- RTLIL::Cell *new_cell = module->addDffeGate(NEW_ID, dff_cell->getPort(ID::C), make_patterns_logic(it.first, true),
- new_sig_d, new_sig_q, dff_cell->type == ID($_DFF_P_), true);
- log(" created %s cell %s for %s -> %s.\n", log_id(new_cell->type), log_id(new_cell), log_signal(new_sig_d), log_signal(new_sig_q));
- }
- }
-
- if (!direct_dict.empty())
- return;
-
- if (remaining_indices.empty()) {
- log(" removing now obsolete cell %s.\n", log_id(dff_cell));
- module->remove(dff_cell);
- } else if (GetSize(remaining_indices) != GetSize(sig_d)) {
- log(" removing %d now obsolete bits from cell %s.\n", GetSize(sig_d) - GetSize(remaining_indices), log_id(dff_cell));
- RTLIL::SigSpec new_sig_d, new_sig_q;
- for (int i : remaining_indices) {
- new_sig_d.append(sig_d[i]);
- new_sig_q.append(sig_q[i]);
- }
- dff_cell->setPort(ID::D, new_sig_d);
- dff_cell->setPort(ID::Q, new_sig_q);
- dff_cell->setParam(ID::WIDTH, GetSize(remaining_indices));
- }
- }
-
- void run()
- {
- log("Transforming FF to FF+Enable cells in module %s:\n", log_id(module));
- for (auto dff_cell : dff_cells) {
- // log("Handling candidate %s:\n", log_id(dff_cell));
- handle_dff_cell(dff_cell);
- }
- }
-};
-
-struct Dff2dffePass : public Pass {
- Dff2dffePass() : Pass("dff2dffe", "transform $dff cells to $dffe cells") { }
- void help() override
- {
- // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
- log("\n");
- log(" dff2dffe [options] [selection]\n");
- log("\n");
- log("This pass transforms $dff cells driven by a tree of multiplexers with one or\n");
- log("more feedback paths to $dffe cells. It also works on gate-level cells such as\n");
- log("$_DFF_P_, $_DFF_N_ and $_MUX_.\n");
- log("\n");
- log(" -unmap\n");
- log(" operate in the opposite direction: replace $dffe cells with combinations\n");
- log(" of $dff and $mux cells. the options below are ignored in unmap mode.\n");
- log("\n");
- log(" -unmap-mince N\n");
- log(" Same as -unmap but only unmap $dffe where the clock enable port\n");
- log(" signal is used by less $dffe than the specified number\n");
- log("\n");
- log(" -direct <internal_gate_type> <external_gate_type>\n");
- log(" map directly to external gate type. <internal_gate_type> can\n");
- log(" be any internal gate-level FF cell (except $_DFFE_??_). the\n");
- log(" <external_gate_type> is the cell type name for a cell with an\n");
- log(" identical interface to the <internal_gate_type>, except it\n");
- log(" also has an high-active enable port 'E'.\n");
- log(" Usually <external_gate_type> is an intermediate cell type\n");
- log(" that is then translated to the final type using 'techmap'.\n");
- log("\n");
- log(" -direct-match <pattern>\n");
- log(" like -direct for all DFF cell types matching the expression.\n");
- log(" this will use $_DFFE_* as <external_gate_type> matching the\n");
- log(" internal gate type $_DFF_*_, and $_SDFFE_* for those matching\n");
- log(" $_SDFF_*_, except for $_DFF_[NP]_, which is converted to \n");
- log(" $_DFFE_[NP]_.\n");
- log("\n");
- }
- void execute(std::vector<std::string> args, RTLIL::Design *design) override
- {
- log_header(design, "Executing DFF2DFFE pass (transform $dff to $dffe where applicable).\n");
-
- bool unmap_mode = false;
- int min_ce_use = -1;
- dict<IdString, IdString> direct_dict;
-
- size_t argidx;
- for (argidx = 1; argidx < args.size(); argidx++) {
- if (args[argidx] == "-unmap") {
- unmap_mode = true;
- continue;
- }
- if (args[argidx] == "-unmap-mince" && argidx + 1 < args.size()) {
- unmap_mode = true;
- min_ce_use = atoi(args[++argidx].c_str());
- continue;
- }
- if (args[argidx] == "-direct" && argidx + 2 < args.size()) {
- string direct_from = RTLIL::escape_id(args[++argidx]);
- string direct_to = RTLIL::escape_id(args[++argidx]);
- direct_dict[direct_from] = direct_to;
- continue;
- }
- if (args[argidx] == "-direct-match" && argidx + 1 < args.size()) {
- bool found_match = false;
- const char *pattern = args[++argidx].c_str();
- if (patmatch(pattern, "$_DFF_P_" )) found_match = true, direct_dict[ID($_DFF_P_) ] = ID($_DFFE_PP_);
- if (patmatch(pattern, "$_DFF_N_" )) found_match = true, direct_dict[ID($_DFF_N_) ] = ID($_DFFE_NP_);
- if (patmatch(pattern, "$_DFF_NN0_")) found_match = true, direct_dict[ID($_DFF_NN0_)] = ID($_DFFE_NN0P_);
- if (patmatch(pattern, "$_DFF_NN1_")) found_match = true, direct_dict[ID($_DFF_NN1_)] = ID($_DFFE_NN1P_);
- if (patmatch(pattern, "$_DFF_NP0_")) found_match = true, direct_dict[ID($_DFF_NP0_)] = ID($_DFFE_NP0P_);
- if (patmatch(pattern, "$_DFF_NP1_")) found_match = true, direct_dict[ID($_DFF_NP1_)] = ID($_DFFE_NP1P_);
- if (patmatch(pattern, "$_DFF_PN0_")) found_match = true, direct_dict[ID($_DFF_PN0_)] = ID($_DFFE_PN0P_);
- if (patmatch(pattern, "$_DFF_PN1_")) found_match = true, direct_dict[ID($_DFF_PN1_)] = ID($_DFFE_PN1P_);
- if (patmatch(pattern, "$_DFF_PP0_")) found_match = true, direct_dict[ID($_DFF_PP0_)] = ID($_DFFE_PP0P_);
- if (patmatch(pattern, "$_DFF_PP1_")) found_match = true, direct_dict[ID($_DFF_PP1_)] = ID($_DFFE_PP1P_);
-
- if (patmatch(pattern, "$_SDFF_NN0_")) found_match = true, direct_dict[ID($_SDFF_NN0_)] = ID($_SDFFE_NN0P_);
- if (patmatch(pattern, "$_SDFF_NN1_")) found_match = true, direct_dict[ID($_SDFF_NN1_)] = ID($_SDFFE_NN1P_);
- if (patmatch(pattern, "$_SDFF_NP0_")) found_match = true, direct_dict[ID($_SDFF_NP0_)] = ID($_SDFFE_NP0P_);
- if (patmatch(pattern, "$_SDFF_NP1_")) found_match = true, direct_dict[ID($_SDFF_NP1_)] = ID($_SDFFE_NP1P_);
- if (patmatch(pattern, "$_SDFF_PN0_")) found_match = true, direct_dict[ID($_SDFF_PN0_)] = ID($_SDFFE_PN0P_);
- if (patmatch(pattern, "$_SDFF_PN1_")) found_match = true, direct_dict[ID($_SDFF_PN1_)] = ID($_SDFFE_PN1P_);
- if (patmatch(pattern, "$_SDFF_PP0_")) found_match = true, direct_dict[ID($_SDFF_PP0_)] = ID($_SDFFE_PP0P_);
- if (patmatch(pattern, "$_SDFF_PP1_")) found_match = true, direct_dict[ID($_SDFF_PP1_)] = ID($_SDFFE_PP1P_);
- if (!found_match)
- log_cmd_error("No cell types matched pattern '%s'.\n", pattern);
- continue;
- }
- break;
- }
- extra_args(args, argidx, design);
-
- if (!direct_dict.empty()) {
- log("Selected cell types for direct conversion:\n");
- for (auto &it : direct_dict)
- log(" %s -> %s\n", log_id(it.first), log_id(it.second));
- }
-
- for (auto mod : design->selected_modules())
- if (!mod->has_processes_warn())
- {
- if (unmap_mode) {
- SigMap sigmap(mod);
- for (auto cell : mod->selected_cells()) {
- if (cell->type == ID($dffe)) {
- if (min_ce_use >= 0) {
- int ce_use = 0;
- for (auto cell_other : mod->selected_cells()) {
- if (cell_other->type != cell->type)
- continue;
- if (sigmap(cell->getPort(ID::EN)) == sigmap(cell_other->getPort(ID::EN)))
- ce_use++;
- }
- if (ce_use >= min_ce_use)
- continue;
- }
-
- RTLIL::SigSpec tmp = mod->addWire(NEW_ID, GetSize(cell->getPort(ID::D)));
- mod->addDff(NEW_ID, cell->getPort(ID::CLK), tmp, cell->getPort(ID::Q), cell->getParam(ID::CLK_POLARITY).as_bool());
- if (cell->getParam(ID::EN_POLARITY).as_bool())
- mod->addMux(NEW_ID, cell->getPort(ID::Q), cell->getPort(ID::D), cell->getPort(ID::EN), tmp);
- else
- mod->addMux(NEW_ID, cell->getPort(ID::D), cell->getPort(ID::Q), cell->getPort(ID::EN), tmp);
- mod->remove(cell);
- continue;
- }
- if (cell->type.begins_with("$_DFFE_")) {
- if (min_ce_use >= 0) {
- int ce_use = 0;
- for (auto cell_other : mod->selected_cells()) {
- if (cell_other->type != cell->type)
- continue;
- if (sigmap(cell->getPort(ID::E)) == sigmap(cell_other->getPort(ID::E)))
- ce_use++;
- }
- if (ce_use >= min_ce_use)
- continue;
- }
-
- bool clk_pol = cell->type.compare(7, 1, "P") == 0;
- bool en_pol = cell->type.compare(8, 1, "P") == 0;
- RTLIL::SigSpec tmp = mod->addWire(NEW_ID);
- mod->addDff(NEW_ID, cell->getPort(ID::C), tmp, cell->getPort(ID::Q), clk_pol);
- if (en_pol)
- mod->addMux(NEW_ID, cell->getPort(ID::Q), cell->getPort(ID::D), cell->getPort(ID::E), tmp);
- else
- mod->addMux(NEW_ID, cell->getPort(ID::D), cell->getPort(ID::Q), cell->getPort(ID::E), tmp);
- mod->remove(cell);
- continue;
- }
- }
- continue;
- }
-
- Dff2dffeWorker worker(mod, direct_dict);
- worker.run();
- }
- }
-} Dff2dffePass;
-
-PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/dff2dffs.cc b/passes/techmap/dff2dffs.cc
deleted file mode 100644
index 6c2cca4bc..000000000
--- a/passes/techmap/dff2dffs.cc
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * yosys -- Yosys Open SYnthesis Suite
- *
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- * Copyright (C) 2018 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.
- *
- */
-
-#include "kernel/yosys.h"
-#include "kernel/sigtools.h"
-
-USING_YOSYS_NAMESPACE
-PRIVATE_NAMESPACE_BEGIN
-
-struct Dff2dffsPass : public Pass {
- Dff2dffsPass() : Pass("dff2dffs", "process sync set/reset with SR over CE priority") { }
- void help() override
- {
- log("\n");
- log(" dff2dffs [options] [selection]\n");
- log("\n");
- log("Merge synchronous set/reset $_MUX_ cells to create $_SDFF_[NP][NP][01]_, to be run before\n");
- log("dff2dffe for SR over CE priority.\n");
- log("\n");
- log(" -match-init\n");
- log(" Disallow merging synchronous set/reset that has polarity opposite of the\n");
- log(" output wire's init attribute (if any).\n");
- log("\n");
- }
- void execute(std::vector<std::string> args, RTLIL::Design *design) override
- {
- log_header(design, "Executing dff2dffs pass (merge synchronous set/reset into FF cells).\n");
-
- bool match_init = false;
- size_t argidx;
- for (argidx = 1; argidx < args.size(); argidx++)
- {
- // if (args[argidx] == "-singleton") {
- // singleton_mode = true;
- // continue;
- // }
- if (args[argidx] == "-match-init") {
- match_init = true;
- continue;
- }
- break;
- }
- extra_args(args, argidx, design);
-
- pool<IdString> dff_types;
- dff_types.insert(ID($_DFF_N_));
- dff_types.insert(ID($_DFF_P_));
-
- for (auto module : design->selected_modules())
- {
- log("Merging set/reset $_MUX_ cells into DFFs in %s.\n", log_id(module));
-
- SigMap sigmap(module);
- dict<SigBit, Cell*> sr_muxes;
- vector<Cell*> ff_cells;
-
- for (auto cell : module->selected_cells())
- {
- if (dff_types.count(cell->type)) {
- ff_cells.push_back(cell);
- continue;
- }
-
- if (cell->type != ID($_MUX_))
- continue;
-
- SigBit bit_a = sigmap(cell->getPort(ID::A));
- SigBit bit_b = sigmap(cell->getPort(ID::B));
-
- if (bit_a.wire == nullptr || bit_b.wire == nullptr)
- sr_muxes[sigmap(cell->getPort(ID::Y))] = cell;
- }
-
- for (auto cell : ff_cells)
- {
- SigSpec sig_d = cell->getPort(ID::D);
-
- if (GetSize(sig_d) < 1)
- continue;
-
- SigBit bit_d = sigmap(sig_d[0]);
-
- if (sr_muxes.count(bit_d) == 0)
- continue;
-
- Cell *mux_cell = sr_muxes.at(bit_d);
- SigBit bit_a = sigmap(mux_cell->getPort(ID::A));
- SigBit bit_b = sigmap(mux_cell->getPort(ID::B));
- SigBit bit_s = sigmap(mux_cell->getPort(ID::S));
-
- SigBit sr_val, sr_sig;
- bool invert_sr;
- sr_sig = bit_s;
- if (bit_a.wire == nullptr) {
- bit_d = bit_b;
- sr_val = bit_a;
- invert_sr = true;
- } else {
- log_assert(bit_b.wire == nullptr);
- bit_d = bit_a;
- sr_val = bit_b;
- invert_sr = false;
- }
-
- if (match_init) {
- SigBit bit_q = cell->getPort(ID::Q);
- if (bit_q.wire) {
- auto it = bit_q.wire->attributes.find(ID::init);
- if (it != bit_q.wire->attributes.end()) {
- auto init_val = it->second[bit_q.offset];
- if (init_val == State::S1 && sr_val != State::S1)
- continue;
- if (init_val == State::S0 && sr_val != State::S0)
- continue;
- }
- }
- }
-
- log(" Merging %s (A=%s, B=%s, S=%s) into %s (%s).\n", log_id(mux_cell),
- log_signal(bit_a), log_signal(bit_b), log_signal(bit_s), log_id(cell), log_id(cell->type));
-
- if (sr_val == State::S1) {
- if (cell->type == ID($_DFF_N_)) {
- if (invert_sr) cell->type = ID($_SDFF_NN1_);
- else cell->type = ID($_SDFF_NP1_);
- } else {
- log_assert(cell->type == ID($_DFF_P_));
- if (invert_sr) cell->type = ID($_SDFF_PN1_);
- else cell->type = ID($_SDFF_PP1_);
- }
- } else {
- if (cell->type == ID($_DFF_N_)) {
- if (invert_sr) cell->type = ID($_SDFF_NN0_);
- else cell->type = ID($_SDFF_NP0_);
- } else {
- log_assert(cell->type == ID($_DFF_P_));
- if (invert_sr) cell->type = ID($_SDFF_PN0_);
- else cell->type = ID($_SDFF_PP0_);
- }
- }
- cell->setPort(ID::R, sr_sig);
- cell->setPort(ID::D, bit_d);
- }
- }
- }
-} Dff2dffsPass;
-
-PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/dffinit.cc b/passes/techmap/dffinit.cc
index c60a901c1..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
@@ -19,6 +19,7 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
+#include "kernel/ffinit.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -94,29 +95,10 @@ struct DffinitPass : public Pass {
for (auto module : design->selected_modules())
{
SigMap sigmap(module);
- dict<SigBit, State> init_bits;
- pool<SigBit> cleanup_bits;
- pool<SigBit> used_bits;
-
- for (auto wire : module->selected_wires()) {
- if (wire->attributes.count(ID::init)) {
- Const value = wire->attributes.at(ID::init);
- for (int i = 0; i < min(GetSize(value), GetSize(wire)); i++)
- if (value[i] != State::Sx)
- init_bits[sigmap(SigBit(wire, i))] = value[i];
- }
- if (wire->port_output)
- for (auto bit : sigmap(wire))
- used_bits.insert(bit);
- }
+ FfInitVals initvals(&sigmap, module);
for (auto cell : module->selected_cells())
{
- for (auto it : cell->connections())
- if (!cell->known() || cell->input(it.first))
- for (auto bit : sigmap(it.second))
- used_bits.insert(bit);
-
if (ff_types.count(cell->type) == 0)
continue;
@@ -131,17 +113,18 @@ struct DffinitPass : public Pass {
if (cell->hasParam(it.second))
value = cell->getParam(it.second);
+ Const initval = initvals(sig);
+ initvals.remove_init(sig);
for (int i = 0; i < GetSize(sig); i++) {
- if (init_bits.count(sig[i]) == 0)
+ if (initval[i] == State::Sx)
continue;
while (GetSize(value.bits) <= i)
value.bits.push_back(State::S0);
- if (noreinit && value.bits[i] != State::Sx && value.bits[i] != init_bits.at(sig[i]))
+ if (noreinit && value.bits[i] != State::Sx && value.bits[i] != initval[i])
log_error("Trying to assign a different init value for %s.%s.%s which technically "
"have a conflicted init value.\n",
log_id(module), log_id(cell), log_id(it.second));
- value.bits[i] = init_bits.at(sig[i]);
- cleanup_bits.insert(sig[i]);
+ value.bits[i] = initval[i];
}
if (highlow_mode && GetSize(value) != 0) {
@@ -161,23 +144,6 @@ struct DffinitPass : public Pass {
}
}
}
-
- for (auto wire : module->selected_wires())
- if (wire->attributes.count(ID::init)) {
- Const &value = wire->attributes.at(ID::init);
- bool do_cleanup = true;
- for (int i = 0; i < min(GetSize(value), GetSize(wire)); i++) {
- SigBit bit = sigmap(SigBit(wire, i));
- if (cleanup_bits.count(bit) || !used_bits.count(bit))
- value[i] = State::Sx;
- else if (value[i] != State::Sx)
- do_cleanup = false;
- }
- if (do_cleanup) {
- log("Removing init attribute from wire %s.%s.\n", log_id(module), log_id(wire));
- wire->attributes.erase(ID::init);
- }
- }
}
}
} DffinitPass;
diff --git a/passes/techmap/dfflegalize.cc b/passes/techmap/dfflegalize.cc
new file mode 100644
index 000000000..1d99caa3a
--- /dev/null
+++ b/passes/techmap/dfflegalize.cc
@@ -0,0 +1,1235 @@
+/*
+ * 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/ffinit.h"
+#include "kernel/ff.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+enum FfType {
+ FF_DFF,
+ FF_DFFE,
+ FF_ADFF,
+ FF_ADFFE,
+ FF_ALDFF,
+ FF_ALDFFE,
+ FF_DFFSR,
+ FF_DFFSRE,
+ FF_SDFF,
+ FF_SDFFE,
+ FF_SDFFCE,
+ FF_RLATCH,
+ FF_SR,
+ FF_DLATCH,
+ FF_ADLATCH,
+ FF_DLATCHSR,
+ NUM_FFTYPES,
+};
+
+enum FfNeg {
+ 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 {
+ DffLegalizePass() : Pass("dfflegalize", "convert FFs to types supported by the target") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" dfflegalize [options] [selection]\n");
+ log("\n");
+ log("Converts FFs to types supported by the target.\n");
+ log("\n");
+ log(" -cell <cell_type_pattern> <init_values>\n");
+ log(" specifies a supported group of FF cells. <cell_type_pattern>\n");
+ log(" is a yosys internal fine cell name, where ? characters can be\n");
+ log(" as a wildcard matching any character. <init_values> specifies\n");
+ log(" which initialization values these FF cells can support, and can\n");
+ log(" be one of:\n");
+ log("\n");
+ log(" - x (no init value supported)\n");
+ log(" - 0\n");
+ log(" - 1\n");
+ log(" - r (init value has to match reset value, only for some FF types)\n");
+ log(" - 01 (both 0 and 1 supported).\n");
+ log("\n");
+ log(" -mince <num>\n");
+ log(" specifies a minimum number of FFs that should be using any given\n");
+ log(" clock enable signal. If a clock enable signal doesn't meet this\n");
+ log(" threshold, it is unmapped into soft logic.\n");
+ log("\n");
+ log(" -minsrst <num>\n");
+ log(" specifies a minimum number of FFs that should be using any given\n");
+ log(" sync set/reset signal. If a sync set/reset signal doesn't meet this\n");
+ log(" threshold, it is unmapped into soft logic.\n");
+ log("\n");
+ log("The following cells are supported by this pass (ie. will be ingested,\n");
+ log("and can be specified as allowed targets):\n");
+ log("\n");
+ log("- $_DFF_[NP]_\n");
+ 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");
+ log("- $_SDFFE_[NP][NP][01][NP]_\n");
+ log("- $_SDFFCE_[NP][NP][01][NP]_\n");
+ log("- $_SR_[NP][NP]_\n");
+ log("- $_DLATCH_[NP]_\n");
+ log("- $_DLATCH_[NP][NP][01]_\n");
+ log("- $_DLATCHSR_[NP][NP][NP]_\n");
+ log("\n");
+ log("The following transformations are performed by this pass:");
+ log("\n");
+ log("- upconversion from a less capable cell to a more capable cell, if the less");
+ log(" capable cell is not supported (eg. dff -> dffe, or adff -> dffsr)");
+ log("\n");
+ log("- unmapping FFs with clock enable (due to unsupported cell type or -mince)");
+ log("\n");
+ log("- unmapping FFs with sync reset (due to unsupported cell type or -minsrst)");
+ log("\n");
+ log("- adding inverters on the control pins (due to unsupported polarity)");
+ log("\n");
+ log("- adding inverters on the D and Q pins and inverting the init/reset values\n");
+ log(" (due to unsupported init or reset value)");
+ log("\n");
+ log("- converting sr into adlatch (by tying D to 1 and using E as set input)");
+ log("\n");
+ log("- emulating unsupported dffsr cell by adff + adff + sr + mux");
+ log("\n");
+ log("- emulating unsupported dlatchsr cell by adlatch + adlatch + sr + mux");
+ log("\n");
+ log("- emulating adff when the (reset, init) value combination is unsupported by\n");
+ log(" dff + adff + dlatch + mux");
+ log("\n");
+ log("- emulating adlatch when the (reset, init) value combination is unsupported by\n");
+ log("- dlatch + adlatch + dlatch + mux");
+ log("\n");
+ log("If the pass is unable to realize a given cell type (eg. adff when only plain dff");
+ log("is available), an error is raised.");
+ }
+
+ // Table of all supported cell types.
+ // First index in the array is one of the FF_* values, second
+ // index is the set of negative-polarity inputs (OR of NEG_*
+ // values), and the value is the set of supported init values
+ // (OR of INIT_* values).
+ int supported_cells_neg[NUM_FFTYPES][NUM_NEG];
+ // Aggregated table ignoring signal polarity.
+ 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 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_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;
+
+ dict<SigBit, int> ce_used;
+ dict<SigBit, int> srst_used;
+
+ SigMap sigmap;
+ FfInitVals initvals;
+
+ int flip_initmask(int mask) {
+ int res = mask & INIT_X;
+ if (mask & INIT_0)
+ 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;
+ }
+
+ 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 {
+ 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;
+ }
+
+ void emulate_split_init_arst(FfData &ff) {
+ ff.remove();
+
+ 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;
+
+ 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;
+
+ 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;
+
+ 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);
+ }
+
+ 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
+ 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 we have to unmap enable anyway, do it before breakdown.
+ if (ff.has_ce && !supported_cells[FF_ADFFE])
+ ff.unmap_ce();
+
+ 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_assert(ff.width == 1);
+ ff.remove();
+
+ 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;
+
+ 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;
+ }
+ // 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);
+ }
+
+ void legalize_sdffce(FfData &ff) {
+ if (!try_flip(ff, supported_cells[FF_SDFFCE] | supported_cells[FF_SDFFE])) {
+ ff.unmap_srst();
+ legalize_dff(ff);
+ return;
+ }
+
+ 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 {
+ 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);
+ }
+
+ 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 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;
+ }
+ // 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();
+ }
+
+ if (!ff.has_ce) {
+ if (supported_cells[FF_ALDFF] & initmask) {
+ legalize_finish(ff);
+ return;
+ }
+ 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);
+ }
+
+ 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;
+ }
+ }
+ 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;
+ }
+ }
+ }
+ }
+
+ 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
+ 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);
+ }
+ }
+ }
+
+ 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.
+
+ // Find the smallest value that xored with the neg mask
+ // results in a supported one — this results in preferentially
+ // inverting resets before clocks, etc.
+ int xneg;
+ for (xneg = 0; xneg < NUM_NEG; xneg++)
+ if (supported_cells_neg[ff_type][ff_neg ^ xneg] & initmask)
+ break;
+ log_assert(xneg < NUM_NEG);
+ 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)
+ flip_pol(ff, ff.sig_clk, ff.pol_clk);
+ ff_neg ^= xneg;
+ }
+
+ fixup_reset_x(ff, supported_cells_neg[ff_type][ff_neg]);
+ ff.emit();
+ }
+
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+
+ log_header(design, "Executing DFFLEGALIZE pass (convert FFs to types supported by the target).\n");
+
+ for (int i = 0; i < NUM_FFTYPES; i++) {
+ for (int j = 0; j < NUM_NEG; j++)
+ supported_cells_neg[i][j] = 0;
+ supported_cells[i] = 0;
+ }
+ mince = 0;
+ minsrst = 0;
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-cell" && argidx + 2 < args.size()) {
+ std::string celltype = args[++argidx];
+ std::string inittype = args[++argidx];
+ enum FfType ff_type;
+ char pol_c = 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 = FF_SR;
+ pol_s = celltype[5];
+ pol_r = celltype[6];
+ } else if (celltype.substr(0, 6) == "$_DFF_" && celltype.size() == 8 && celltype[7] == '_') {
+ ff_type = FF_DFF;
+ pol_c = celltype[6];
+ } else if (celltype.substr(0, 7) == "$_DFFE_" && celltype.size() == 10 && celltype[9] == '_') {
+ ff_type = FF_DFFE;
+ pol_c = celltype[7];
+ pol_ce = celltype[8];
+ } else if (celltype.substr(0, 6) == "$_DFF_" && celltype.size() == 10 && celltype[9] == '_') {
+ 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 = FF_ADFFE;
+ pol_c = celltype[7];
+ pol_r = celltype[8];
+ srval = celltype[9];
+ 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 = 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 = FF_DFFSRE;
+ pol_c = celltype[9];
+ pol_s = celltype[10];
+ pol_r = celltype[11];
+ pol_ce = celltype[12];
+ } else if (celltype.substr(0, 7) == "$_SDFF_" && celltype.size() == 11 && celltype[10] == '_') {
+ 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 = FF_SDFFE;
+ pol_c = celltype[8];
+ pol_r = celltype[9];
+ srval = celltype[10];
+ pol_ce = celltype[11];
+ } else if (celltype.substr(0, 9) == "$_SDFFCE_" && celltype.size() == 14 && celltype[13] == '_') {
+ ff_type = FF_SDFFCE;
+ pol_c = celltype[9];
+ pol_r = celltype[10];
+ srval = celltype[11];
+ pol_ce = celltype[12];
+ } else if (celltype.substr(0, 9) == "$_DLATCH_" && celltype.size() == 11 && celltype[10] == '_') {
+ ff_type = FF_DLATCH;
+ pol_l = celltype[9];
+ } else if (celltype.substr(0, 9) == "$_DLATCH_" && celltype.size() == 13 && celltype[12] == '_') {
+ 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 = FF_DLATCHSR;
+ pol_l = celltype[11];
+ pol_s = celltype[12];
+ pol_r = celltype[13];
+ } else {
+unrecognized:
+ log_error("unrecognized cell type %s.\n", celltype.c_str());
+ }
+ int mask = 0;
+ int match = 0;
+ for (auto pair : {
+ std::make_pair(pol_c, NEG_C),
+ 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;
+ match |= pair.second;
+ } else if (pair.first == 'P' || pair.first == 0) {
+ mask |= pair.second;
+ } else if (pair.first != '?') {
+ 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') {
+ initmask &= 0x0ff;
+ } else if (srval == '1') {
+ initmask &= 0xf0f;
+ } else if (srval != 0 && srval != '?') {
+ goto unrecognized;
+ }
+ 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());
+ continue;
+ } else if (args[argidx] == "-minsrst" && argidx + 1 < args.size()) {
+ minsrst = atoi(args[++argidx].c_str());
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+ supported_dffsr = supported_cells[FF_DFFSR] | supported_cells[FF_DFFSRE];
+ 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())
+ {
+ sigmap.set(module);
+ initvals.set(&sigmap, module);
+
+ if (mince || minsrst) {
+ ce_used.clear();
+ srst_used.clear();
+
+ for (auto cell : module->cells()) {
+ if (!RTLIL::builtin_ff_cell_types().count(cell->type))
+ continue;
+
+ 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;
+ }
+ }
+ for (auto cell : module->selected_cells())
+ {
+ if (!RTLIL::builtin_ff_cell_types().count(cell->type))
+ continue;
+ FfData ff(&initvals, cell);
+ legalize_ff(ff);
+ }
+ }
+
+ sigmap.clear();
+ initvals.clear();
+ ce_used.clear();
+ srst_used.clear();
+ }
+} DffLegalizePass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc
index c189d649b..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
@@ -115,7 +115,7 @@ static bool parse_pin(LibertyAst *cell, LibertyAst *attr, std::string &pin_name,
return false;
}
-static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has_reset, bool rstpol, bool rstval, bool prepare_mode)
+static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has_reset, bool rstpol, bool rstval)
{
LibertyAst *best_cell = nullptr;
std::map<std::string, char> best_cell_ports;
@@ -222,21 +222,12 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has
if (best_cell != nullptr) {
log(" cell %s (%sinv, pins=%d, area=%.2f) is a direct match for cell type %s.\n",
best_cell->args[0].c_str(), best_cell_noninv ? "non" : "", best_cell_pins, best_cell_area, cell_type.c_str());
- if (prepare_mode) {
- cell_mappings[cell_type].cell_name = cell_type;
- cell_mappings[cell_type].ports["C"] = 'C';
- if (has_reset)
- cell_mappings[cell_type].ports["R"] = 'R';
- cell_mappings[cell_type].ports["D"] = 'D';
- cell_mappings[cell_type].ports["Q"] = 'Q';
- } else {
- cell_mappings[cell_type].cell_name = RTLIL::escape_id(best_cell->args[0]);
- cell_mappings[cell_type].ports = best_cell_ports;
- }
+ cell_mappings[cell_type].cell_name = RTLIL::escape_id(best_cell->args[0]);
+ cell_mappings[cell_type].ports = best_cell_ports;
}
}
-static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool setpol, bool clrpol, bool prepare_mode)
+static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool setpol, bool clrpol)
{
LibertyAst *best_cell = nullptr;
std::map<std::string, char> best_cell_ports;
@@ -339,141 +330,12 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool
if (best_cell != nullptr) {
log(" cell %s (%sinv, pins=%d, area=%.2f) is a direct match for cell type %s.\n",
best_cell->args[0].c_str(), best_cell_noninv ? "non" : "", best_cell_pins, best_cell_area, cell_type.c_str());
- if (prepare_mode) {
- cell_mappings[cell_type].cell_name = cell_type;
- cell_mappings[cell_type].ports["C"] = 'C';
- cell_mappings[cell_type].ports["S"] = 'S';
- cell_mappings[cell_type].ports["R"] = 'R';
- cell_mappings[cell_type].ports["D"] = 'D';
- cell_mappings[cell_type].ports["Q"] = 'Q';
- } else {
- cell_mappings[cell_type].cell_name = RTLIL::escape_id(best_cell->args[0]);
- cell_mappings[cell_type].ports = best_cell_ports;
- }
+ cell_mappings[cell_type].cell_name = RTLIL::escape_id(best_cell->args[0]);
+ cell_mappings[cell_type].ports = best_cell_ports;
}
}
-static bool expand_cellmap_worker(std::string from, std::string to, std::string inv)
-{
- if (cell_mappings.count(to) > 0)
- return false;
-
- log(" create mapping for %s from mapping for %s.\n", to.c_str(), from.c_str());
- cell_mappings[to].cell_name = cell_mappings[from].cell_name;
- cell_mappings[to].ports = cell_mappings[from].ports;
-
- for (auto &it : cell_mappings[to].ports) {
- char cmp_ch = it.second;
- if ('a' <= cmp_ch && cmp_ch <= 'z')
- cmp_ch -= 'a' - 'A';
- if (inv.find(cmp_ch) == std::string::npos)
- continue;
- if ('a' <= it.second && it.second <= 'z')
- it.second -= 'a' - 'A';
- else if ('A' <= it.second && it.second <= 'Z')
- it.second += 'a' - 'A';
- }
- return true;
-}
-
-static bool expand_cellmap(std::string pattern, std::string inv)
-{
- std::vector<std::pair<std::string, std::string>> from_to_list;
- bool return_status = false;
-
- for (auto &it : cell_mappings) {
- std::string from = it.first.str(), to = it.first.str();
- if (from.size() != pattern.size())
- continue;
- for (size_t i = 0; i < from.size(); i++) {
- if (pattern[i] == '*') {
- to[i] = from[i] == 'P' ? 'N' :
- from[i] == 'N' ? 'P' :
- from[i] == '1' ? '0' :
- from[i] == '0' ? '1' : '*';
- } else
- if (pattern[i] != '?' && pattern[i] != from[i])
- goto pattern_failed;
- }
- from_to_list.push_back(std::pair<std::string, std::string>(from, to));
- pattern_failed:;
- }
-
- for (auto &it : from_to_list)
- return_status = return_status || expand_cellmap_worker(it.first, it.second, inv);
- return return_status;
-}
-
-static void map_sr_to_arst(IdString from, IdString to)
-{
- if (!cell_mappings.count(from) || cell_mappings.count(to) > 0)
- return;
-
- char from_clk_pol = from[8];
- char from_set_pol = from[9];
- char from_clr_pol = from[10];
- char to_clk_pol = to[6];
- char to_rst_pol = to[7];
- char to_rst_val = to[8];
-
- log_assert(from_clk_pol == to_clk_pol);
- log_assert(to_rst_pol == from_set_pol && to_rst_pol == from_clr_pol);
-
- log(" create mapping for %s from mapping for %s.\n", to.c_str(), from.c_str());
- cell_mappings[to].cell_name = cell_mappings[from].cell_name;
- cell_mappings[to].ports = cell_mappings[from].ports;
-
- for (auto &it : cell_mappings[to].ports)
- {
- bool is_set_pin = it.second == 'S' || it.second == 's';
- bool is_clr_pin = it.second == 'R' || it.second == 'r';
-
- if (!is_set_pin && !is_clr_pin)
- continue;
-
- if ((to_rst_val == '0' && is_set_pin) || (to_rst_val == '1' && is_clr_pin))
- {
- // this is the unused set/clr pin -- deactivate it
- if (is_set_pin)
- it.second = (from_set_pol == 'P') == (it.second == 'S') ? '0' : '1';
- else
- it.second = (from_clr_pol == 'P') == (it.second == 'R') ? '0' : '1';
- }
- else
- {
- // this is the used set/clr pin -- rename it to 'reset'
- if (it.second == 'S')
- it.second = 'R';
- if (it.second == 's')
- it.second = 'r';
- }
- }
-}
-
-static void map_adff_to_dff(IdString from, IdString to)
-{
- if (!cell_mappings.count(from) || cell_mappings.count(to) > 0)
- return;
-
- char from_clk_pol = from[6];
- char from_rst_pol = from[7];
- char to_clk_pol = to[6];
-
- log_assert(from_clk_pol == to_clk_pol);
-
- log(" create mapping for %s from mapping for %s.\n", to.c_str(), from.c_str());
- cell_mappings[to].cell_name = cell_mappings[from].cell_name;
- cell_mappings[to].ports = cell_mappings[from].ports;
-
- for (auto &it : cell_mappings[to].ports) {
- if (it.second == 'S' || it.second == 'R')
- it.second = from_rst_pol == 'P' ? '0' : '1';
- if (it.second == 's' || it.second == 'r')
- it.second = from_rst_pol == 'P' ? '1' : '0';
- }
-}
-
-static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module, bool prepare_mode)
+static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module)
{
log("Mapping DFF cells in module `%s':\n", module->name.c_str());
@@ -499,7 +361,7 @@ static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module, bool prepare
module->remove(cell);
cell_mapping &cm = cell_mappings[cell_type];
- RTLIL::Cell *new_cell = module->addCell(cell_name, prepare_mode ? cm.cell_name : cm.cell_name);
+ RTLIL::Cell *new_cell = module->addCell(cell_name, cm.cell_name);
new_cell->set_src_attribute(src);
@@ -552,7 +414,7 @@ struct DfflibmapPass : public Pass {
void help() override
{
log("\n");
- log(" dfflibmap [-prepare] -liberty <file> [selection]\n");
+ log(" dfflibmap [-prepare] [-map-only] [-info] -liberty <file> [selection]\n");
log("\n");
log("Map internal flip-flop cells to the flip-flop cells in the technology\n");
log("library specified in the given liberty file.\n");
@@ -562,15 +424,27 @@ struct DfflibmapPass : public Pass {
log("\n");
log("When called with -prepare, this command will convert the internal FF cells\n");
log("to the internal cell types that best match the cells found in the given\n");
- log("liberty file.\n");
+ log("liberty file, but won't actually map them to the target cells.\n");
+ log("\n");
+ log("When called with -map-only, this command will only map internal cell\n");
+ log("types that are already of exactly the right type to match the target\n");
+ log("cells, leaving remaining internal cells untouched.\n");
+ log("\n");
+ log("When called with -info, this command will only print the target cell\n");
+ log("list, along with their associated internal cell types, and the arguments");
+ log("that would be passed to the dfflegalize pass. The design will not be\n");
+ log("changed.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
log_header(design, "Executing DFFLIBMAP pass (mapping DFF cells to sequential cells from liberty file).\n");
+ log_push();
std::string liberty_file;
bool prepare_mode = false;
+ bool map_only_mode = false;
+ bool info_mode = false;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@@ -585,10 +459,28 @@ struct DfflibmapPass : public Pass {
prepare_mode = true;
continue;
}
+ if (arg == "-map-only") {
+ map_only_mode = true;
+ continue;
+ }
+ if (arg == "-info") {
+ info_mode = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
+ int modes = 0;
+ if (prepare_mode)
+ modes++;
+ if (map_only_mode)
+ modes++;
+ if (info_mode)
+ modes++;
+ if (modes > 1)
+ log_cmd_error("Only one of -prepare, -map-only, or -info options should be given!\n");
+
if (liberty_file.empty())
log_cmd_error("Missing `-liberty liberty_file' option!\n");
@@ -599,74 +491,49 @@ struct DfflibmapPass : public Pass {
LibertyParser libparser(f);
f.close();
- find_cell(libparser.ast, ID($_DFF_N_), false, false, false, false, prepare_mode);
- find_cell(libparser.ast, ID($_DFF_P_), true, false, false, false, prepare_mode);
-
- find_cell(libparser.ast, ID($_DFF_NN0_), false, true, false, false, prepare_mode);
- find_cell(libparser.ast, ID($_DFF_NN1_), false, true, false, true, prepare_mode);
- find_cell(libparser.ast, ID($_DFF_NP0_), false, true, true, false, prepare_mode);
- find_cell(libparser.ast, ID($_DFF_NP1_), false, true, true, true, prepare_mode);
- find_cell(libparser.ast, ID($_DFF_PN0_), true, true, false, false, prepare_mode);
- find_cell(libparser.ast, ID($_DFF_PN1_), true, true, false, true, prepare_mode);
- find_cell(libparser.ast, ID($_DFF_PP0_), true, true, true, false, prepare_mode);
- find_cell(libparser.ast, ID($_DFF_PP1_), true, true, true, true, prepare_mode);
-
- find_cell_sr(libparser.ast, ID($_DFFSR_NNN_), false, false, false, prepare_mode);
- find_cell_sr(libparser.ast, ID($_DFFSR_NNP_), false, false, true, prepare_mode);
- find_cell_sr(libparser.ast, ID($_DFFSR_NPN_), false, true, false, prepare_mode);
- find_cell_sr(libparser.ast, ID($_DFFSR_NPP_), false, true, true, prepare_mode);
- find_cell_sr(libparser.ast, ID($_DFFSR_PNN_), true, false, false, prepare_mode);
- find_cell_sr(libparser.ast, ID($_DFFSR_PNP_), true, false, true, prepare_mode);
- find_cell_sr(libparser.ast, ID($_DFFSR_PPN_), true, true, false, prepare_mode);
- find_cell_sr(libparser.ast, ID($_DFFSR_PPP_), true, true, true, prepare_mode);
-
- // try to implement as many cells as possible just by inverting
- // the SET and RESET pins. If necessary, implement cell types
- // by inverting both D and Q. Only invert clock pins if there
- // is no other way of implementing the cell.
- while (1)
- {
- if (expand_cellmap("$_DFF_?*?_", "R") ||
- expand_cellmap("$_DFFSR_?*?_", "S") ||
- expand_cellmap("$_DFFSR_??*_", "R"))
- continue;
-
- if (expand_cellmap("$_DFF_??*_", "DQ"))
- continue;
-
- if (expand_cellmap("$_DFF_*_", "C") ||
- expand_cellmap("$_DFF_*??_", "C") ||
- expand_cellmap("$_DFFSR_*??_", "C"))
- continue;
-
- break;
- }
-
- map_sr_to_arst(ID($_DFFSR_NNN_), ID($_DFF_NN0_));
- map_sr_to_arst(ID($_DFFSR_NNN_), ID($_DFF_NN1_));
- map_sr_to_arst(ID($_DFFSR_NPP_), ID($_DFF_NP0_));
- map_sr_to_arst(ID($_DFFSR_NPP_), ID($_DFF_NP1_));
- map_sr_to_arst(ID($_DFFSR_PNN_), ID($_DFF_PN0_));
- map_sr_to_arst(ID($_DFFSR_PNN_), ID($_DFF_PN1_));
- map_sr_to_arst(ID($_DFFSR_PPP_), ID($_DFF_PP0_));
- map_sr_to_arst(ID($_DFFSR_PPP_), ID($_DFF_PP1_));
-
- map_adff_to_dff(ID($_DFF_NN0_), ID($_DFF_N_));
- map_adff_to_dff(ID($_DFF_NN1_), ID($_DFF_N_));
- map_adff_to_dff(ID($_DFF_NP0_), ID($_DFF_N_));
- map_adff_to_dff(ID($_DFF_NP1_), ID($_DFF_N_));
- map_adff_to_dff(ID($_DFF_PN0_), ID($_DFF_P_));
- map_adff_to_dff(ID($_DFF_PN1_), ID($_DFF_P_));
- map_adff_to_dff(ID($_DFF_PP0_), ID($_DFF_P_));
- map_adff_to_dff(ID($_DFF_PP1_), ID($_DFF_P_));
+ find_cell(libparser.ast, ID($_DFF_N_), false, false, false, false);
+ find_cell(libparser.ast, ID($_DFF_P_), true, false, false, false);
+
+ find_cell(libparser.ast, ID($_DFF_NN0_), false, true, false, false);
+ find_cell(libparser.ast, ID($_DFF_NN1_), false, true, false, true);
+ find_cell(libparser.ast, ID($_DFF_NP0_), false, true, true, false);
+ find_cell(libparser.ast, ID($_DFF_NP1_), false, true, true, true);
+ find_cell(libparser.ast, ID($_DFF_PN0_), true, true, false, false);
+ find_cell(libparser.ast, ID($_DFF_PN1_), true, true, false, true);
+ find_cell(libparser.ast, ID($_DFF_PP0_), true, true, true, false);
+ find_cell(libparser.ast, ID($_DFF_PP1_), true, true, true, true);
+
+ find_cell_sr(libparser.ast, ID($_DFFSR_NNN_), false, false, false);
+ find_cell_sr(libparser.ast, ID($_DFFSR_NNP_), false, false, true);
+ find_cell_sr(libparser.ast, ID($_DFFSR_NPN_), false, true, false);
+ find_cell_sr(libparser.ast, ID($_DFFSR_NPP_), false, true, true);
+ find_cell_sr(libparser.ast, ID($_DFFSR_PNN_), true, false, false);
+ find_cell_sr(libparser.ast, ID($_DFFSR_PNP_), true, false, true);
+ find_cell_sr(libparser.ast, ID($_DFFSR_PPN_), true, true, false);
+ find_cell_sr(libparser.ast, ID($_DFFSR_PPP_), true, true, true);
log(" final dff cell mappings:\n");
logmap_all();
- for (auto module : design->selected_modules())
- if (!module->get_blackbox_attribute())
- dfflibmap(design, module, prepare_mode);
+ if (!map_only_mode) {
+ std::string dfflegalize_cmd = "dfflegalize";
+ for (auto it : cell_mappings)
+ dfflegalize_cmd += stringf(" -cell %s 01", it.first.c_str());
+ dfflegalize_cmd += " t:$_DFF* t:$_SDFF*";
+ if (info_mode) {
+ log("dfflegalize command line: %s\n", dfflegalize_cmd.c_str());
+ } else {
+ Pass::call(design, dfflegalize_cmd);
+ }
+ }
+
+ if (!prepare_mode && !info_mode) {
+ for (auto module : design->selected_modules())
+ if (!module->get_blackbox_attribute())
+ dfflibmap(design, module);
+ }
+ log_pop();
cell_mappings.clear();
}
} DfflibmapPass;
diff --git a/passes/techmap/dffunmap.cc b/passes/techmap/dffunmap.cc
new file mode 100644
index 000000000..7312015f1
--- /dev/null
+++ b/passes/techmap/dffunmap.cc
@@ -0,0 +1,106 @@
+/*
+ * 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/ff.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct DffunmapPass : public Pass {
+ DffunmapPass() : Pass("dffunmap", "unmap clock enable and synchronous reset from FFs") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" dffunmap [options] [selection]\n");
+ log("\n");
+ log("This pass transforms FF types with clock enable and/or synchronous reset into\n");
+ log("their base type (with neither clock enable nor sync reset) by emulating the clock\n");
+ log("enable and synchronous reset with multiplexers on the cell input.\n");
+ log("\n");
+ log(" -ce-only\n");
+ log(" unmap only clock enables, leave synchronous resets alone.\n");
+ log("\n");
+ log(" -srst-only\n");
+ log(" unmap only synchronous resets, leave clock enables alone.\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ log_header(design, "Executing DFFUNMAP pass (unmap clock enable and synchronous reset from FFs).\n");
+
+ bool ce_only = false;
+ bool srst_only = false;
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ if (args[argidx] == "-ce-only") {
+ ce_only = true;
+ continue;
+ }
+ if (args[argidx] == "-srst-only") {
+ srst_only = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ if (ce_only && srst_only)
+ log_cmd_error("Options -ce-only and -srst-only are mutually exclusive!\n");
+
+ for (auto mod : design->selected_modules())
+ {
+ SigMap sigmap(mod);
+ FfInitVals initvals(&sigmap, mod);
+
+ for (auto cell : mod->selected_cells())
+ {
+ if (!RTLIL::builtin_ff_cell_types().count(cell->type))
+ continue;
+
+ FfData ff(&initvals, cell);
+ IdString name = cell->name;
+
+ if (!ff.has_clk)
+ continue;
+
+ if (ce_only) {
+ if (!ff.has_ce)
+ continue;
+ ff.unmap_ce();
+ } else if (srst_only) {
+ if (!ff.has_srst)
+ continue;
+ ff.unmap_srst();
+ } else {
+ if (!ff.has_ce && !ff.has_srst)
+ continue;
+ ff.unmap_ce_srst();
+ }
+
+ ff.emit();
+ }
+ }
+ }
+} DffunmapPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/extract.cc b/passes/techmap/extract.cc
index 7278cb680..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)
@@ -354,7 +355,7 @@ struct ExtractPass : public Pass {
log("\n");
log("This pass looks for subcircuits that are isomorphic to any of the modules\n");
log("in the given map file and replaces them with instances of this modules. The\n");
- log("map file can be a Verilog source file (*.v) or an ilang file (*.il).\n");
+ log("map file can be a Verilog source file (*.v) or an RTLIL source file (*.il).\n");
log("\n");
log(" -map <map_file>\n");
log(" use the modules in this file as reference. This option can be used\n");
@@ -409,7 +410,7 @@ struct ExtractPass : public Pass {
log("the following options are to be used instead of the -map option.\n");
log("\n");
log(" -mine <out_file>\n");
- log(" mine for frequent subcircuits and write them to the given ilang file\n");
+ log(" mine for frequent subcircuits and write them to the given RTLIL file\n");
log("\n");
log(" -mine_cells_span <min> <max>\n");
log(" only mine for subcircuits with the specified number of cells\n");
@@ -578,7 +579,7 @@ struct ExtractPass : public Pass {
}
if (map_filenames.empty() && mine_outfile.empty())
- log_cmd_error("Missing option -map <verilog_or_ilang_file> or -mine <output_ilang_file>.\n");
+ log_cmd_error("Missing option -map <verilog_or_rtlil_file> or -mine <output_rtlil_file>.\n");
RTLIL::Design *map = nullptr;
@@ -606,7 +607,7 @@ struct ExtractPass : public Pass {
delete map;
log_cmd_error("Can't open map file `%s'.\n", filename.c_str());
}
- Frontend::frontend_call(map, &f, filename, (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".il") == 0 ? "ilang" : "verilog"));
+ Frontend::frontend_call(map, &f, filename, (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".il") == 0 ? "rtlil" : "verilog"));
f.close();
if (filename.size() <= 3 || filename.compare(filename.size()-3, std::string::npos, ".il") != 0) {
@@ -744,7 +745,7 @@ struct ExtractPass : public Pass {
f.open(mine_outfile.c_str(), std::ofstream::trunc);
if (f.fail())
log_error("Can't open output file `%s'.\n", mine_outfile.c_str());
- Backend::backend_call(map, &f, mine_outfile, "ilang");
+ Backend::backend_call(map, &f, mine_outfile, "rtlil");
f.close();
}
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 9b350456f..48d9600fa 100644
--- a/passes/techmap/extractinv.cc
+++ b/passes/techmap/extractinv.cc
@@ -1,8 +1,8 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- * Copyright (C) 2019 Marcin Kościelnicki <mwk@0x04.net>
+ * 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
* purpose with or without fee is hereby granted, provided that the above
diff --git a/passes/techmap/flatten.cc b/passes/techmap/flatten.cc
index b5f55cffa..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()));
}
@@ -152,18 +155,16 @@ struct FlattenWorker
// Attach port connections of the flattened cell
- SigMap tpl_sigmap(tpl);
pool<SigBit> tpl_driven;
for (auto tpl_cell : tpl->cells())
for (auto &tpl_conn : tpl_cell->connections())
if (tpl_cell->output(tpl_conn.first))
- for (auto bit : tpl_sigmap(tpl_conn.second))
+ for (auto bit : tpl_conn.second)
tpl_driven.insert(bit);
for (auto &tpl_conn : tpl->connections())
- for (auto bit : tpl_sigmap(tpl_conn.first))
+ 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;
@@ -181,16 +182,19 @@ struct FlattenWorker
RTLIL::Wire *tpl_wire = tpl->wire(port_name);
RTLIL::SigSig new_conn;
+ bool is_signed = false;
if (tpl_wire->port_output && !tpl_wire->port_input) {
new_conn.first = port_it.second;
new_conn.second = tpl_wire;
+ is_signed = tpl_wire->is_signed;
} else if (!tpl_wire->port_output && tpl_wire->port_input) {
new_conn.first = tpl_wire;
new_conn.second = port_it.second;
+ is_signed = new_conn.second.is_wire() && new_conn.second.as_wire()->is_signed;
} else {
SigSpec sig_tpl = tpl_wire, sig_mod = port_it.second;
for (int i = 0; i < GetSize(sig_tpl) && i < GetSize(sig_mod); i++) {
- if (tpl_driven.count(tpl_sigmap(sig_tpl[i]))) {
+ if (tpl_driven.count(sig_tpl[i])) {
new_conn.first.append(sig_mod[i]);
new_conn.second.append(sig_tpl[i]);
} else {
@@ -205,14 +209,15 @@ struct FlattenWorker
if (new_conn.second.size() > new_conn.first.size())
new_conn.second.remove(new_conn.first.size(), new_conn.second.size() - new_conn.first.size());
if (new_conn.second.size() < new_conn.first.size())
- new_conn.second.append(RTLIL::SigSpec(RTLIL::State::S0, new_conn.first.size() - new_conn.second.size()));
+ new_conn.second.extend_u0(new_conn.first.size(), is_signed);
log_assert(new_conn.first.size() == new_conn.second.size());
if (sigmap(new_conn.first).has_const())
- log_error("Mismatch in directionality for cell port %s.%s.%s: %s <= %s\n",
+ log_error("Cell port %s.%s.%s is driving constant bits: %s <= %s\n",
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);
@@ -223,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())
{
@@ -246,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 237c261ae..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
@@ -19,6 +19,7 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
+#include "kernel/ffinit.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -100,9 +101,8 @@ struct ShregmapWorker
int dff_count, shreg_count;
pool<Cell*> remove_cells;
- pool<SigBit> remove_init;
- dict<SigBit, bool> sigbit_init;
+ FfInitVals initvals;
dict<SigBit, Cell*> sigbit_chain_next;
dict<SigBit, Cell*> sigbit_chain_prev;
pool<SigBit> sigbit_with_non_chain_users;
@@ -116,16 +116,6 @@ struct ShregmapWorker
for (auto bit : sigmap(wire))
sigbit_with_non_chain_users.insert(bit);
}
-
- if (wire->attributes.count(ID::init)) {
- SigSpec initsig = sigmap(wire);
- Const initval = wire->attributes.at(ID::init);
- for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++)
- if (initval[i] == State::S0 && !opts.zinit)
- sigbit_init[initsig[i]] = false;
- else if (initval[i] == State::S1)
- sigbit_init[initsig[i]] = true;
- }
}
for (auto cell : module->cells())
@@ -137,8 +127,9 @@ struct ShregmapWorker
SigBit d_bit = sigmap(cell->getPort(d_port).as_bit());
SigBit q_bit = sigmap(cell->getPort(q_port).as_bit());
+ State initval = initvals(q_bit);
- if (opts.init || sigbit_init.count(q_bit) == 0)
+ if (opts.init || initval == State::Sx || (opts.zinit && initval == State::S0))
{
auto r = sigbit_chain_next.insert(std::make_pair(d_bit, cell));
if (!r.second) {
@@ -310,22 +301,17 @@ struct ShregmapWorker
if (opts.init) {
vector<State> initval;
for (int i = depth-1; i >= 0; i--) {
- SigBit bit = sigmap(chain[cursor+i]->getPort(q_port).as_bit());
- if (sigbit_init.count(bit) == 0)
- initval.push_back(State::Sx);
- else if (sigbit_init.at(bit))
- initval.push_back(State::S1);
- else
- initval.push_back(State::S0);
- remove_init.insert(bit);
+ SigBit bit = chain[cursor+i]->getPort(q_port).as_bit();
+ initval.push_back(initvals(bit));
+ initvals.remove_init(bit);
}
first_cell->setParam(ID::INIT, initval);
}
if (opts.zinit)
for (int i = depth-1; i >= 0; i--) {
- SigBit bit = sigmap(chain[cursor+i]->getPort(q_port).as_bit());
- remove_init.insert(bit);
+ SigBit bit = chain[cursor+i]->getPort(q_port).as_bit();
+ initvals.remove_init(bit);
}
if (opts.params)
@@ -364,22 +350,6 @@ struct ShregmapWorker
for (auto cell : remove_cells)
module->remove(cell);
- for (auto wire : module->wires())
- {
- if (wire->attributes.count(ID::init) == 0)
- continue;
-
- SigSpec initsig = sigmap(wire);
- Const &initval = wire->attributes.at(ID::init);
-
- for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++)
- if (remove_init.count(initsig[i]))
- initval[i] = State::Sx;
-
- if (SigSpec(initval).is_fully_undef())
- wire->attributes.erase(ID::init);
- }
-
remove_cells.clear();
sigbit_chain_next.clear();
sigbit_chain_prev.clear();
@@ -389,6 +359,7 @@ struct ShregmapWorker
ShregmapWorker(Module *module, const ShregmapOptions &opts) :
module(module), sigmap(module), opts(opts), dff_count(0), shreg_count(0)
{
+ initvals.set(&sigmap, module);
make_sigbit_chain_next_prev();
find_chain_start_cells();
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 f98d1564a..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
@@ -20,6 +20,7 @@
#include "kernel/yosys.h"
#include "kernel/utils.h"
#include "kernel/sigtools.h"
+#include "kernel/ffinit.h"
#include "libs/sha1/sha1.h"
#include <stdlib.h>
@@ -117,19 +118,14 @@ struct TechmapWorker
return result;
for (auto w : module->wires()) {
- const char *p = w->name.c_str();
- if (*p == '$')
+ if (*w->name.c_str() == '$')
continue;
- const char *q = strrchr(p+1, '.');
- if (q)
- p = q;
-
- if (!strncmp(p, "\\_TECHMAP_", 10)) {
+ if (w->name.contains("_TECHMAP_") && !w->name.contains("_TECHMAP_REPLACE_")) {
TechmapWireData record;
record.wire = w;
record.value = w;
- result[p].push_back(record);
+ result[w->name].push_back(record);
w->set_bool_attribute(ID::keep);
w->set_bool_attribute(ID::_techmap_special_);
}
@@ -164,7 +160,7 @@ struct TechmapWorker
orig_cell_name = cell->name.str();
for (auto tpl_cell : tpl->cells())
- if (tpl_cell->name == ID::_TECHMAP_REPLACE_) {
+ if (tpl_cell->name.ends_with("_TECHMAP_REPLACE_")) {
module->rename(cell, stringf("$techmap%d", autoidx++) + cell->name.str());
break;
}
@@ -225,23 +221,21 @@ struct TechmapWorker
}
design->select(module, w);
- if (tpl_w->name.begins_with("\\_TECHMAP_REPLACE_.")) {
- IdString replace_name = stringf("%s%s", orig_cell_name.c_str(), tpl_w->name.c_str() + strlen("\\_TECHMAP_REPLACE_"));
+ if (const char *p = strstr(tpl_w->name.c_str(), "_TECHMAP_REPLACE_.")) {
+ IdString replace_name = stringf("%s%s", orig_cell_name.c_str(), p + strlen("_TECHMAP_REPLACE_"));
Wire *replace_w = module->addWire(replace_name, tpl_w);
module->connect(replace_w, w);
}
}
- SigMap tpl_sigmap(tpl);
pool<SigBit> tpl_written_bits;
-
for (auto tpl_cell : tpl->cells())
for (auto &conn : tpl_cell->connections())
if (tpl_cell->output(conn.first))
- for (auto bit : tpl_sigmap(conn.second))
+ for (auto bit : conn.second)
tpl_written_bits.insert(bit);
for (auto &conn : tpl->connections())
- for (auto bit : tpl_sigmap(conn.first))
+ for (auto bit : conn.first)
tpl_written_bits.insert(bit);
SigMap port_signal_map;
@@ -279,7 +273,7 @@ struct TechmapWorker
SigSpec sig_tpl = w, sig_tpl_pf = w, sig_mod = it.second;
apply_prefix(cell->name, sig_tpl_pf, module);
for (int i = 0; i < GetSize(sig_tpl) && i < GetSize(sig_mod); i++) {
- if (tpl_written_bits.count(tpl_sigmap(sig_tpl[i]))) {
+ if (tpl_written_bits.count(sig_tpl[i])) {
c.first.append(sig_mod[i]);
c.second.append(sig_tpl_pf[i]);
} else {
@@ -328,12 +322,12 @@ struct TechmapWorker
for (auto tpl_cell : tpl->cells())
{
IdString c_name = tpl_cell->name;
- bool techmap_replace_cell = (c_name == ID::_TECHMAP_REPLACE_);
+ bool techmap_replace_cell = c_name.ends_with("_TECHMAP_REPLACE_");
if (techmap_replace_cell)
c_name = orig_cell_name;
- else if (tpl_cell->name.begins_with("\\_TECHMAP_REPLACE_."))
- c_name = stringf("%s%s", orig_cell_name.c_str(), c_name.c_str() + strlen("\\_TECHMAP_REPLACE_"));
+ else if (const char *p = strstr(tpl_cell->name.c_str(), "_TECHMAP_REPLACE_."))
+ c_name = stringf("%s%s", orig_cell_name.c_str(), p + strlen("_TECHMAP_REPLACE_"));
else
apply_prefix(cell->name, c_name);
@@ -370,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()));
@@ -385,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()) {
@@ -426,18 +420,7 @@ struct TechmapWorker
LogMakeDebugHdl mkdebug;
SigMap sigmap(module);
-
- dict<SigBit, State> init_bits;
- pool<SigBit> remove_init_bits;
-
- for (auto wire : module->wires()) {
- if (wire->attributes.count(ID::init)) {
- Const value = wire->attributes.at(ID::init);
- for (int i = 0; i < min(GetSize(value), GetSize(wire)); i++)
- if (value[i] != State::Sx)
- init_bits[sigmap(SigBit(wire, i))] = value[i];
- }
- }
+ FfInitVals initvals(&sigmap, module);
TopoSort<RTLIL::Cell*, IdString::compare_ptr_by_name<RTLIL::Cell>> cells;
dict<RTLIL::Cell*, pool<RTLIL::SigBit>> cell_to_inbit;
@@ -643,6 +626,8 @@ struct TechmapWorker
if (tpl->avail_parameters.count(ID::_TECHMAP_CELLTYPE_) != 0)
parameters.emplace(ID::_TECHMAP_CELLTYPE_, RTLIL::unescape_id(cell->type));
+ if (tpl->avail_parameters.count(ID::_TECHMAP_CELLNAME_) != 0)
+ parameters.emplace(ID::_TECHMAP_CELLNAME_, RTLIL::unescape_id(cell->name));
for (auto &conn : cell->connections()) {
if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTMSK_%s_", log_id(conn.first))) != 0) {
@@ -659,15 +644,7 @@ struct TechmapWorker
parameters.emplace(stringf("\\_TECHMAP_CONSTVAL_%s_", log_id(conn.first)), RTLIL::SigSpec(v).as_const());
}
if (tpl->avail_parameters.count(stringf("\\_TECHMAP_WIREINIT_%s_", log_id(conn.first))) != 0) {
- auto sig = sigmap(conn.second);
- RTLIL::Const value(State::Sx, sig.size());
- for (int i = 0; i < sig.size(); i++) {
- auto it = init_bits.find(sig[i]);
- if (it != init_bits.end()) {
- value[i] = it->second;
- }
- }
- parameters.emplace(stringf("\\_TECHMAP_WIREINIT_%s_", log_id(conn.first)), value);
+ parameters.emplace(stringf("\\_TECHMAP_WIREINIT_%s_", log_id(conn.first)), initvals(conn.second));
}
}
@@ -748,12 +725,16 @@ struct TechmapWorker
for (auto &it : twd)
techmap_wire_names.insert(it.first);
- for (auto &it : twd[ID::_TECHMAP_FAIL_]) {
- RTLIL::SigSpec value = it.value;
- if (value.is_fully_const() && value.as_bool()) {
- log("Not using module `%s' from techmap as it contains a %s marker wire with non-zero value %s.\n",
- derived_name.c_str(), log_id(it.wire->name), log_signal(value));
- techmap_do_cache[tpl] = false;
+ for (auto &it : twd) {
+ if (!it.first.ends_with("_TECHMAP_FAIL_"))
+ continue;
+ for (const TechmapWireData &elem : it.second) {
+ RTLIL::SigSpec value = elem.value;
+ if (value.is_fully_const() && value.as_bool()) {
+ log("Not using module `%s' from techmap as it contains a %s marker wire with non-zero value %s.\n",
+ derived_name.c_str(), log_id(elem.wire->name), log_signal(value));
+ techmap_do_cache[tpl] = false;
+ }
}
}
@@ -762,7 +743,7 @@ struct TechmapWorker
for (auto &it : twd)
{
- if (!it.first.begins_with("\\_TECHMAP_DO_") || it.second.empty())
+ if (!it.first.contains("_TECHMAP_DO_") || it.second.empty())
continue;
auto &data = it.second.front();
@@ -774,7 +755,7 @@ struct TechmapWorker
const char *p = data.wire->name.c_str();
const char *q = strrchr(p+1, '.');
- q = q ? q : p+1;
+ q = q ? q+1 : p+1;
std::string cmd_string = data.value.as_const().decode_string();
@@ -817,11 +798,31 @@ struct TechmapWorker
}
}
+ // Handle outputs first, as these cannot be remapped.
+ for (auto &conn : cell->connections())
+ {
+ Wire *twire = tpl->wire(conn.first);
+ if (!twire->port_output)
+ continue;
+
+ for (int i = 0; i < GetSize(conn.second); i++) {
+ RTLIL::SigBit bit = sigmap(conn.second[i]);
+ RTLIL::SigBit tplbit(twire, i);
+ cellbits_to_tplbits[bit] = tplbit;
+ }
+ }
+
+ // Now handle inputs, remapping as necessary.
for (auto &conn : cell->connections())
+ {
+ Wire *twire = tpl->wire(conn.first);
+ if (twire->port_output)
+ continue;
+
for (int i = 0; i < GetSize(conn.second); i++)
{
RTLIL::SigBit bit = sigmap(conn.second[i]);
- RTLIL::SigBit tplbit(tpl->wire(conn.first), i);
+ RTLIL::SigBit tplbit(twire, i);
if (bit.wire == nullptr)
{
@@ -836,6 +837,7 @@ struct TechmapWorker
else
cellbits_to_tplbits[bit] = tplbit;
}
+ }
RTLIL::SigSig port_conn;
for (auto &it : port_connmap) {
@@ -870,7 +872,7 @@ struct TechmapWorker
TechmapWires twd = techmap_find_special_wires(tpl);
for (auto &it : twd) {
- if (it.first != ID::_TECHMAP_FAIL_ && (!it.first.begins_with("\\_TECHMAP_REMOVEINIT_") || !it.first.ends_with("_")) && !it.first.begins_with("\\_TECHMAP_DO_") && !it.first.begins_with("\\_TECHMAP_DONE_"))
+ if (!it.first.ends_with("_TECHMAP_FAIL_") && (!it.first.begins_with("\\_TECHMAP_REMOVEINIT_") || !it.first.ends_with("_")) && !it.first.contains("_TECHMAP_DO_") && !it.first.contains("_TECHMAP_DONE_"))
log_error("Techmap yielded unknown config wire %s.\n", log_id(it.first));
if (techmap_do_cache[tpl])
for (auto &it2 : it.second)
@@ -912,7 +914,7 @@ struct TechmapWorker
auto sig = sigmap(it->second);
for (int i = 0; i < sig.size(); i++)
if (val[i] == State::S1)
- remove_init_bits.insert(sig[i]);
+ initvals.remove_init(sig[i]);
}
}
}
@@ -961,25 +963,6 @@ struct TechmapWorker
handled_cells.insert(cell);
}
- if (!remove_init_bits.empty()) {
- for (auto wire : module->wires())
- if (wire->attributes.count(ID::init)) {
- Const &value = wire->attributes.at(ID::init);
- bool do_cleanup = true;
- for (int i = 0; i < min(GetSize(value), GetSize(wire)); i++) {
- SigBit bit = sigmap(SigBit(wire, i));
- if (remove_init_bits.count(bit))
- value[i] = State::Sx;
- else if (value[i] != State::Sx)
- do_cleanup = false;
- }
- if (do_cleanup) {
- log("Removing init attribute from wire %s.%s.\n", log_id(module), log_id(wire));
- wire->attributes.erase(ID::init);
- }
- }
- }
-
if (log_continue) {
log_header(design, "Continuing TECHMAP pass.\n");
log_continue = false;
@@ -999,7 +982,7 @@ struct TechmapPass : public Pass {
log(" techmap [-map filename] [selection]\n");
log("\n");
log("This pass implements a very simple technology mapper that replaces cells in\n");
- log("the design with implementations given in form of a Verilog or ilang source\n");
+ log("the design with implementations given in form of a Verilog or RTLIL source\n");
log("file.\n");
log("\n");
log(" -map filename\n");
@@ -1042,7 +1025,9 @@ struct TechmapPass : public Pass {
log("\n");
log("When a module in the map file has the 'techmap_celltype' attribute set, it will\n");
log("match cells with a type that match the text value of this attribute. Otherwise\n");
- log("the module name will be used to match the cell.\n");
+ log("the module name will be used to match the cell. Multiple space-separated cell\n");
+ log("types can be listed, and wildcards using [] will be expanded (ie. \"$_DFF_[PN]_\"\n");
+ log("is the same as \"$_DFF_P_ $_DFF_N_\").\n");
log("\n");
log("When a module in the map file has the 'techmap_simplemap' attribute set, techmap\n");
log("will use 'simplemap' (see 'help simplemap') to map cells matching the module.\n");
@@ -1111,6 +1096,10 @@ struct TechmapPass : public Pass {
log(" When a parameter with this name exists, it will be set to the type name\n");
log(" of the cell that matches the module.\n");
log("\n");
+ log(" _TECHMAP_CELLNAME_\n");
+ log(" When a parameter with this name exists, it will be set to the name\n");
+ log(" of the cell that matches the module.\n");
+ log("\n");
log(" _TECHMAP_CONSTMSK_<port-name>_\n");
log(" _TECHMAP_CONSTVAL_<port-name>_\n");
log(" When this pair of parameters is available in a module for a port, then\n");
@@ -1220,7 +1209,7 @@ struct TechmapPass : public Pass {
if (!map->module(mod->name))
map->add(mod->clone());
} else {
- Frontend::frontend_call(map, nullptr, fn, (fn.size() > 3 && fn.compare(fn.size()-3, std::string::npos, ".il") == 0 ? "ilang" : verilog_frontend));
+ Frontend::frontend_call(map, nullptr, fn, (fn.size() > 3 && fn.compare(fn.size()-3, std::string::npos, ".il") == 0 ? "rtlil" : verilog_frontend));
}
}
@@ -1230,8 +1219,27 @@ struct TechmapPass : public Pass {
for (auto module : map->modules()) {
if (module->attributes.count(ID::techmap_celltype) && !module->attributes.at(ID::techmap_celltype).bits.empty()) {
char *p = strdup(module->attributes.at(ID::techmap_celltype).decode_string().c_str());
- for (char *q = strtok(p, " \t\r\n"); q; q = strtok(nullptr, " \t\r\n"))
- celltypeMap[RTLIL::escape_id(q)].insert(module->name);
+ for (char *q = strtok(p, " \t\r\n"); q; q = strtok(nullptr, " \t\r\n")) {
+ std::vector<std::string> queue;
+ queue.push_back(q);
+ while (!queue.empty()) {
+ std::string name = queue.back();
+ queue.pop_back();
+ auto pos = name.find('[');
+ if (pos == std::string::npos) {
+ // No further expansion.
+ celltypeMap[RTLIL::escape_id(name)].insert(module->name);
+ } else {
+ // Expand [] in this name.
+ auto epos = name.find(']', pos);
+ if (epos == std::string::npos)
+ log_error("Malformed techmap_celltype pattern %s\n", q);
+ for (size_t i = pos + 1; i < epos; i++) {
+ queue.push_back(name.substr(0, pos) + name[i] + name.substr(epos + 1, std::string::npos));
+ }
+ }
+ }
+ }
free(p);
} else {
IdString module_name = module->name.begins_with("\\$") ?
@@ -1239,8 +1247,15 @@ struct TechmapPass : public Pass {
celltypeMap[module_name].insert(module->name);
}
}
- for (auto &i : celltypeMap)
+ log_debug("Cell type mappings to use:\n");
+ for (auto &i : celltypeMap) {
i.second.sort(RTLIL::sort_by_id_str());
+ std::string maps = "";
+ for (auto &map : i.second)
+ maps += stringf(" %s", log_id(map));
+ log_debug(" %s:%s\n", log_id(i.first), maps.c_str());
+ }
+ log_debug("\n");
for (auto module : design->modules())
worker.module_queue.insert(module);
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 cc0b26bcc..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
@@ -19,6 +19,8 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
+#include "kernel/ffinit.h"
+#include "kernel/ff.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -57,158 +59,27 @@ struct ZinitPass : public Pass {
for (auto module : design->selected_modules())
{
SigMap sigmap(module);
- dict<SigBit, std::pair<State,SigBit>> initbits;
-
- for (auto wire : module->selected_wires())
- {
- if (wire->attributes.count(ID::init) == 0)
- continue;
-
- SigSpec wirebits = sigmap(wire);
- Const initval = wire->attributes.at(ID::init);
-
- for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++)
- {
- SigBit bit = wirebits[i];
- State val = initval[i];
-
- if (val != State::S0 && val != State::S1 && bit.wire != nullptr)
- continue;
-
- if (initbits.count(bit)) {
- if (initbits.at(bit).first != val)
- log_error("Conflicting init values for signal %s (%s = %s != %s).\n",
- log_signal(bit), log_signal(SigBit(wire, i)),
- log_signal(val), log_signal(initbits.at(bit).first));
- continue;
- }
-
- initbits[bit] = std::make_pair(val,SigBit(wire,i));
- }
- }
-
- 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_)
- };
+ FfInitVals initvals(&sigmap, module);
for (auto cell : module->selected_cells())
{
- if (!dff_types.count(cell->type))
+ if (!RTLIL::builtin_ff_cell_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)
- continue;
-
- Const initval;
-
- for (int i = 0; i < GetSize(sig_q); i++) {
- if (initbits.count(sig_q[i])) {
- const auto &d = initbits.at(sig_q[i]);
- initval.bits.push_back(d.first);
- const auto &b = d.second;
- b.wire->attributes.at(ID::init)[b.offset] = State::Sx;
- } else
- initval.bits.push_back(all_mode ? State::S0 : State::Sx);
- }
-
- Wire *initwire = module->addWire(NEW_ID, GetSize(initval));
- initwire->attributes[ID::init] = initval;
-
- 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]);
- initwire->attributes[ID::init][i] = State::S0;
- }
- else
- {
- module->connect(sig_q[i], SigSpec(initwire, i));
- }
+ 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 2d80e66e4..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
@@ -171,7 +171,7 @@ static void test_abcloop()
}
log("Found viable UUT after %d cycles:\n", create_cycles);
- Pass::call(design, "write_ilang");
+ Pass::call(design, "write_rtlil");
Pass::call(design, "abc");
log("\n");
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 bdb475d3b..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);
@@ -264,6 +306,10 @@ static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type,
cell->setPort(ID::Y, wire);
}
+ if (cell_type.in(ID($shiftx))) {
+ cell->parameters[ID::A_SIGNED] = false;
+ }
+
if (cell_type.in(ID($shl), ID($shr), ID($sshl), ID($sshr))) {
cell->parameters[ID::B_SIGNED] = false;
}
@@ -674,12 +720,12 @@ struct TestCellPass : public Pass {
log(" -s {positive_integer}\n");
log(" use this value as rng seed value (default = unix time).\n");
log("\n");
- log(" -f {ilang_file}\n");
- log(" don't generate circuits. instead load the specified ilang file.\n");
+ log(" -f {rtlil_file}\n");
+ log(" don't generate circuits. instead load the specified RTLIL file.\n");
log("\n");
log(" -w {filename_prefix}\n");
log(" don't test anything. just generate the circuits and write them\n");
- log(" to ilang files with the specified prefix\n");
+ log(" to RTLIL files with the specified prefix\n");
log("\n");
log(" -map {filename}\n");
log(" pass this option to techmap.\n");
@@ -720,7 +766,7 @@ struct TestCellPass : public Pass {
{
int num_iter = 100;
std::string techmap_cmd = "techmap -assert";
- std::string ilang_file, write_prefix;
+ std::string rtlil_file, write_prefix;
xorshift32_state = 0;
std::ofstream vlog_file;
bool muxdiv = false;
@@ -746,7 +792,7 @@ struct TestCellPass : public Pass {
continue;
}
if (args[argidx] == "-f" && argidx+1 < GetSize(args)) {
- ilang_file = args[++argidx];
+ rtlil_file = args[++argidx];
num_iter = 1;
continue;
}
@@ -851,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)] = "*";
}
@@ -906,10 +954,10 @@ struct TestCellPass : public Pass {
selected_cell_types.push_back(args[argidx]);
}
- if (!ilang_file.empty()) {
+ if (!rtlil_file.empty()) {
if (!selected_cell_types.empty())
log_cmd_error("Do not specify any cell types when using -f.\n");
- selected_cell_types.push_back(ID(ilang));
+ selected_cell_types.push_back(ID(rtlil));
}
if (selected_cell_types.empty())
@@ -921,12 +969,12 @@ struct TestCellPass : public Pass {
for (int i = 0; i < num_iter; i++)
{
RTLIL::Design *design = new RTLIL::Design;
- if (cell_type == ID(ilang))
- Frontend::frontend_call(design, NULL, std::string(), "ilang " + ilang_file);
+ if (cell_type == ID(rtlil))
+ Frontend::frontend_call(design, NULL, std::string(), "rtlil " + rtlil_file);
else
create_gold_module(design, cell_type, cell_types.at(cell_type), constmode, muxdiv);
if (!write_prefix.empty()) {
- Pass::call(design, stringf("write_ilang %s_%s_%05d.il", write_prefix.c_str(), cell_type.c_str()+1, i));
+ Pass::call(design, stringf("write_rtlil %s_%s_%05d.il", write_prefix.c_str(), cell_type.c_str()+1, i));
} else if (edges) {
Pass::call(design, "dump gold");
run_edges_test(design, verbose);
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 ddd9822b9..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
@@ -144,12 +144,12 @@ struct SynthAchronixPass : public ScriptPass {
run("opt -fast -mux_undef -undriven -fine -full");
run("memory_map");
run("opt -undriven -fine");
- run("dff2dffe -direct-match $_DFF_*");
run("opt -fine");
run("techmap -map +/techmap.v");
run("opt -full");
run("clean -purge");
run("setundef -undriven -zero");
+ run("dfflegalize -cell $_DFF_P_ x");
if (retime || help_mode)
run("abc -markgroups -dff -D 1", "(only if -retime)");
}
@@ -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/cells_map.v b/techlibs/anlogic/cells_map.v
index 0bcea9856..d9f264ab1 100644
--- a/techlibs/anlogic/cells_map.v
+++ b/techlibs/anlogic/cells_map.v
@@ -1,31 +1,17 @@
-module \$_DFF_N_ (input D, C, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'bx), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(1'b0)); endmodule
-module \$_DFF_P_ (input D, C, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'bx), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(1'b0)); endmodule
+module \$_DFFE_PN0P_ (input D, C, R, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("INV"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C) ,.ce(E), .sr(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+module \$_DFFE_PN1P_ (input D, C, R, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("SET"), .SRMUX("INV"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(E), .sr(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+module \$_DFFE_PP0P_ (input D, C, R, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(E), .sr(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+module \$_DFFE_PP1P_ (input D, C, R, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("SET"), .SRMUX("SR"), . SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(E), .sr(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
-module \$_DFFE_NN_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'bx), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(E), .sr(1'b0)); endmodule
-module \$_DFFE_NP_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'bx), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(E), .sr(1'b0)); endmodule
-module \$_DFFE_PN_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'bx), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(E), .sr(1'b0)); endmodule
-module \$_DFFE_PP_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'bx), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(E), .sr(1'b0)); endmodule
+module \$_SDFFE_PN0P_ (input D, C, R, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C) ,.ce(E), .sr(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+module \$_SDFFE_PN1P_ (input D, C, R, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("SET"), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(E), .sr(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+module \$_SDFFE_PP0P_ (input D, C, R, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(E), .sr(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+module \$_SDFFE_PP1P_ (input D, C, R, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("SET"), .SRMUX("SR"), . SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(E), .sr(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
-module \$_DFF_NN0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("INV"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule
-module \$_DFF_NN1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("INV"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule
-module \$_DFF_NP0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("SR"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule
-module \$_DFF_NP1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("SR"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule
-module \$_DFF_PN0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("INV"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C) , .ce(1'b1), .sr(R)); endmodule
-module \$_DFF_PN1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("INV"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule
-module \$_DFF_PP0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("SR"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule
-module \$_DFF_PP1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("SR"), . SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule
-
-module \$_DLATCH_N_ (E, D, Q);
- wire [1023:0] _TECHMAP_DO_ = "simplemap; opt";
- input E, D;
- output Q = !E ? D : Q;
-endmodule
-
-module \$_DLATCH_P_ (E, D, Q);
- wire [1023:0] _TECHMAP_DO_ = "simplemap; opt";
- input E, D;
- output Q = E ? D : Q;
-endmodule
+module \$_DLATCH_NN0_ (input D, R, E, output Q); AL_MAP_SEQ #(.DFFMODE("LATCH"), .REGSET("RESET"), .SRMUX("INV"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(E) ,.ce(1'b1), .sr(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+module \$_DLATCH_NN1_ (input D, R, E, output Q); AL_MAP_SEQ #(.DFFMODE("LATCH"), .REGSET("SET"), .SRMUX("INV"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(E), .ce(1'b1), .sr(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+module \$_DLATCH_NP0_ (input D, R, E, output Q); AL_MAP_SEQ #(.DFFMODE("LATCH"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(E), .ce(1'b1), .sr(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+module \$_DLATCH_NP1_ (input D, R, E, output Q); AL_MAP_SEQ #(.DFFMODE("LATCH"), .REGSET("SET"), .SRMUX("SR"), . SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(E), .ce(1'b1), .sr(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
`ifndef NO_LUT
module \$lut (A, Y);
diff --git a/techlibs/anlogic/cells_sim.v b/techlibs/anlogic/cells_sim.v
index 0fba43572..e8ecf4f03 100644
--- a/techlibs/anlogic/cells_sim.v
+++ b/techlibs/anlogic/cells_sim.v
@@ -10,9 +10,6 @@ module AL_MAP_SEQ (
parameter SRMUX = "SR"; //SR/INV
parameter SRMODE = "SYNC"; //SYNC/ASYNC
- wire clk_ce;
- assign clk_ce = ce ? clk : 1'b0;
-
wire srmux;
generate
case (SRMUX)
@@ -20,7 +17,7 @@ module AL_MAP_SEQ (
"INV": assign srmux = ~sr;
default: assign srmux = sr;
endcase
- endgenerate
+ endgenerate
wire regset;
generate
@@ -34,43 +31,45 @@ module AL_MAP_SEQ (
initial q = regset;
generate
- if (DFFMODE == "FF")
+ if (DFFMODE == "FF")
begin
- if (SRMODE == "ASYNC")
+ if (SRMODE == "ASYNC")
begin
- always @(posedge clk_ce, posedge srmux)
+ always @(posedge clk, posedge srmux)
if (srmux)
q <= regset;
- else
- q <= d;
- end
+ else if (ce)
+ q <= d;
+ end
else
begin
- always @(posedge clk_ce)
+ always @(posedge clk)
if (srmux)
q <= regset;
- else
- q <= d;
+ else if (ce)
+ q <= d;
end
end
else
begin
// DFFMODE == "LATCH"
- if (SRMODE == "ASYNC")
+ if (SRMODE == "ASYNC")
begin
- always @(clk_ce, srmux)
+ always @*
if (srmux)
q <= regset;
- else
- q <= d;
- end
+ else if (~clk & ce)
+ q <= d;
+ end
else
begin
- always @(clk_ce)
- if (srmux)
- q <= regset;
- else
- q <= d;
+ always @*
+ if (~clk) begin
+ if (srmux)
+ q <= regset;
+ else if (ce)
+ q <= d;
+ end
end
end
endgenerate
diff --git a/techlibs/anlogic/synth_anlogic.cc b/techlibs/anlogic/synth_anlogic.cc
index d7475df86..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");
@@ -182,8 +198,8 @@ struct SynthAnlogicPass : public ScriptPass
if (check_label("map_ffs"))
{
+ run("dfflegalize -cell $_DFFE_P??P_ r -cell $_SDFFE_P??P_ r -cell $_DLATCH_N??_ r");
run("techmap -D NO_LUT -map +/anlogic/cells_map.v");
- run("dffinit -strinit SET RESET -ff AL_MAP_SEQ q REGSET -noreinit");
run("opt_expr -mux_undef");
run("simplemap");
}
@@ -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_map.v b/techlibs/common/abc9_map.v
index 6ed90b5f5..b00e0e6a8 100644
--- a/techlibs/common/abc9_map.v
+++ b/techlibs/common/abc9_map.v
@@ -1,5 +1,5 @@
`ifdef DFF
-(* techmap_celltype = "$_DFF_N_ $_DFF_P_" *)
+(* techmap_celltype = "$_DFF_[PN]_" *)
module $_DFF_x_(input C, D, output Q);
parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
parameter _TECHMAP_CELLTYPE_ = "";
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/adff2dff.v b/techlibs/common/adff2dff.v
index eca0110eb..2e4357b64 100644
--- a/techlibs/common/adff2dff.v
+++ b/techlibs/common/adff2dff.v
@@ -11,7 +11,7 @@ module adff2dff (CLK, ARST, D, Q);
(* force_downto *)
output reg [WIDTH-1:0] Q;
(* force_downto *)
- wire reg [WIDTH-1:0] NEXT_Q;
+ reg [WIDTH-1:0] NEXT_Q;
wire [1023:0] _TECHMAP_DO_ = "proc;;";
diff --git a/techlibs/common/cmp2lcu.v b/techlibs/common/cmp2lcu.v
index a221727e7..4e62039e9 100644
--- a/techlibs/common/cmp2lcu.v
+++ b/techlibs/common/cmp2lcu.v
@@ -41,10 +41,7 @@ generate
wire [WIDTH-1:0] BB = {{(WIDTH-B_WIDTH){B_SIGNED ? B[B_WIDTH-1] : 1'b0}}, B};
// For $ge operation, start with the assumption that A and B are
// equal (propagating this equality if A and B turn out to be so)
- if (_TECHMAP_CELLTYPE_ == "$ge")
- localparam CI = 1'b1;
- else
- localparam CI = 1'b0;
+ localparam CI = _TECHMAP_CELLTYPE_ == "$ge";
$__CMP2LCU #(.AB_WIDTH(WIDTH), .AB_SIGNED(A_SIGNED && B_SIGNED), .LCU_WIDTH(1), .BUDGET(`LUT_WIDTH), .CI(CI))
_TECHMAP_REPLACE_ (.A(AA), .B(BB), .P(1'b1), .G(1'b0), .Y(Y));
end
@@ -81,12 +78,12 @@ generate
assign Y = CO[LCU_WIDTH-1];
end
else begin
- if (_TECHMAP_CONSTMSK_A_[AB_WIDTH-1:0] && _TECHMAP_CONSTMSK_B_[AB_WIDTH-1:0])
- localparam COST = 0;
- else if (_TECHMAP_CONSTMSK_A_[AB_WIDTH-1:0] || _TECHMAP_CONSTMSK_B_[AB_WIDTH-1:0])
- localparam COST = 1;
- else
- localparam COST = 2;
+ localparam COST =
+ _TECHMAP_CONSTMSK_A_[AB_WIDTH-1:0] && _TECHMAP_CONSTMSK_B_[AB_WIDTH-1:0]
+ ? 0
+ : (_TECHMAP_CONSTMSK_A_[AB_WIDTH-1:0] || _TECHMAP_CONSTMSK_B_[AB_WIDTH-1:0]
+ ? 1
+ : 2);
if (BUDGET < COST)
$__CMP2LCU #(.AB_WIDTH(AB_WIDTH), .AB_SIGNED(AB_SIGNED), .LCU_WIDTH(LCU_WIDTH+1), .BUDGET(`LUT_WIDTH), .CI(CI))
@@ -104,21 +101,21 @@ generate
// from MSB down, deferring to less significant bits if the
// MSBs are equal
assign GG = P[0] & (A[AB_WIDTH-1] & ~B[AB_WIDTH-1]);
+ (* force_downto *)
+ wire [LCU_WIDTH-1:0] P_, G_;
if (LCU_WIDTH == 1) begin
// Propagate only if all pairs are equal
// (inconclusive evidence to say A >= B)
- wire P_ = P[0] & PP;
+ assign P_ = P[0] & PP;
// Generate if any comparisons call for it
- wire G_ = G[0] | GG;
+ assign G_ = G[0] | GG;
end
else begin
// Propagate only if all pairs are equal
// (inconclusive evidence to say A >= B)
- (* force_downto *)
- wire [LCU_WIDTH-1:0] P_ = {P[LCU_WIDTH-1:1], P[0] & PP};
+ assign P_ = {P[LCU_WIDTH-1:1], P[0] & PP};
// Generate if any comparisons call for it
- (* force_downto *)
- wire [LCU_WIDTH-1:0] G_ = {G[LCU_WIDTH-1:1], G[0] | GG};
+ assign G_ = {G[LCU_WIDTH-1:1], G[0] | GG};
end
if (AB_WIDTH == 1)
$__CMP2LCU #(.AB_WIDTH(AB_WIDTH-1), .AB_SIGNED(1'b0), .LCU_WIDTH(LCU_WIDTH), .BUDGET(BUDGET-COST), .CI(CI))
diff --git a/techlibs/common/cmp2lut.v b/techlibs/common/cmp2lut.v
index ec8f98e8d..c753bd2f1 100644
--- a/techlibs/common/cmp2lut.v
+++ b/techlibs/common/cmp2lut.v
@@ -66,14 +66,12 @@ function automatic [(1 << `LUT_WIDTH)-1:0] gen_lut;
endfunction
generate
- if (_TECHMAP_CELLTYPE_ == "$lt")
- localparam operation = 0;
- if (_TECHMAP_CELLTYPE_ == "$le")
- localparam operation = 1;
- if (_TECHMAP_CELLTYPE_ == "$gt")
- localparam operation = 2;
- if (_TECHMAP_CELLTYPE_ == "$ge")
- localparam operation = 3;
+ localparam operation =
+ _TECHMAP_CELLTYPE_ == "$lt" ? 0 :
+ _TECHMAP_CELLTYPE_ == "$le" ? 1 :
+ _TECHMAP_CELLTYPE_ == "$gt" ? 2 :
+ _TECHMAP_CELLTYPE_ == "$ge" ? 3 :
+ -1;
if (A_WIDTH > `LUT_WIDTH || B_WIDTH > `LUT_WIDTH || Y_WIDTH != 1)
wire _TECHMAP_FAIL_ = 1;
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 bec47d01f..ca2b3c5cf 100644
--- a/techlibs/common/mul2dsp.v
+++ b/techlibs/common/mul2dsp.v
@@ -1,314 +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
- (* 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
- (* 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(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 partial_sum[i] = partial[i];
- else
- assign partial_sum[i] = (partial[i] << (* mul2dsp *) i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)) + (* mul2dsp *) 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(last_partial)
- );
- assign partial_sum[n] = (last_partial << (* mul2dsp *) n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)) + (* mul2dsp *) partial_sum[n-1];
- assign Y = 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
- (* 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
- (* 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(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 partial_sum[i] = partial[i];
- else
- assign partial_sum[i] = (partial[i] << (* mul2dsp *) i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + (* mul2dsp *) 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(last_partial)
- );
- assign partial_sum[n] = (last_partial << (* mul2dsp *) n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + (* mul2dsp *) partial_sum[n-1];
- assign Y = partial_sum[n];
- end
- else begin
- if (A_SIGNED)
- wire signed [`DSP_A_MAXWIDTH-1:0] Aext = $signed(A);
- else
- wire [`DSP_A_MAXWIDTH-1:0] Aext = A;
- if (B_SIGNED)
- wire signed [`DSP_B_MAXWIDTH-1:0] Bext = $signed(B);
- else
- wire [`DSP_B_MAXWIDTH-1:0] Bext = B;
-
- `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(Aext),
- .B(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 2660e6f15..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
@@ -237,7 +237,7 @@ endmodule
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
-//- $reduce_and (A, B, Y)
+//- $reduce_and (A, Y)
//-
//- An AND reduction. This corresponds to the Verilog unary prefix '&' operator.
//-
@@ -264,7 +264,7 @@ endmodule
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
-//- $reduce_or (A, B, Y)
+//- $reduce_or (A, Y)
//-
//- An OR reduction. This corresponds to the Verilog unary prefix '|' operator.
//-
@@ -291,7 +291,7 @@ endmodule
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
-//- $reduce_xor (A, B, Y)
+//- $reduce_xor (A, Y)
//-
//- A XOR reduction. This corresponds to the Verilog unary prefix '^' operator.
//-
@@ -318,7 +318,7 @@ endmodule
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
-//- $reduce_xnor (A, B, Y)
+//- $reduce_xnor (A, Y)
//-
//- A XNOR reduction. This corresponds to the Verilog unary prefix '~^' operator.
//-
@@ -345,7 +345,7 @@ endmodule
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
-//- $reduce_bool (A, B, Y)
+//- $reduce_bool (A, Y)
//-
//- An OR reduction. This cell type is used instead of $reduce_or when a signal is
//- implicitly converted to a boolean signal, e.g. for operands of '&&' and '||'.
@@ -480,10 +480,18 @@ input [B_WIDTH-1:0] B;
output [Y_WIDTH-1:0] Y;
generate
- if (B_SIGNED) begin:BLOCK1
- assign Y = $signed(B) < 0 ? A << -B : A >> B;
- end else begin:BLOCK2
- assign Y = A >> B;
+ if (A_SIGNED) begin:BLOCK1
+ if (B_SIGNED) begin:BLOCK2
+ assign Y = $signed(B) < 0 ? $signed(A) << -B : $signed(A) >> B;
+ end else begin:BLOCK3
+ assign Y = $signed(A) >> B;
+ end
+ end else begin:BLOCK4
+ if (B_SIGNED) begin:BLOCK5
+ assign Y = $signed(B) < 0 ? A << -B : A >> B;
+ end else begin:BLOCK6
+ assign Y = A >> B;
+ end
end
endgenerate
@@ -1284,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;
@@ -1310,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);
@@ -1318,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
@@ -1882,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;
@@ -1931,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;
@@ -2174,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);
@@ -2200,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);
@@ -2225,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 = "";
@@ -2312,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 b4c65e658..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
@@ -220,6 +220,9 @@ struct SynthPass : public ScriptPass
run("opt_expr");
run("opt_clean");
run("check");
+ run("opt -nodffe -nosdff");
+ if (!nofsm)
+ run("fsm" + fsm_opts, " (unless -nofsm)");
run("opt");
run("wreduce");
run("peepopt");
@@ -233,9 +236,6 @@ struct SynthPass : public ScriptPass
if (!noshare)
run("share", " (unless -noshare)");
run("opt");
- if (!nofsm)
- run("fsm" + fsm_opts, " (unless -nofsm)");
- run("opt -fast");
run("memory -nomap" + memory_opts);
run("opt_clean");
}
diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v
index 9607302b7..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
@@ -141,78 +141,48 @@ module _90_shift_shiftx (A, B, Y);
parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0;
localparam extbit = _TECHMAP_CELLTYPE_ == "$shift" ? 1'b0 : 1'bx;
+ wire a_padding = _TECHMAP_CELLTYPE_ == "$shiftx" ? extbit : (A_SIGNED ? A[A_WIDTH-1] : 1'b0);
- generate
-`ifndef NO_LSB_FIRST_SHIFT_SHIFTX
- // If $shift/$shiftx only shifts in units of Y_WIDTH
- // (a common pattern created by pmux2shiftx)
- // which is checked by ensuring that all that
- // the appropriate LSBs of B are constant zero,
- // then we can decompose LSB first instead of
- // MSB first
- localparam CLOG2_Y_WIDTH = $clog2(Y_WIDTH);
- if (B_WIDTH > CLOG2_Y_WIDTH+1 &&
- _TECHMAP_CONSTMSK_B_[CLOG2_Y_WIDTH-1:0] == {CLOG2_Y_WIDTH{1'b1}} &&
- _TECHMAP_CONSTVAL_B_[CLOG2_Y_WIDTH-1:0] == {CLOG2_Y_WIDTH{1'b0}}) begin
- // Halve the size of $shift/$shiftx by $mux-ing A according to
- // the LSB of B, after discarding the zeroed bits
- localparam Y_WIDTH2 = 2**CLOG2_Y_WIDTH;
- localparam entries = (A_WIDTH+Y_WIDTH-1)/Y_WIDTH2;
- localparam len = Y_WIDTH2 * ((entries+1)/2);
- wire [len-1:0] AA;
- wire [(A_WIDTH+Y_WIDTH2+Y_WIDTH-1)-1:0] Apad = {{(Y_WIDTH2+Y_WIDTH-1){extbit}}, A};
- genvar i;
- for (i = 0; i < A_WIDTH; i=i+Y_WIDTH2*2)
- assign AA[i/2 +: Y_WIDTH2] = B[CLOG2_Y_WIDTH] ? Apad[i+Y_WIDTH2 +: Y_WIDTH2] : Apad[i +: Y_WIDTH2];
- wire [B_WIDTH-2:0] BB = {B[B_WIDTH-1:CLOG2_Y_WIDTH+1], {CLOG2_Y_WIDTH{1'b0}}};
- if (_TECHMAP_CELLTYPE_ == "$shift")
- $shift #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(len), .B_WIDTH(B_WIDTH-1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(AA), .B(BB), .Y(Y));
- else
- $shiftx #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(len), .B_WIDTH(B_WIDTH-1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(AA), .B(BB), .Y(Y));
- end
- else
-`endif
- begin
- localparam BB_WIDTH = `MIN($clog2(`MAX(A_WIDTH, Y_WIDTH)) + (B_SIGNED ? 2 : 1), B_WIDTH);
- localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH) + (B_SIGNED ? 2**(BB_WIDTH-1) : 0);
+ localparam BB_WIDTH = `MIN($clog2(`MAX(A_WIDTH, Y_WIDTH)) + (B_SIGNED ? 2 : 1), B_WIDTH);
+ localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH) + (B_SIGNED ? 2**(BB_WIDTH-1) : 0);
- wire [1023:0] _TECHMAP_DO_00_ = "proc;;";
- wire [1023:0] _TECHMAP_DO_01_ = "CONSTMAP; opt_muxtree; opt_expr -mux_undef -mux_bool -fine;;;";
+ wire [1023:0] _TECHMAP_DO_00_ = "proc;;";
+ wire [1023:0] _TECHMAP_DO_01_ = "CONSTMAP; opt_muxtree; opt_expr -mux_undef -mux_bool -fine;;;";
- integer i;
- (* force_downto *)
- reg [WIDTH-1:0] buffer;
- reg overflow;
+ integer i;
+ (* force_downto *)
+ reg [WIDTH-1:0] buffer;
+ reg overflow;
- always @* begin
- overflow = 0;
+ always @* begin
+ overflow = 0;
+ buffer = {WIDTH{extbit}};
+ buffer[Y_WIDTH-1:0] = {Y_WIDTH{a_padding}};
+ buffer[A_WIDTH-1:0] = A;
+
+ if (B_WIDTH > BB_WIDTH) begin
+ if (B_SIGNED) begin
+ for (i = BB_WIDTH; i < B_WIDTH; i = i+1)
+ if (B[i] != B[BB_WIDTH-1])
+ overflow = 1;
+ end else
+ overflow = |B[B_WIDTH-1:BB_WIDTH];
+ if (overflow)
buffer = {WIDTH{extbit}};
- buffer[`MAX(A_WIDTH, Y_WIDTH)-1:0] = A;
-
- if (B_WIDTH > BB_WIDTH) begin
- if (B_SIGNED) begin
- for (i = BB_WIDTH; i < B_WIDTH; i = i+1)
- if (B[i] != B[BB_WIDTH-1])
- overflow = 1;
- end else
- overflow = |B[B_WIDTH-1:BB_WIDTH];
- if (overflow)
- buffer = {WIDTH{extbit}};
- end
-
- for (i = BB_WIDTH-1; i >= 0; i = i-1)
- if (B[i]) begin
- if (B_SIGNED && i == BB_WIDTH-1)
- buffer = {buffer, {2**i{extbit}}};
- else if (2**i < WIDTH)
- buffer = {{2**i{extbit}}, buffer[WIDTH-1 : 2**i]};
- else
- buffer = {WIDTH{extbit}};
- end
- end
- assign Y = buffer;
end
- endgenerate
+
+ if (B_SIGNED && B[BB_WIDTH-1])
+ buffer = {buffer, {2**(BB_WIDTH-1){extbit}}};
+
+ for (i = 0; i < (B_SIGNED ? BB_WIDTH-1 : BB_WIDTH); i = i+1)
+ if (B[i]) begin
+ if (2**i < WIDTH)
+ buffer = {{2**i{extbit}}, buffer[WIDTH-1 : 2**i]};
+ else
+ buffer = {WIDTH{extbit}};
+ end
+ end
+ assign Y = buffer;
endmodule
@@ -627,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/Makefile.inc b/techlibs/ecp5/Makefile.inc
index 9d564c78c..4c1bc23b5 100644
--- a/techlibs/ecp5/Makefile.inc
+++ b/techlibs/ecp5/Makefile.inc
@@ -1,6 +1,5 @@
-OBJS += techlibs/ecp5/synth_ecp5.o techlibs/ecp5/ecp5_ffinit.o \
- techlibs/ecp5/ecp5_gsr.o
+OBJS += techlibs/ecp5/synth_ecp5.o techlibs/ecp5/ecp5_gsr.o
GENFILES += techlibs/ecp5/bram_init_1_2_4.vh
GENFILES += techlibs/ecp5/bram_init_9_18_36.vh
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 80f497cc3..4944ece45 100644
--- a/techlibs/ecp5/cells_map.v
+++ b/techlibs/ecp5/cells_map.v
@@ -1,66 +1,100 @@
-module \$_DFF_N_ (input D, C, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
-module \$_DFF_P_ (input D, C, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
-
-module \$_DFFE_NN_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
-module \$_DFFE_PN_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
-
-module \$_DFFE_NP_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
-module \$_DFFE_PP_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
-
-module \$_DFF_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
-module \$_DFF_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
-module \$_DFF_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
-module \$_DFF_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
-
-module \$_DFF_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$_DFF_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$_DFF_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$_DFF_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
-
-module \$_SDFF_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
-module \$_SDFF_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
-module \$_SDFF_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
-module \$_SDFF_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
-
-module \$_SDFF_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$_SDFF_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$_SDFF_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$_SDFF_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
-
-module \$_DFFE_NN0P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
-module \$_DFFE_NN1P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
-module \$_DFFE_PN0P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
-module \$_DFFE_PN1P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
-
-module \$_DFFE_NP0P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$_DFFE_NP1P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$_DFFE_PP0P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$_DFFE_PP1P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
-
-module \$_SDFFE_NN0P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
-module \$_SDFFE_NN1P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
-module \$_SDFFE_PN0P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
-module \$_SDFFE_PN1P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
-
-module \$_SDFFE_NP0P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$_SDFFE_NP1P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$_SDFFE_PP0P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$_SDFFE_PP1P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); 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 \$_DFFSR_NNN_ (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_NNP_ (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_NPN_ (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_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_PNN_ (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
-module \$_DFFSR_PNP_ (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
-module \$_DFFSR_PPN_ (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
-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 \$_DFF_N_ (input D, C, output Q);
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
+ TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q));
+ else
+ TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q));
+ endgenerate
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
+endmodule
+
+module \$_DFF_P_ (input D, C, output Q);
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
+ TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q));
+ else
+ TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q));
+ endgenerate
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
+endmodule
+
+module \$_DFFE_NN_ (input D, C, E, output Q);
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
+ TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q));
+ else
+ TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q));
+ endgenerate
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
+endmodule
+
+module \$_DFFE_PN_ (input D, C, E, output Q);
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
+ TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q));
+ else
+ TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q));
+ endgenerate
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
+endmodule
+
+module \$_DFFE_NP_ (input D, C, E, output Q);
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
+ TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q));
+ else
+ TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q));
+ endgenerate
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
+endmodule
+
+module \$_DFFE_PP_ (input D, C, E, output Q);
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
+ TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q));
+ else
+ TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q));
+ endgenerate
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
+endmodule
+
+module \$_DFF_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+module \$_DFF_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+module \$_DFF_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+module \$_DFF_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+
+module \$_SDFF_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+module \$_SDFF_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+module \$_SDFF_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+module \$_SDFF_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+
+module \$_DFFE_NP0P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+module \$_DFFE_NP1P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+module \$_DFFE_PP0P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+module \$_DFFE_PP1P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+
+module \$_DFFE_NP0N_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+module \$_DFFE_NP1N_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+module \$_DFFE_PP0N_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+module \$_DFFE_PP1N_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
+
+module \$_SDFFE_NP0P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .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_NP1P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .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
+module \$_SDFFE_PP0P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .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_PP1P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .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
+
+module \$_SDFFE_NP0N_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("INV"), .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_NP1N_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("INV"), .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
+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
+
+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 \$_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_ffinit.cc b/techlibs/ecp5/ecp5_ffinit.cc
deleted file mode 100644
index 0ecc86388..000000000
--- a/techlibs/ecp5/ecp5_ffinit.cc
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * yosys -- Yosys Open SYnthesis Suite
- *
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- * Copyright (C) 2018-19 David Shah <david@symbioticeda.com>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#include "kernel/yosys.h"
-#include "kernel/sigtools.h"
-
-USING_YOSYS_NAMESPACE
-PRIVATE_NAMESPACE_BEGIN
-
-struct Ecp5FfinitPass : public Pass {
- Ecp5FfinitPass() : Pass("ecp5_ffinit", "ECP5: handle FF init values") { }
- void help() override
- {
- // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
- log("\n");
- log(" ecp5_ffinit [options] [selection]\n");
- log("\n");
- log("Remove init values for FF output signals when equal to reset value.\n");
- log("If reset is not used, set the reset value to the init value, otherwise\n");
- log("unmap out the reset (if not an async reset).\n");
- }
- void execute(std::vector<std::string> args, RTLIL::Design *design) override
- {
- log_header(design, "Executing ECP5_FFINIT pass (implement FF init values).\n");
-
- size_t argidx;
- for (argidx = 1; argidx < args.size(); argidx++)
- {
- // if (args[argidx] == "-singleton") {
- // singleton_mode = true;
- // continue;
- // }
- break;
- }
- extra_args(args, argidx, design);
-
- for (auto module : design->selected_modules())
- {
- log("Handling FF init values in %s.\n", log_id(module));
-
- SigMap sigmap(module);
- pool<Wire*> init_wires;
- dict<SigBit, State> initbits;
- dict<SigBit, SigBit> initbit_to_wire;
- pool<SigBit> handled_initbits;
-
- for (auto wire : module->selected_wires())
- {
- if (wire->attributes.count(ID::init) == 0)
- continue;
-
- SigSpec wirebits = sigmap(wire);
- Const initval = wire->attributes.at(ID::init);
- init_wires.insert(wire);
-
- for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++)
- {
- SigBit bit = wirebits[i];
- State val = initval[i];
-
- if (val != State::S0 && val != State::S1)
- continue;
-
- if (initbits.count(bit)) {
- if (initbits.at(bit) != val) {
- log_warning("Conflicting init values for signal %s (%s = %s, %s = %s).\n",
- log_signal(bit), log_signal(SigBit(wire, i)), log_signal(val),
- log_signal(initbit_to_wire[bit]), log_signal(initbits.at(bit)));
- initbits.at(bit) = State::Sx;
- }
- continue;
- }
-
- initbits[bit] = val;
- initbit_to_wire[bit] = SigBit(wire, i);
- }
- }
- for (auto cell : module->selected_cells())
- {
- if (cell->type != ID(TRELLIS_FF))
- continue;
- SigSpec sig_d = cell->getPort(ID(DI));
- SigSpec sig_q = cell->getPort(ID::Q);
- SigSpec sig_lsr = cell->getPort(ID(LSR));
-
- if (GetSize(sig_d) < 1 || GetSize(sig_q) < 1)
- continue;
-
- SigBit bit_d = sigmap(sig_d[0]);
- SigBit bit_q = sigmap(sig_q[0]);
-
- std::string regset = cell->getParam(ID(REGSET)).decode_string();
- State resetState;
- if (regset == "SET")
- resetState = State::S1;
- else if (regset == "RESET")
- resetState = State::S0;
- else
- log_error("FF cell %s has illegal REGSET value %s.\n",
- log_id(cell), regset.c_str());
-
- if (!initbits.count(bit_q))
- continue;
-
- State val = initbits.at(bit_q);
-
- if (val == State::Sx)
- continue;
-
- log("FF init value for cell %s (%s): %s = %c\n", log_id(cell), log_id(cell->type),
- log_signal(bit_q), val != State::S0 ? '1' : '0');
- // Initval is the same as the reset state. Matches hardware, nowt more to do
- if (val == resetState) {
- handled_initbits.insert(bit_q);
- continue;
- }
-
- if (GetSize(sig_lsr) >= 1 && sig_lsr[0] != State::S0) {
- std::string srmode = cell->getParam(ID(SRMODE)).decode_string();
- if (srmode == "ASYNC") {
- log("Async reset value %c for FF cell %s inconsistent with init value %c.\n",
- resetState != State::S0 ? '1' : '0', log_id(cell), val != State::S0 ? '1' : '0');
- } else {
- SigBit bit_lsr = sigmap(sig_lsr[0]);
- Wire *new_bit_d = module->addWire(NEW_ID);
- if (resetState == State::S0) {
- module->addAndnotGate(NEW_ID, bit_d, bit_lsr, new_bit_d);
- } else {
- module->addOrGate(NEW_ID, bit_d, bit_lsr, new_bit_d);
- }
-
- cell->setPort(ID(DI), new_bit_d);
- cell->setPort(ID(LSR), State::S0);
-
- if(cell->hasPort(ID(CE))) {
- std::string cemux = cell->getParam(ID(CEMUX)).decode_string();
- SigSpec sig_ce = cell->getPort(ID(CE));
- if (GetSize(sig_ce) >= 1) {
- SigBit bit_ce = sigmap(sig_ce[0]);
- Wire *new_bit_ce = module->addWire(NEW_ID);
- if (cemux == "INV")
- module->addAndnotGate(NEW_ID, bit_ce, bit_lsr, new_bit_ce);
- else
- module->addOrGate(NEW_ID, bit_ce, bit_lsr, new_bit_ce);
- cell->setPort(ID(CE), new_bit_ce);
- }
- }
- cell->setParam(ID(REGSET), val != State::S0 ? Const("SET") : Const("RESET"));
- handled_initbits.insert(bit_q);
- }
- } else {
- cell->setParam(ID(REGSET), val != State::S0 ? Const("SET") : Const("RESET"));
- handled_initbits.insert(bit_q);
- }
- }
-
- for (auto wire : init_wires)
- {
- if (wire->attributes.count(ID::init) == 0)
- continue;
-
- SigSpec wirebits = sigmap(wire);
- Const &initval = wire->attributes.at(ID::init);
- bool remove_attribute = true;
-
- for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++) {
- if (handled_initbits.count(wirebits[i]))
- initval[i] = State::Sx;
- else if (initval[i] != State::Sx)
- remove_attribute = false;
- }
-
- if (remove_attribute)
- wire->attributes.erase(ID::init);
- }
- }
- }
-} Ecp5FfinitPass;
-
-PRIVATE_NAMESPACE_END
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 0874b954a..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");
@@ -257,6 +257,8 @@ struct SynthEcp5Pass : public ScriptPass
run("opt_expr");
run("opt_clean");
run("check");
+ run("opt -nodffe -nosdff");
+ run("fsm");
run("opt");
run("wreduce");
run("peepopt");
@@ -271,8 +273,6 @@ struct SynthEcp5Pass : public ScriptPass
}
run("alumacc");
run("opt");
- run("fsm");
- run("opt -fast");
run("memory -nomap");
run("opt_clean");
}
@@ -311,16 +311,26 @@ struct SynthEcp5Pass : public ScriptPass
if (check_label("map_ffs"))
{
- run("dff2dffs");
run("opt_clean");
- if (!nodffe)
- run("dff2dffe -direct-match $_DFF_* -direct-match $_SDFF_*");
+ std::string dfflegalize_args = " -cell $_DFF_?_ 01 -cell $_DFF_?P?_ r -cell $_SDFF_?P?_ r";
+ if (help_mode) {
+ dfflegalize_args += " [-cell $_DFFE_??_ 01 -cell $_DFFE_?P??_ r -cell $_SDFFE_?P??_ r]";
+ } else if (!nodffe) {
+ dfflegalize_args += " -cell $_DFFE_??_ 01 -cell $_DFFE_?P??_ r -cell $_SDFFE_?P??_ r";
+ }
+ if (help_mode) {
+ dfflegalize_args += " [-cell $_ALDFF_?P_ x -cell $_ALDFFE_?P?_ x] [-cell $_DLATCH_?_ x]";
+ } else if (asyncprld) {
+ dfflegalize_args += " -cell $_ALDFF_?P_ x -cell $_ALDFFE_?P?_ x";
+ } else {
+ dfflegalize_args += " -cell $_DLATCH_?_ x";
+ }
+ 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_ffinit");
run("ecp5_gsr");
run("attrmvcp -copy -attr syn_useioff");
run("opt_clean");
@@ -376,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/Makefile.inc b/techlibs/efinix/Makefile.inc
index 69665982c..2a3a953e3 100644
--- a/techlibs/efinix/Makefile.inc
+++ b/techlibs/efinix/Makefile.inc
@@ -1,10 +1,10 @@
OBJS += techlibs/efinix/synth_efinix.o
-OBJS += techlibs/efinix/efinix_gbuf.o
OBJS += techlibs/efinix/efinix_fixcarry.o
$(eval $(call add_share_file,share/efinix,techlibs/efinix/cells_map.v))
$(eval $(call add_share_file,share/efinix,techlibs/efinix/arith_map.v))
$(eval $(call add_share_file,share/efinix,techlibs/efinix/cells_sim.v))
$(eval $(call add_share_file,share/efinix,techlibs/efinix/brams_map.v))
+$(eval $(call add_share_file,share/efinix,techlibs/efinix/gbuf_map.v))
$(eval $(call add_share_file,share/efinix,techlibs/efinix/brams.txt))
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/cells_map.v b/techlibs/efinix/cells_map.v
index 1090f8b27..6f6271da2 100644
--- a/techlibs/efinix/cells_map.v
+++ b/techlibs/efinix/cells_map.v
@@ -1,21 +1,59 @@
-module \$_DFF_N_ (input D, C, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(1'b0), .Q(Q)); endmodule
-module \$_DFF_P_ (input D, C, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(1'b0), .Q(Q)); endmodule
+(* techmap_celltype = "$_DFFE_[PN][PN][01][PN]_" *)
+module \$_DFFE_xxxx_ (input D, C, R, E, output Q);
-module \$_DFFE_NN_ (input D, C, E, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b0), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(E), .CLK(C), .SR(1'b0), .Q(Q)); endmodule
-module \$_DFFE_NP_ (input D, C, E, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(E), .CLK(C), .SR(1'b0), .Q(Q)); endmodule
+ parameter _TECHMAP_CELLTYPE_ = "";
-module \$_DFFE_PN_ (input D, C, E, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b0), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(E), .CLK(C), .SR(1'b0), .Q(Q)); endmodule
-module \$_DFFE_PP_ (input D, C, E, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(E), .CLK(C), .SR(1'b0), .Q(Q)); endmodule
+ EFX_FF #(
+ .CLK_POLARITY(_TECHMAP_CELLTYPE_[39:32] == "P"),
+ .CE_POLARITY(_TECHMAP_CELLTYPE_[15:8] == "P"),
+ .SR_POLARITY(_TECHMAP_CELLTYPE_[31:24] == "P"),
+ .D_POLARITY(1'b1),
+ .SR_SYNC(1'b0),
+ .SR_VALUE(_TECHMAP_CELLTYPE_[23:16] == "1"),
+ .SR_SYNC_PRIORITY(1'b1)
+ ) _TECHMAP_REPLACE_ (.D(D), .CE(E), .CLK(C), .SR(R), .Q(Q));
-module \$_DFF_NN0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
-module \$_DFF_NN1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b1), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
-module \$_DFF_PN0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
-module \$_DFF_PN1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b1), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
-module \$_DFF_NP0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
-module \$_DFF_NP1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b1), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
-module \$_DFF_PP0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
-module \$_DFF_PP1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b1), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule
+endmodule
+
+(* techmap_celltype = "$_SDFFE_[PN][PN][01][PN]_" *)
+module \$_SDFFE_xxxx_ (input D, C, R, E, output Q);
+
+ parameter _TECHMAP_CELLTYPE_ = "";
+
+ EFX_FF #(
+ .CLK_POLARITY(_TECHMAP_CELLTYPE_[39:32] == "P"),
+ .CE_POLARITY(_TECHMAP_CELLTYPE_[15:8] == "P"),
+ .SR_POLARITY(_TECHMAP_CELLTYPE_[31:24] == "P"),
+ .D_POLARITY(1'b1),
+ .SR_SYNC(1'b1),
+ .SR_VALUE(_TECHMAP_CELLTYPE_[23:16] == "1"),
+ .SR_SYNC_PRIORITY(1'b1)
+ ) _TECHMAP_REPLACE_ (.D(D), .CE(E), .CLK(C), .SR(R), .Q(Q));
+
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
+
+endmodule
+
+(* techmap_celltype = "$_SDFFCE_[PN][PN][01][PN]_" *)
+module \$_SDFFCE_xxxx_ (input D, C, R, E, output Q);
+
+ parameter _TECHMAP_CELLTYPE_ = "";
+
+ EFX_FF #(
+ .CLK_POLARITY(_TECHMAP_CELLTYPE_[39:32] == "P"),
+ .CE_POLARITY(_TECHMAP_CELLTYPE_[15:8] == "P"),
+ .SR_POLARITY(_TECHMAP_CELLTYPE_[31:24] == "P"),
+ .D_POLARITY(1'b1),
+ .SR_SYNC(1'b1),
+ .SR_VALUE(_TECHMAP_CELLTYPE_[23:16] == "1"),
+ .SR_SYNC_PRIORITY(1'b0)
+ ) _TECHMAP_REPLACE_ (.D(D), .CE(E), .CLK(C), .SR(R), .Q(Q));
+
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
+
+endmodule
module \$_DLATCH_N_ (E, D, Q);
wire [1023:0] _TECHMAP_DO_ = "simplemap; opt";
diff --git a/techlibs/efinix/cells_sim.v b/techlibs/efinix/cells_sim.v
index a74d1c571..22c7bc776 100644
--- a/techlibs/efinix/cells_sim.v
+++ b/techlibs/efinix/cells_sim.v
@@ -36,6 +36,7 @@ module EFX_FF(
output reg Q,
input D,
input CE,
+ (* clkbuf_sink *)
input CLK,
input SR
);
@@ -100,6 +101,7 @@ endmodule
module EFX_GBUFCE(
input CE,
input I,
+ (* clkbuf_driver *)
output O
);
parameter CE_POLARITY = 1'b1;
@@ -115,11 +117,13 @@ module EFX_RAM_5K(
input [WRITE_WIDTH-1:0] WDATA,
input [WRITE_ADDR_WIDTH-1:0] WADDR,
input WE,
+ (* clkbuf_sink *)
input WCLK,
input WCLKE,
output [READ_WIDTH-1:0] RDATA,
input [READ_ADDR_WIDTH-1:0] RADDR,
input RE,
+ (* clkbuf_sink *)
input RCLK
);
parameter READ_WIDTH = 20;
@@ -172,4 +176,4 @@ module EFX_RAM_5K(
(WRITE_WIDTH == 10) ? 9 : // 512x10
(WRITE_WIDTH == 5) ? 10 : -1; // 1024x5
-endmodule \ No newline at end of file
+endmodule
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/efinix_gbuf.cc b/techlibs/efinix/efinix_gbuf.cc
deleted file mode 100644
index ae191359a..000000000
--- a/techlibs/efinix/efinix_gbuf.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * yosys -- Yosys Open SYnthesis Suite
- *
- * Copyright (C) 2019 Miodrag Milanovic <miodrag@symbioticeda.com>
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#include "kernel/yosys.h"
-#include "kernel/sigtools.h"
-
-USING_YOSYS_NAMESPACE
-PRIVATE_NAMESPACE_BEGIN
-
-static void handle_gbufs(Module *module)
-{
- SigMap sigmap(module);
-
- pool<SigBit> clk_bits;
- dict<SigBit, SigBit> rewrite_bits;
- vector<pair<Cell*, SigBit>> pad_bits;
-
- for (auto cell : module->cells())
- {
- if (cell->type == ID(EFX_FF)) {
- for (auto bit : sigmap(cell->getPort(ID::CLK)))
- clk_bits.insert(bit);
- }
- if (cell->type == ID(EFX_RAM_5K)) {
- for (auto bit : sigmap(cell->getPort(ID(RCLK))))
- clk_bits.insert(bit);
- for (auto bit : sigmap(cell->getPort(ID(WCLK))))
- clk_bits.insert(bit);
- }
- }
-
- for (auto wire : vector<Wire*>(module->wires()))
- {
- if (!wire->port_input)
- continue;
-
- for (int index = 0; index < GetSize(wire); index++)
- {
- SigBit bit(wire, index);
- SigBit canonical_bit = sigmap(bit);
-
- if (!clk_bits.count(canonical_bit))
- continue;
-
- Cell *c = module->addCell(NEW_ID, ID(EFX_GBUFCE));
- SigBit new_bit = module->addWire(NEW_ID);
- c->setParam(ID(CE_POLARITY), State::S1);
- c->setPort(ID::O, new_bit);
- c->setPort(ID(CE), State::S1);
- pad_bits.push_back(make_pair(c, bit));
- rewrite_bits[canonical_bit] = new_bit;
-
- log("Added %s cell %s for port bit %s.\n", log_id(c->type), log_id(c), log_signal(bit));
- }
- }
-
- auto rewrite_function = [&](SigSpec &s) {
- for (auto &bit : s) {
- SigBit canonical_bit = sigmap(bit);
- if (rewrite_bits.count(canonical_bit))
- bit = rewrite_bits.at(canonical_bit);
- }
- };
-
- module->rewrite_sigspecs(rewrite_function);
-
- for (auto &it : pad_bits)
- it.first->setPort(ID::I, it.second);
-}
-
-struct EfinixGbufPass : public Pass {
- EfinixGbufPass() : Pass("efinix_gbuf", "Efinix: insert global clock buffers") { }
- void help() override
- {
- // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
- log("\n");
- log(" efinix_gbuf [options] [selection]\n");
- log("\n");
- log("Add Efinix global clock buffers to top module as needed.\n");
- log("\n");
- }
- void execute(std::vector<std::string> args, RTLIL::Design *design) override
- {
- log_header(design, "Executing efinix_gbuf pass (insert global clock buffers).\n");
-
- size_t argidx;
- for (argidx = 1; argidx < args.size(); argidx++)
- {
- break;
- }
- extra_args(args, argidx, design);
-
- Module *module = design->top_module();
-
- if (module == nullptr)
- log_cmd_error("No top module found.\n");
-
- handle_gbufs(module);
- }
-} EfinixGbufPass;
-
-PRIVATE_NAMESPACE_END
diff --git a/techlibs/efinix/gbuf_map.v b/techlibs/efinix/gbuf_map.v
new file mode 100644
index 000000000..43e0c9ac3
--- /dev/null
+++ b/techlibs/efinix/gbuf_map.v
@@ -0,0 +1,3 @@
+module \$__EFX_GBUF (input I, output O);
+ EFX_GBUFCE #(.CE_POLARITY(1'b1)) _TECHMAP_REPLACE_ (.I(I), .O(O), .CE(1'b1));
+endmodule
diff --git a/techlibs/efinix/synth_efinix.cc b/techlibs/efinix/synth_efinix.cc
index 6ca44eed1..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
@@ -182,8 +182,8 @@ struct SynthEfinixPass : public ScriptPass
if (check_label("map_ffs"))
{
+ run("dfflegalize -cell $_DFFE_????_ 0 -cell $_SDFFE_????_ 0 -cell $_SDFFCE_????_ 0 -cell $_DLATCH_?_ x");
run("techmap -D NO_LUT -map +/efinix/cells_map.v");
- run("dffinit -strinit SET RESET -ff AL_MAP_SEQ q REGSET -noreinit");
run("opt_expr -mux_undef");
run("simplemap");
}
@@ -202,7 +202,8 @@ struct SynthEfinixPass : public ScriptPass
if (check_label("map_gbuf"))
{
- run("efinix_gbuf");
+ run("clkbufmap -buf $__EFX_GBUF O:I");
+ run("techmap -map +/efinix/gbuf_map.v");
run("efinix_fixcarry");
run("clean");
}
@@ -212,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/intel/arria10gx/cells_arith.v b/techlibs/gatemate/arith_map.v
index 6a52a0f95..a3ab9c186 100644
--- a/techlibs/intel/arria10gx/cells_arith.v
+++ b/techlibs/gatemate/arith_map.v
@@ -1,71 +1,69 @@
-/*
- * yosys -- Yosys Open SYnthesis Suite
- *
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-// NOTE: This is still WIP.
-(* techmap_celltype = "$alu" *)
-module _80_altera_a10gx_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;
- //output [Y_WIDTH-1:0] CO;
- output CO;
-
- wire _TECHMAP_FAIL_ = Y_WIDTH <= 4;
-
- (* 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;
- //wire [Y_WIDTH:0] C = {CO, CI};
- wire [Y_WIDTH+1:0] COx;
- wire [Y_WIDTH+1:0] C = {COx, CI};
-
- /* Start implementation */
- (* keep *) fiftyfivenm_lcell_comb #(.lut_mask(16'b0000_0000_1010_1010), .sum_lutc_input("cin")) carry_start (.cout(COx[0]), .dataa(C[0]), .datab(1'b1), .datac(1'b1), .datad(1'b1));
-
- genvar i;
- generate for (i = 0; i < Y_WIDTH; i = i + 1) begin: slice
- if(i==Y_WIDTH-1) begin
- (* keep *) fiftyfivenm_lcell_comb #(.lut_mask(16'b1111_0000_1110_0000), .sum_lutc_input("cin")) carry_end (.combout(COx[Y_WIDTH]), .dataa(1'b1), .datab(1'b1), .datac(1'b1), .datad(1'b1), .cin(C[Y_WIDTH]));
- assign CO = COx[Y_WIDTH];
- end
- else
- fiftyfivenm_lcell_comb #(.lut_mask(16'b1001_0110_1110_1000), .sum_lutc_input("cin")) arith_cell (.combout(Y[i]), .cout(COx[i+1]), .dataa(AA[i]), .datab(BB[i]), .datac(1'b1), .datad(1'b1), .cin(C[i+1]));
- end: slice
- endgenerate
- /* End implementation */
- assign X = AA ^ BB;
-
-endmodule
+/*
+ * 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/Makefile.inc b/techlibs/gowin/Makefile.inc
index 0756e3bcf..e6a6be970 100644
--- a/techlibs/gowin/Makefile.inc
+++ b/techlibs/gowin/Makefile.inc
@@ -1,6 +1,5 @@
OBJS += techlibs/gowin/synth_gowin.o
-OBJS += techlibs/gowin/determine_init.o
GENFILES += techlibs/gowin/bram_init_16.vh
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 5460274ca..5978a00d0 100644
--- a/techlibs/gowin/cells_map.v
+++ b/techlibs/gowin/cells_map.v
@@ -3,231 +3,125 @@
//value regardless. The parameter is ignored.
// DFFN D Flip-Flop with Negative-Edge Clock
-module \$_DFF_N_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, output Q);
- generate
- if (_TECHMAP_WIREINIT_Q_ === 1'b1)
- DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(1'b0));
- else
- DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C));
- endgenerate
+module \$_DFF_N_ (input D, C, output Q);
+ DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C));
wire _TECHMAP_REMOVEINIT_Q_ = 1;
endmodule
// DFF D Flip-Flop
-module \$_DFF_P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, output Q);
- generate
- if (_TECHMAP_WIREINIT_Q_ === 1'b1)
- DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(1'b0));
- else
- DFF _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C));
- endgenerate
+module \$_DFF_P_ (input D, C, output Q);
+ DFF _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C));
wire _TECHMAP_REMOVEINIT_Q_ = 1;
endmodule
// DFFE D Flip-Flop with Clock Enable
-module \$_DFFE_PP_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, E, output Q);
- generate
- if (_TECHMAP_WIREINIT_Q_ === 1'b1)
- DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E), .SET(1'b0));
- else
- DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E));
- endgenerate
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-
-module \$_DFFE_PN_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, E, output Q);
- generate
- if (_TECHMAP_WIREINIT_Q_ === 1'b1)
- DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E), .SET(1'b0));
- else
- DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E));
- endgenerate
+module \$_DFFE_PP_ (input D, C, E, output Q);
+ DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E));
wire _TECHMAP_REMOVEINIT_Q_ = 1;
endmodule
// DFFNE D Flip-Flop with Negative-Edge Clock and Clock Enable
-module \$_DFFE_NP_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, E, output Q);
- generate
- if (_TECHMAP_WIREINIT_Q_ === 1'b1)
- DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E), .SET(1'b0));
- else
- DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E));
- endgenerate
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-
-module \$_DFFE_NN_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, E, output Q);
- generate
- if (_TECHMAP_WIREINIT_Q_ === 1'b1)
- DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E), .SET(1'b0));
- else
- DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E));
- endgenerate
+module \$_DFFE_NP_ (input D, C, E, output Q);
+ DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E));
wire _TECHMAP_REMOVEINIT_Q_ = 1;
endmodule
// DFFR D Flip-Flop with Synchronous Reset
-module \$_SDFF_PN0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
- DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
-endmodule
-
-module \$_SDFF_PP0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+module \$_SDFF_PP0_ (input D, C, R, output Q);
DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
endmodule
// DFFNR D Flip-Flop with Negative-Edge Clock and Synchronous Reset
-module \$_SDFF_NN0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
- DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
-endmodule
-module \$_SDFF_NP0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+module \$_SDFF_NP0_ (input D, C, R, output Q);
DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
endmodule
// DFFRE D Flip-Flop with Clock Enable and Synchronous Reset
-module \$_SDFFE_PN0P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
- DFFRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R), .CE(E));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
-endmodule
-module \$_SDFFE_PP0P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+module \$_SDFFE_PP0P_ (input D, C, R, E, output Q);
DFFRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R), .CE(E));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
endmodule
// DFFNRE D Flip-Flop with Negative-Edge Clock,Clock Enable, and Synchronous Reset
-module \$_SDFFE_NN0P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
- DFFNRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R), .CE(E));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
-endmodule
-module \$_SDFFE_NP0P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+module \$_SDFFE_NP0P_ (input D, C, R, E, output Q);
DFFNRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R), .CE(E));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
endmodule
// DFFS D Flip-Flop with Synchronous Set
-module \$_SDFF_PN1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
- DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
-endmodule
-module \$_SDFF_PP1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+module \$_SDFF_PP1_ (input D, C, R, output Q);
DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
endmodule
// DFFNS D Flip-Flop with Negative-Edge Clock and Synchronous Set
-module \$_SDFF_NN1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
- DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
-endmodule
-module \$_SDFF_NP1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+module \$_SDFF_NP1_ (input D, C, R, output Q);
DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
endmodule
// DFFSE D Flip-Flop with Clock Enable and Synchronous Set
-module \$_SDFFE_PN1P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
- DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R), .CE(E));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
-endmodule
-module \$_SDFFE_PP1P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+module \$_SDFFE_PP1P_ (input D, C, R, E, output Q);
DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R), .CE(E));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
endmodule
// DFFNSE D Flip-Flop with Negative-Edge Clock,Clock Enable,and Synchronous Set
-module \$_SDFFE_NN1P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
- DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R), .CE(E));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
-endmodule
-module \$_SDFFE_NP1P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+module \$_SDFFE_NP1P_ (input D, C, R, E, output Q);
DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R), .CE(E));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
endmodule
// DFFP D Flip-Flop with Asynchronous Preset
-module \$_DFF_PP1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+module \$_DFF_PP1_ (input D, C, R, output Q);
DFFP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
-endmodule
-module \$_DFF_PN1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
- DFFP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
endmodule
// DFFNP D Flip-Flop with Negative-Edge Clock and Asynchronous Preset
-module \$_DFF_NP1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+module \$_DFF_NP1_ (input D, C, R, output Q);
DFFNP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
-endmodule
-module \$_DFF_NN1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
- DFFNP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
endmodule
// DFFC D Flip-Flop with Asynchronous Clear
-module \$_DFF_PP0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+module \$_DFF_PP0_ (input D, C, R, output Q);
DFFC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
-endmodule
-module \$_DFF_PN0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
- DFFC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
endmodule
// DFFNC D Flip-Flop with Negative-Edge Clock and Asynchronous Clear
-module \$_DFF_NP0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+module \$_DFF_NP0_ (input D, C, R, output Q);
DFFNC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
-endmodule
-module \$_DFF_NN0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
- DFFNC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
endmodule
// DFFPE D Flip-Flop with Clock Enable and Asynchronous Preset
-module \$_DFFE_PP1P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+module \$_DFFE_PP1P_ (input D, C, R, E, output Q);
DFFPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R), .CE(E));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
-endmodule
-module \$_DFFE_PN1P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
- DFFPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R), .CE(E));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
endmodule
// DFFNPE D Flip-Flop with Negative-Edge Clock,Clock Enable, and Asynchronous Preset
-module \$_DFFE_NP1P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+module \$_DFFE_NP1P_ (input D, C, R, E, output Q);
DFFNPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R), .CE(E));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
-endmodule
-module \$_DFFE_NN1P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
- DFFNPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R), .CE(E));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
endmodule
// DFFCE D Flip-Flop with Clock Enable and Asynchronous Clear
-module \$_DFFE_PP0P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+module \$_DFFE_PP0P_ (input D, C, R, E, output Q);
DFFCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R), .CE(E));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
-endmodule
-module \$_DFFE_PN0P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
- DFFCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R), .CE(E));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
endmodule
// DFFNCE D Flip-Flop with Negative-Edge Clock,Clock Enable and Asynchronous Clear
-module \$_DFFE_NP0P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+module \$_DFFE_NP0P_ (input D, C, R, E, output Q);
DFFNCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R), .CE(E));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
-endmodule
-module \$_DFFE_NN0P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
- DFFNCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R), .CE(E));
- wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+ 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 a67855dab..bb4b9e5c5 100644
--- a/techlibs/gowin/cells_sim.v
+++ b/techlibs/gowin/cells_sim.v
@@ -1,33 +1,112 @@
+(* abc9_lut=1 *)
module LUT1(output F, input I0);
parameter [1:0] INIT = 0;
+ specify
+ (I0 => F) = (555, 902);
+ endspecify
assign F = I0 ? INIT[1] : INIT[0];
endmodule
+(* abc9_lut=1 *)
module LUT2(output F, input I0, I1);
parameter [3:0] INIT = 0;
+ specify
+ (I0 => F) = (867, 1184);
+ (I1 => F) = (555, 902);
+ endspecify
wire [ 1: 0] s1 = I1 ? INIT[ 3: 2] : INIT[ 1: 0];
assign F = I0 ? s1[1] : s1[0];
endmodule
+(* abc9_lut=1 *)
module LUT3(output F, input I0, I1, I2);
parameter [7:0] INIT = 0;
+ specify
+ (I0 => F) = (1054, 1486);
+ (I1 => F) = (867, 1184);
+ (I2 => F) = (555, 902);
+ endspecify
wire [ 3: 0] s2 = I2 ? INIT[ 7: 4] : INIT[ 3: 0];
wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
assign F = I0 ? s1[1] : s1[0];
endmodule
+(* abc9_lut=1 *)
module LUT4(output F, input I0, I1, I2, I3);
parameter [15:0] INIT = 0;
+ specify
+ (I0 => F) = (1054, 1486);
+ (I1 => F) = (1053, 1583);
+ (I2 => F) = (867, 1184);
+ (I3 => F) = (555, 902);
+ 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 F = I0 ? s1[1] : s1[0];
endmodule
+(* abc9_lut=2 *)
+module __APICULA_LUT5(output F, input I0, I1, I2, I3, M0);
+ specify
+ (I0 => F) = (1187, 1638);
+ (I1 => F) = (1184, 1638);
+ (I2 => F) = (995, 1371);
+ (I3 => F) = (808, 1116);
+ (M0 => F) = (486, 680);
+ endspecify
+endmodule
+
+(* abc9_lut=4 *)
+module __APICULA_LUT6(output F, input I0, I1, I2, I3, M0, M1);
+ specify
+ (I0 => F) = (1187 + 136, 1638 + 255);
+ (I1 => F) = (1184 + 136, 1638 + 255);
+ (I2 => F) = (995 + 136, 1371 + 255);
+ (I3 => F) = (808 + 136, 1116 + 255);
+ (M0 => F) = (486 + 136, 680 + 255);
+ (M1 => F) = (478, 723);
+ endspecify
+endmodule
+
+(* abc9_lut=8 *)
+module __APICULA_LUT7(output F, input I0, I1, I2, I3, M0, M1, M2);
+ specify
+ (I0 => F) = (1187 + 136 + 136, 1638 + 255 + 255);
+ (I1 => F) = (1184 + 136 + 136, 1638 + 255 + 255);
+ (I2 => F) = (995 + 136 + 136, 1371 + 255 + 255);
+ (I3 => F) = (808 + 136 + 136, 1116 + 255 + 255);
+ (M0 => F) = (486 + 136 + 136, 680 + 255 + 255);
+ (M1 => F) = (478 + 136, 723 + 255);
+ (M2 => F) = (478, 723);
+ endspecify
+endmodule
+
+(* abc9_lut=16 *)
+module __APICULA_LUT8(output F, input I0, I1, I2, I3, M0, M1, M2, M3);
+ specify
+ (I0 => F) = (1187 + 136 + 136 + 136, 1638 + 255 + 255 + 255);
+ (I1 => F) = (1184 + 136 + 136 + 136, 1638 + 255 + 255 + 255);
+ (I2 => F) = (995 + 136 + 136 + 136, 1371 + 255 + 255 + 255);
+ (I3 => F) = (808 + 136 + 136 + 136, 1116 + 255 + 255 + 255);
+ (M0 => F) = (486 + 136 + 136 + 136, 680 + 255 + 255 + 255);
+ (M1 => F) = (478 + 136 + 136, 723 + 255 + 255);
+ (M2 => F) = (478 + 136, 723 + 255);
+ (M3 => F) = (478, 723);
+ endspecify
+ endmodule
+
module MUX2 (O, I0, I1, S0);
input I0,I1;
input S0;
output O;
+
+ specify
+ (I0 => O) = (141, 160);
+ (I1 => O) = (141, 160);
+ (S0 => O) = (486, 680);
+ endspecify
+
assign O = S0 ? I1 : I0;
endmodule
@@ -35,6 +114,13 @@ module MUX2_LUT5 (O, I0, I1, S0);
input I0,I1;
input S0;
output O;
+
+ specify
+ (I0 => O) = (141, 160);
+ (I1 => O) = (141, 160);
+ (S0 => O) = (486, 680);
+ endspecify
+
MUX2 mux2_lut5 (O, I0, I1, S0);
endmodule
@@ -42,6 +128,13 @@ module MUX2_LUT6 (O, I0, I1, S0);
input I0,I1;
input S0;
output O;
+
+ specify
+ (I0 => O) = (136, 255);
+ (I1 => O) = (136, 255);
+ (S0 => O) = (478, 723);
+ endspecify
+
MUX2 mux2_lut6 (O, I0, I1, S0);
endmodule
@@ -49,6 +142,13 @@ module MUX2_LUT7 (O, I0, I1, S0);
input I0,I1;
input S0;
output O;
+
+ specify
+ (I0 => O) = (136, 255);
+ (I1 => O) = (136, 255);
+ (S0 => O) = (478, 723);
+ endspecify
+
MUX2 mux2_lut7 (O, I0, I1, S0);
endmodule
@@ -56,29 +156,58 @@ module MUX2_LUT8 (O, I0, I1, S0);
input I0,I1;
input S0;
output O;
+
+ specify
+ (I0 => O) = (136, 255);
+ (I1 => O) = (136, 255);
+ (S0 => O) = (478, 723);
+ endspecify
+
MUX2 mux2_lut8 (O, I0, I1, S0);
endmodule
+(* abc9_flop, lib_whitebox *)
module DFF (output reg Q, input CLK, D);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
+
+ specify
+ (posedge CLK => (Q : D)) = (480, 660);
+ $setup(D, posedge CLK, 576);
+ endspecify
+
always @(posedge CLK)
Q <= D;
endmodule
+(* abc9_flop, lib_whitebox *)
module DFFE (output reg Q, input D, CLK, CE);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
+
+ specify
+ if (CE) (posedge CLK => (Q : D)) = (480, 660);
+ $setup(D, posedge CLK &&& CE, 576);
+ $setup(CE, posedge CLK, 63);
+ endspecify
+
always @(posedge CLK) begin
if (CE)
Q <= D;
end
endmodule // DFFE (positive clock edge; clock enable)
-
+(* abc9_box, lib_whitebox *)
module DFFS (output reg Q, input D, CLK, SET);
- parameter [0:0] INIT = 1'b0;
+ parameter [0:0] INIT = 1'b1;
initial Q = INIT;
+
+ specify
+ (posedge CLK => (Q : D)) = (480, 660);
+ $setup(D, posedge CLK, 576);
+ $setup(SET, posedge CLK, 63);
+ endspecify
+
always @(posedge CLK) begin
if (SET)
Q <= 1'b1;
@@ -87,10 +216,18 @@ module DFFS (output reg Q, input D, CLK, SET);
end
endmodule // DFFS (positive clock edge; synchronous set)
-
+(* abc9_box, lib_whitebox *)
module DFFSE (output reg Q, input D, CLK, CE, SET);
- parameter [0:0] INIT = 1'b0;
+ parameter [0:0] INIT = 1'b1;
initial Q = INIT;
+
+ specify
+ if (CE) (posedge CLK => (Q : D)) = (480, 660);
+ $setup(D, posedge CLK &&& CE, 576);
+ $setup(CE, posedge CLK, 63);
+ $setup(SET, posedge CLK, 63);
+ endspecify
+
always @(posedge CLK) begin
if (SET)
Q <= 1'b1;
@@ -99,10 +236,17 @@ module DFFSE (output reg Q, input D, CLK, CE, SET);
end
endmodule // DFFSE (positive clock edge; synchronous set takes precedence over clock enable)
-
+(* abc9_flop, lib_whitebox *)
module DFFR (output reg Q, input D, CLK, RESET);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
+
+ specify
+ (posedge CLK => (Q : D)) = (480, 660);
+ $setup(D, posedge CLK, 576);
+ $setup(RESET, posedge CLK, 63);
+ endspecify
+
always @(posedge CLK) begin
if (RESET)
Q <= 1'b0;
@@ -111,10 +255,18 @@ module DFFR (output reg Q, input D, CLK, RESET);
end
endmodule // DFFR (positive clock edge; synchronous reset)
-
+(* abc9_flop, lib_whitebox *)
module DFFRE (output reg Q, input D, CLK, CE, RESET);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
+
+ specify
+ if (CE) (posedge CLK => (Q : D)) = (480, 660);
+ $setup(D, posedge CLK &&& CE, 576);
+ $setup(CE, posedge CLK, 63);
+ $setup(RESET, posedge CLK, 63);
+ endspecify
+
always @(posedge CLK) begin
if (RESET)
Q <= 1'b0;
@@ -123,10 +275,17 @@ module DFFRE (output reg Q, input D, CLK, CE, RESET);
end
endmodule // DFFRE (positive clock edge; synchronous reset takes precedence over clock enable)
-
+(* abc9_box, lib_whitebox *)
module DFFP (output reg Q, input D, CLK, PRESET);
- parameter [0:0] INIT = 1'b0;
+ parameter [0:0] INIT = 1'b1;
initial Q = INIT;
+
+ specify
+ (posedge CLK => (Q : D)) = (480, 660);
+ (posedge PRESET => (Q : 1'b1)) = (1800, 2679);
+ $setup(D, posedge CLK, 576);
+ endspecify
+
always @(posedge CLK or posedge PRESET) begin
if(PRESET)
Q <= 1'b1;
@@ -135,10 +294,18 @@ module DFFP (output reg Q, input D, CLK, PRESET);
end
endmodule // DFFP (positive clock edge; asynchronous preset)
-
+(* abc9_box, lib_whitebox *)
module DFFPE (output reg Q, input D, CLK, CE, PRESET);
- parameter [0:0] INIT = 1'b0;
+ parameter [0:0] INIT = 1'b1;
initial Q = INIT;
+
+ specify
+ if (CE) (posedge CLK => (Q : D)) = (480, 660);
+ (posedge PRESET => (Q : 1'b1)) = (1800, 2679);
+ $setup(D, posedge CLK &&& CE, 576);
+ $setup(CE, posedge CLK, 63);
+ endspecify
+
always @(posedge CLK or posedge PRESET) begin
if(PRESET)
Q <= 1'b1;
@@ -147,10 +314,17 @@ module DFFPE (output reg Q, input D, CLK, CE, PRESET);
end
endmodule // DFFPE (positive clock edge; asynchronous preset; clock enable)
-
+(* abc9_box, lib_whitebox *)
module DFFC (output reg Q, input D, CLK, CLEAR);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
+
+ specify
+ (posedge CLK => (Q : D)) = (480, 660);
+ (posedge CLEAR => (Q : 1'b0)) = (1800, 2679);
+ $setup(D, posedge CLK, 576);
+ endspecify
+
always @(posedge CLK or posedge CLEAR) begin
if(CLEAR)
Q <= 1'b0;
@@ -159,10 +333,18 @@ module DFFC (output reg Q, input D, CLK, CLEAR);
end
endmodule // DFFC (positive clock edge; asynchronous clear)
-
+(* abc9_box, lib_whitebox *)
module DFFCE (output reg Q, input D, CLK, CE, CLEAR);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
+
+ specify
+ if (CE) (posedge CLK => (Q : D)) = (480, 660);
+ (posedge CLEAR => (Q : 1'b0)) = (1800, 2679);
+ $setup(D, posedge CLK &&& CE, 576);
+ $setup(CE, posedge CLK, 63);
+ endspecify
+
always @(posedge CLK or posedge CLEAR) begin
if(CLEAR)
Q <= 1'b0;
@@ -171,27 +353,48 @@ module DFFCE (output reg Q, input D, CLK, CE, CLEAR);
end
endmodule // DFFCE (positive clock edge; asynchronous clear; clock enable)
-
+(* abc9_flop, lib_whitebox *)
module DFFN (output reg Q, input CLK, D);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
+
+ specify
+ (negedge CLK => (Q : D)) = (480, 660);
+ $setup(D, negedge CLK, 576);
+ endspecify
+
always @(negedge CLK)
Q <= D;
endmodule
+(* abc9_flop, lib_whitebox *)
module DFFNE (output reg Q, input D, CLK, CE);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
+
+ specify
+ if (CE) (negedge CLK => (Q : D)) = (480, 660);
+ $setup(D, negedge CLK &&& CE, 576);
+ $setup(CE, negedge CLK, 63);
+ endspecify
+
always @(negedge CLK) begin
if (CE)
Q <= D;
end
endmodule // DFFNE (negative clock edge; clock enable)
-
+(* abc9_box, lib_whitebox *)
module DFFNS (output reg Q, input D, CLK, SET);
- parameter [0:0] INIT = 1'b0;
+ parameter [0:0] INIT = 1'b1;
initial Q = INIT;
+
+ specify
+ (negedge CLK => (Q : D)) = (480, 660);
+ $setup(D, negedge CLK, 576);
+ $setup(SET, negedge CLK, 63);
+ endspecify
+
always @(negedge CLK) begin
if (SET)
Q <= 1'b1;
@@ -200,10 +403,18 @@ module DFFNS (output reg Q, input D, CLK, SET);
end
endmodule // DFFNS (negative clock edge; synchronous set)
-
+(* abc9_box, lib_whitebox *)
module DFFNSE (output reg Q, input D, CLK, CE, SET);
- parameter [0:0] INIT = 1'b0;
+ parameter [0:0] INIT = 1'b1;
initial Q = INIT;
+
+ specify
+ if (CE) (negedge CLK => (Q : D)) = (480, 660);
+ $setup(D, negedge CLK &&& CE, 576);
+ $setup(CE, negedge CLK, 63);
+ $setup(SET, negedge CLK, 63);
+ endspecify
+
always @(negedge CLK) begin
if (SET)
Q <= 1'b1;
@@ -212,10 +423,17 @@ module DFFNSE (output reg Q, input D, CLK, CE, SET);
end
endmodule // DFFNSE (negative clock edge; synchronous set takes precedence over clock enable)
-
+(* abc9_flop, lib_whitebox *)
module DFFNR (output reg Q, input D, CLK, RESET);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
+
+ specify
+ (negedge CLK => (Q : D)) = (480, 660);
+ $setup(D, negedge CLK, 576);
+ $setup(RESET, negedge CLK, 63);
+ endspecify
+
always @(negedge CLK) begin
if (RESET)
Q <= 1'b0;
@@ -224,10 +442,18 @@ module DFFNR (output reg Q, input D, CLK, RESET);
end
endmodule // DFFNR (negative clock edge; synchronous reset)
-
+(* abc9_flop, lib_whitebox *)
module DFFNRE (output reg Q, input D, CLK, CE, RESET);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
+
+ specify
+ if (CE) (negedge CLK => (Q : D)) = (480, 660);
+ $setup(D, negedge CLK &&& CE, 576);
+ $setup(CE, negedge CLK, 63);
+ $setup(RESET, negedge CLK, 63);
+ endspecify
+
always @(negedge CLK) begin
if (RESET)
Q <= 1'b0;
@@ -236,10 +462,17 @@ module DFFNRE (output reg Q, input D, CLK, CE, RESET);
end
endmodule // DFFNRE (negative clock edge; synchronous reset takes precedence over clock enable)
-
+(* abc9_box, lib_whitebox *)
module DFFNP (output reg Q, input D, CLK, PRESET);
- parameter [0:0] INIT = 1'b0;
+ parameter [0:0] INIT = 1'b1;
initial Q = INIT;
+
+ specify
+ (negedge CLK => (Q : D)) = (480, 660);
+ (posedge PRESET => (Q : 1'b1)) = (1800, 2679);
+ $setup(D, negedge CLK, 576);
+ endspecify
+
always @(negedge CLK or posedge PRESET) begin
if(PRESET)
Q <= 1'b1;
@@ -248,10 +481,18 @@ module DFFNP (output reg Q, input D, CLK, PRESET);
end
endmodule // DFFNP (negative clock edge; asynchronous preset)
-
+(* abc9_box, lib_whitebox *)
module DFFNPE (output reg Q, input D, CLK, CE, PRESET);
- parameter [0:0] INIT = 1'b0;
+ parameter [0:0] INIT = 1'b1;
initial Q = INIT;
+
+ specify
+ if (CE) (negedge CLK => (Q : D)) = (480, 660);
+ (posedge PRESET => (Q : 1'b1)) = (1800, 2679);
+ $setup(D, negedge CLK &&& CE, 576);
+ $setup(CE, negedge CLK, 63);
+ endspecify
+
always @(negedge CLK or posedge PRESET) begin
if(PRESET)
Q <= 1'b1;
@@ -260,10 +501,17 @@ module DFFNPE (output reg Q, input D, CLK, CE, PRESET);
end
endmodule // DFFNPE (negative clock edge; asynchronous preset; clock enable)
-
+(* abc9_box, lib_whitebox *)
module DFFNC (output reg Q, input D, CLK, CLEAR);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
+
+ specify
+ (negedge CLK => (Q : D)) = (480, 660);
+ (posedge CLEAR => (Q : 1'b0)) = (1800, 2679);
+ $setup(D, negedge CLK, 576);
+ endspecify
+
always @(negedge CLK or posedge CLEAR) begin
if(CLEAR)
Q <= 1'b0;
@@ -272,10 +520,18 @@ module DFFNC (output reg Q, input D, CLK, CLEAR);
end
endmodule // DFFNC (negative clock edge; asynchronous clear)
-
+(* abc9_box, lib_whitebox *)
module DFFNCE (output reg Q, input D, CLK, CE, CLEAR);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
+
+ specify
+ if (CE) (negedge CLK => (Q : D)) = (480, 660);
+ (posedge CLEAR => (Q : 1'b0)) = (1800, 2679);
+ $setup(D, negedge CLK &&& CE, 576);
+ $setup(CE, negedge CLK, 63);
+ endspecify
+
always @(negedge CLK or posedge CLEAR) begin
if(CLEAR)
Q <= 1'b0;
@@ -294,25 +550,37 @@ module GND(output G);
assign G = 0;
endmodule
+(* abc9_box *)
module IBUF(output O, input I);
+
+ specify
+ (I => O) = 0;
+ endspecify
+
assign O = I;
endmodule
+(* abc9_box *)
module OBUF(output O, input I);
+
+ specify
+ (I => O) = 0;
+ endspecify
+
assign O = I;
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
@@ -320,14 +588,15 @@ module GSR (input GSRI);
wire GSRO = GSRI;
endmodule
+(* abc9_box, lib_whitebox *)
module ALU (SUM, COUT, I0, I1, I3, CIN);
input I0;
input I1;
input I3;
-input CIN;
+(* abc9_carry *) input CIN;
output SUM;
-output COUT;
+(* abc9_carry *) output COUT;
localparam ADD = 0;
localparam SUB = 1;
@@ -344,6 +613,17 @@ parameter ALU_MODE = 0;
reg S, C;
+specify
+ (I0 => SUM) = (1043, 1432);
+ (I1 => SUM) = (775, 1049);
+ (I3 => SUM) = (751, 1010);
+ (CIN => SUM) = (694, 811);
+ (I0 => COUT) = (1010, 1380);
+ (I1 => COUT) = (1021, 1505);
+ (I3 => COUT) = (483, 792);
+ (CIN => COUT) = (49, 82);
+endspecify
+
assign SUM = S ^ CIN;
assign COUT = S? CIN : C;
@@ -395,43 +675,249 @@ 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;
-
- 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
+
+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 : 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
+
+
+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 *)
@@ -516,5 +1002,66 @@ input [31:0] DI;
input [2:0] BLKSEL;
output [31:0] DO;
+specify
+ (posedge CLKB => (DO : DI)) = (419, 493);
+ $setup(RESETA, posedge CLKA, 62);
+ $setup(RESETB, posedge CLKB, 62);
+ $setup(OCE, posedge CLKB, 62);
+ $setup(CEA, posedge CLKA, 62);
+ $setup(CEB, posedge CLKB, 62);
+ $setup(OCE, posedge CLKB, 62);
+ $setup(WREA, posedge CLKA, 62);
+ $setup(WREB, posedge CLKB, 62);
+ $setup(DI, posedge CLKA, 62);
+ $setup(ADA, posedge CLKA, 62);
+ $setup(ADB, posedge CLKB, 62);
+ $setup(BLKSEL, posedge CLKA, 62);
+endspecify
+
endmodule
+(* blackbox *)
+module rPLL (CLKOUT, CLKOUTP, CLKOUTD, CLKOUTD3, LOCK, CLKIN, CLKFB, FBDSEL, IDSEL, ODSEL, DUTYDA, PSDA, FDLY, RESET, RESET_P);
+input CLKIN;
+input CLKFB;
+input RESET;
+input RESET_P;
+input [5:0] FBDSEL;
+input [5:0] IDSEL;
+input [5:0] ODSEL;
+input [3:0] PSDA,FDLY;
+input [3:0] DUTYDA;
+
+output CLKOUT;
+output LOCK;
+output CLKOUTP;
+output CLKOUTD;
+output CLKOUTD3;
+
+parameter FCLKIN = "100.0"; // frequency of CLKIN
+parameter DYN_IDIV_SEL= "false"; // true:IDSEL, false:IDIV_SEL
+parameter IDIV_SEL = 0; // 0:1, 1:2 ... 63:64
+parameter DYN_FBDIV_SEL= "false"; // true:FBDSEL, false:FBDIV_SEL
+parameter FBDIV_SEL = 0; // 0:1, 1:2 ... 63:64
+parameter DYN_ODIV_SEL= "false"; // true:ODSEL, false:ODIV_SEL
+parameter ODIV_SEL = 8; // 2/4/8/16/32/48/64/80/96/112/128
+
+parameter PSDA_SEL= "0000";
+parameter DYN_DA_EN = "false"; // true:PSDA or DUTYDA or FDA, false: DA_SEL
+parameter DUTYDA_SEL= "1000";
+
+parameter CLKOUT_FT_DIR = 1'b1; // CLKOUT fine tuning direction. 1'b1 only
+parameter CLKOUTP_FT_DIR = 1'b1; // 1'b1 only
+parameter CLKOUT_DLY_STEP = 0; // 0, 1, 2, 4
+parameter CLKOUTP_DLY_STEP = 0; // 0, 1, 2
+
+parameter CLKFB_SEL = "internal"; // "internal", "external"
+parameter CLKOUT_BYPASS = "false"; // "true", "false"
+parameter CLKOUTP_BYPASS = "false"; // "true", "false"
+parameter CLKOUTD_BYPASS = "false"; // "true", "false"
+parameter DYN_SDIV_SEL = 2; // 2~128, only even numbers
+parameter CLKOUTD_SRC = "CLKOUT"; // CLKOUT, CLKOUTP
+parameter CLKOUTD3_SRC = "CLKOUT"; // CLKOUT, CLKOUTP
+parameter DEVICE = "GW1N-1"; // "GW1N-1", "GW1N-4", "GW1N-9", "GW1NR-4", "GW1NR-9", "GW1N-4B", "GW1NR-4B", "GW1NS-2", "GW1NS-2C", "GW1NZ-1", "GW1NSR-2", "GW1NSR-2C", "GW1N-1S", "GW1NSE-2C", "GW1NRF-4B", "GW1N-9C", "GW1NR-9C", "GW1N-4C", "GW1NR-4C"
+
+endmodule
diff --git a/techlibs/gowin/determine_init.cc b/techlibs/gowin/determine_init.cc
deleted file mode 100644
index 15ff115de..000000000
--- a/techlibs/gowin/determine_init.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * yosys -- Yosys Open SYnthesis Suite
- *
- * Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
- *
- * 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 DetermineInitPass : public Pass {
- DetermineInitPass() : Pass("determine_init", "Determine the init value of cells") { }
- void help() override
- {
- log("\n");
- log(" determine_init [selection]\n");
- log("\n");
- log("Determine the init value of cells that doesn't allow unknown init value.\n");
- log("\n");
- }
-
- Const determine_init(Const init)
- {
- for (int i = 0; i < GetSize(init); i++) {
- if (init[i] != State::S0 && init[i] != State::S1)
- init[i] = State::S0;
- }
-
- return init;
- }
-
- void execute(std::vector<std::string> args, RTLIL::Design *design) override
- {
- log_header(design, "Executing DETERMINE_INIT pass (determine init value for cells).\n");
-
- extra_args(args, args.size(), design);
-
- int cnt = 0;
- for (auto module : design->selected_modules())
- {
- for (auto cell : module->selected_cells())
- {
- if (cell->type == ID(RAM16S4))
- {
- cell->setParam(ID(INIT_0), determine_init(cell->getParam(ID(INIT_0))));
- cell->setParam(ID(INIT_1), determine_init(cell->getParam(ID(INIT_1))));
- cell->setParam(ID(INIT_2), determine_init(cell->getParam(ID(INIT_2))));
- cell->setParam(ID(INIT_3), determine_init(cell->getParam(ID(INIT_3))));
- cnt++;
- }
- }
- }
- log_header(design, "Updated %d cells with determined init value.\n", cnt);
- }
-} DetermineInitPass;
-
-PRIVATE_NAMESPACE_END
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 32d9cc0a5..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
@@ -44,6 +44,11 @@ struct SynthGowinPass : public ScriptPass
log(" write the design to the specified Verilog netlist file. writing of an\n");
log(" output file is omitted if this parameter is not specified.\n");
log("\n");
+ log(" -json <file>\n");
+ log(" write the design to the specified JSON netlist file. writing of an\n");
+ log(" output file is omitted if this parameter is not specified.\n");
+ log(" This disables features not yet supported by nexpnr-gowin.\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");
@@ -69,9 +74,12 @@ struct SynthGowinPass : public ScriptPass
log("\n");
log(" -noiopads\n");
log(" do not emit IOB at top level ports\n");
- //log("\n");
- //log(" -abc9\n");
- //log(" use new ABC9 flow (EXPERIMENTAL)\n");
+ log("\n");
+ log(" -noalu\n");
+ log(" do not use ALU cells\n");
+ log("\n");
+ log(" -abc9\n");
+ log(" use new ABC9 flow (EXPERIMENTAL)\n");
log("\n");
log("\n");
log("The following commands are executed by this synthesis command:\n");
@@ -79,13 +87,14 @@ struct SynthGowinPass : public ScriptPass
log("\n");
}
- string top_opt, vout_file;
- bool retime, nobram, nolutram, flatten, nodffe, nowidelut, abc9, noiopads;
+ string top_opt, vout_file, json_file;
+ bool retime, nobram, nolutram, flatten, nodffe, nowidelut, abc9, noiopads, noalu;
void clear_flags() override
{
top_opt = "-auto-top";
vout_file = "";
+ json_file = "";
retime = false;
flatten = true;
nobram = false;
@@ -94,6 +103,7 @@ struct SynthGowinPass : public ScriptPass
nowidelut = false;
abc9 = false;
noiopads = false;
+ noalu = false;
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
@@ -112,6 +122,12 @@ struct SynthGowinPass : public ScriptPass
vout_file = args[++argidx];
continue;
}
+ if (args[argidx] == "-json" && argidx+1 < args.size()) {
+ json_file = args[++argidx];
+ nobram = true;
+ nolutram = true;
+ continue;
+ }
if (args[argidx] == "-run" && argidx+1 < args.size()) {
size_t pos = args[argidx+1].find(':');
if (pos == std::string::npos)
@@ -144,10 +160,14 @@ struct SynthGowinPass : public ScriptPass
nowidelut = true;
continue;
}
- //if (args[argidx] == "-abc9") {
- // abc9 = true;
- // continue;
- //}
+ if (args[argidx] == "-noalu") {
+ noalu = true;
+ continue;
+ }
+ if (args[argidx] == "-abc9") {
+ abc9 = true;
+ continue;
+ }
if (args[argidx] == "-noiopads") {
noiopads = true;
continue;
@@ -171,7 +191,7 @@ struct SynthGowinPass : public ScriptPass
{
if (check_label("begin"))
{
- run("read_verilog -lib +/gowin/cells_sim.v");
+ run("read_verilog -specify -lib +/gowin/cells_sim.v");
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
}
@@ -198,7 +218,7 @@ struct SynthGowinPass : public ScriptPass
{
run("memory_bram -rules +/gowin/lutrams.txt");
run("techmap -map +/gowin/lutrams_map.v");
- run("determine_init");
+ run("setundef -params -zero t:RAM16S4");
}
if (check_label("map_ffram"))
@@ -210,19 +230,26 @@ struct SynthGowinPass : public ScriptPass
if (check_label("map_gates"))
{
- run("techmap -map +/techmap.v -map +/gowin/arith_map.v");
+ if (noalu) {
+ run("techmap -map +/techmap.v");
+ } else {
+ run("techmap -map +/techmap.v -map +/gowin/arith_map.v");
+ }
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"))
{
- run("dff2dffs -match-init");
run("opt_clean");
- if (!nodffe)
- run("dff2dffe -direct-match $_DFF_* -direct-match $_SDFF_*");
+ if (nodffe)
+ run("dfflegalize -cell $_DFF_?_ 0 -cell $_SDFF_?P?_ r -cell $_DFF_?P?_ r");
+ else
+ run("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");
run("techmap -map +/gowin/cells_map.v");
run("opt_expr -mux_undef");
run("simplemap");
@@ -230,13 +257,15 @@ struct SynthGowinPass : public ScriptPass
if (check_label("map_luts"))
{
- /*if (nowidelut && abc9) {
- run("abc9 -lut 4");
- } else*/ if (nowidelut && !abc9) {
+ if (nowidelut && abc9) {
+ run("read_verilog -icells -lib -specify +/abc9_model.v");
+ run("abc9 -maxlut 4 -W 500");
+ } else if (nowidelut && !abc9) {
run("abc -lut 4");
- } else /*if (!nowidelut && abc9) {
- run("abc9 -lut 4:8");
- } else*/ if (!nowidelut && !abc9) {
+ } else if (!nowidelut && abc9) {
+ run("read_verilog -icells -lib -specify +/abc9_model.v");
+ run("abc9 -maxlut 8 -W 500");
+ } else if (!nowidelut && !abc9) {
run("abc -lut 4:8");
}
run("clean");
@@ -248,10 +277,10 @@ 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");
}
if (check_label("check"))
@@ -259,13 +288,17 @@ 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",
+ help_mode ? "<file-name>" : json_file.c_str()));
}
}
} SynthGowinPass;
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 17b5d4782..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
@@ -162,7 +162,7 @@ struct SynthGreenPAK4Pass : public ScriptPass
run("opt -undriven -fine");
run("techmap -map +/techmap.v -map +/greenpak4/cells_latch.v");
run("dfflibmap -prepare -liberty +/greenpak4/gp_dff.lib");
- run("opt -fast");
+ run("opt -fast -noclkinv -noff");
if (retime || help_mode)
run("abc -dff -D 1", "(only if -retime)");
}
@@ -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/Makefile.inc b/techlibs/ice40/Makefile.inc
index 1a8caf9a9..8ce3cb024 100644
--- a/techlibs/ice40/Makefile.inc
+++ b/techlibs/ice40/Makefile.inc
@@ -1,8 +1,6 @@
OBJS += techlibs/ice40/synth_ice40.o
OBJS += techlibs/ice40/ice40_braminit.o
-OBJS += techlibs/ice40/ice40_ffssr.o
-OBJS += techlibs/ice40/ice40_ffinit.o
OBJS += techlibs/ice40/ice40_opt.o
GENFILES += techlibs/ice40/brams_init1.vh
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/brams_map.v b/techlibs/ice40/brams_map.v
index ad3bccd21..db9f5d8ce 100644
--- a/techlibs/ice40/brams_map.v
+++ b/techlibs/ice40/brams_map.v
@@ -254,6 +254,41 @@ module \$__ICE40_RAM4K_M123 (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B
wire [15:0] A1DATA_16, B1DATA_16;
+`define INSTANCE \
+ \$__ICE40_RAM4K #( \
+ .READ_MODE(MODE), \
+ .WRITE_MODE(MODE), \
+ .NEGCLK_R(!CLKPOL2), \
+ .NEGCLK_W(!CLKPOL3), \
+ .INIT_0(INIT_0), \
+ .INIT_1(INIT_1), \
+ .INIT_2(INIT_2), \
+ .INIT_3(INIT_3), \
+ .INIT_4(INIT_4), \
+ .INIT_5(INIT_5), \
+ .INIT_6(INIT_6), \
+ .INIT_7(INIT_7), \
+ .INIT_8(INIT_8), \
+ .INIT_9(INIT_9), \
+ .INIT_A(INIT_A), \
+ .INIT_B(INIT_B), \
+ .INIT_C(INIT_C), \
+ .INIT_D(INIT_D), \
+ .INIT_E(INIT_E), \
+ .INIT_F(INIT_F) \
+ ) _TECHMAP_REPLACE_ ( \
+ .RDATA(A1DATA_16), \
+ .RADDR(A1ADDR_11), \
+ .RCLK(CLK2), \
+ .RCLKE(A1EN), \
+ .RE(1'b1), \
+ .WDATA(B1DATA_16), \
+ .WADDR(B1ADDR_11), \
+ .WCLK(CLK3), \
+ .WCLKE(|B1EN), \
+ .WE(1'b1) \
+ );
+
generate
if (MODE == 1) begin
assign A1DATA = {A1DATA_16[14], A1DATA_16[12], A1DATA_16[10], A1DATA_16[ 8],
@@ -261,51 +296,23 @@ module \$__ICE40_RAM4K_M123 (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B
assign {B1DATA_16[14], B1DATA_16[12], B1DATA_16[10], B1DATA_16[ 8],
B1DATA_16[ 6], B1DATA_16[ 4], B1DATA_16[ 2], B1DATA_16[ 0]} = B1DATA;
`include "brams_init1.vh"
+ `INSTANCE
end
if (MODE == 2) begin
assign A1DATA = {A1DATA_16[13], A1DATA_16[9], A1DATA_16[5], A1DATA_16[1]};
assign {B1DATA_16[13], B1DATA_16[9], B1DATA_16[5], B1DATA_16[1]} = B1DATA;
`include "brams_init2.vh"
+ `INSTANCE
end
if (MODE == 3) begin
assign A1DATA = {A1DATA_16[11], A1DATA_16[3]};
assign {B1DATA_16[11], B1DATA_16[3]} = B1DATA;
`include "brams_init3.vh"
+ `INSTANCE
end
endgenerate
- \$__ICE40_RAM4K #(
- .READ_MODE(MODE),
- .WRITE_MODE(MODE),
- .NEGCLK_R(!CLKPOL2),
- .NEGCLK_W(!CLKPOL3),
- .INIT_0(INIT_0),
- .INIT_1(INIT_1),
- .INIT_2(INIT_2),
- .INIT_3(INIT_3),
- .INIT_4(INIT_4),
- .INIT_5(INIT_5),
- .INIT_6(INIT_6),
- .INIT_7(INIT_7),
- .INIT_8(INIT_8),
- .INIT_9(INIT_9),
- .INIT_A(INIT_A),
- .INIT_B(INIT_B),
- .INIT_C(INIT_C),
- .INIT_D(INIT_D),
- .INIT_E(INIT_E),
- .INIT_F(INIT_F)
- ) _TECHMAP_REPLACE_ (
- .RDATA(A1DATA_16),
- .RADDR(A1ADDR_11),
- .RCLK(CLK2),
- .RCLKE(A1EN),
- .RE(1'b1),
- .WDATA(B1DATA_16),
- .WADDR(B1ADDR_11),
- .WCLK(CLK3),
- .WCLKE(|B1EN),
- .WE(1'b1)
- );
+`undef INSTANCE
+
endmodule
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/ff_map.v b/techlibs/ice40/ff_map.v
index 990cd74f1..8174323a2 100644
--- a/techlibs/ice40/ff_map.v
+++ b/techlibs/ice40/ff_map.v
@@ -1,28 +1,25 @@
-module \$_DFF_N_ (input D, C, output Q); SB_DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule
-module \$_DFF_P_ (input D, C, output Q); SB_DFF _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule
+module \$_DFF_N_ (input D, C, output Q); SB_DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule
+module \$_DFF_P_ (input D, C, output Q); SB_DFF _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule
-module \$_DFFE_NN_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule
-module \$_DFFE_PN_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule
+module \$_DFFE_NP_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule
+module \$_DFFE_PP_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule
-module \$_DFFE_NP_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule
-module \$_DFFE_PP_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule
+module \$_DFF_NP0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule
+module \$_DFF_NP1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule
+module \$_DFF_PP0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule
+module \$_DFF_PP1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule
-module \$_DFF_NN0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule
-module \$_DFF_NN1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule
-module \$_DFF_PN0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule
-module \$_DFF_PN1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule
+module \$_DFFE_NP0P_ (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule
+module \$_DFFE_NP1P_ (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule
+module \$_DFFE_PP0P_ (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule
+module \$_DFFE_PP1P_ (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule
-module \$_DFF_NP0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule
-module \$_DFF_NP1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule
-module \$_DFF_PP0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule
-module \$_DFF_PP1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule
+module \$_SDFF_NP0_ (input D, C, R, output Q); SB_DFFNSR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule
+module \$_SDFF_NP1_ (input D, C, R, output Q); SB_DFFNSS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule
+module \$_SDFF_PP0_ (input D, C, R, output Q); SB_DFFSR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule
+module \$_SDFF_PP1_ (input D, C, R, output Q); SB_DFFSS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule
-module \$_DFFE_NN0P_ (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule
-module \$_DFFE_NN1P_ (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule
-module \$_DFFE_PN0P_ (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule
-module \$_DFFE_PN1P_ (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule
-
-module \$_DFFE_NP0P_ (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule
-module \$_DFFE_NP1P_ (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule
-module \$_DFFE_PP0P_ (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule
-module \$_DFFE_PP1P_ (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule
+module \$_SDFFCE_NP0P_ (input D, C, E, R, output Q); SB_DFFNESR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule
+module \$_SDFFCE_NP1P_ (input D, C, E, R, output Q); SB_DFFNESS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule
+module \$_SDFFCE_PP0P_ (input D, C, E, R, output Q); SB_DFFESR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule
+module \$_SDFFCE_PP1P_ (input D, C, E, R, output Q); SB_DFFESS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule
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_ffinit.cc b/techlibs/ice40/ice40_ffinit.cc
deleted file mode 100644
index 2eef3fa93..000000000
--- a/techlibs/ice40/ice40_ffinit.cc
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * yosys -- Yosys Open SYnthesis Suite
- *
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#include "kernel/yosys.h"
-#include "kernel/sigtools.h"
-
-USING_YOSYS_NAMESPACE
-PRIVATE_NAMESPACE_BEGIN
-
-struct Ice40FfinitPass : public Pass {
- Ice40FfinitPass() : Pass("ice40_ffinit", "iCE40: handle FF init values") { }
- void help() override
- {
- // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
- log("\n");
- log(" ice40_ffinit [options] [selection]\n");
- log("\n");
- log("Remove zero init values for FF output signals. Add inverters to implement\n");
- log("nonzero init values.\n");
- log("\n");
- }
- void execute(std::vector<std::string> args, RTLIL::Design *design) override
- {
- log_header(design, "Executing ICE40_FFINIT pass (implement FF init values).\n");
-
- size_t argidx;
- for (argidx = 1; argidx < args.size(); argidx++)
- {
- // if (args[argidx] == "-singleton") {
- // singleton_mode = true;
- // continue;
- // }
- break;
- }
- extra_args(args, argidx, design);
-
- for (auto module : design->selected_modules())
- {
- log("Handling FF init values in %s.\n", log_id(module));
-
- SigMap sigmap(module);
- pool<Wire*> init_wires;
- dict<SigBit, State> initbits;
- dict<SigBit, SigBit> initbit_to_wire;
- pool<SigBit> handled_initbits;
-
- for (auto wire : module->selected_wires())
- {
- if (wire->attributes.count(ID::init) == 0)
- continue;
-
- SigSpec wirebits = sigmap(wire);
- Const initval = wire->attributes.at(ID::init);
- init_wires.insert(wire);
-
- for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++)
- {
- SigBit bit = wirebits[i];
- State val = initval[i];
-
- if (val != State::S0 && val != State::S1)
- continue;
-
- if (initbits.count(bit)) {
- if (initbits.at(bit) != val) {
- log_warning("Conflicting init values for signal %s (%s = %s, %s = %s).\n",
- log_signal(bit), log_signal(SigBit(wire, i)), log_signal(val),
- log_signal(initbit_to_wire[bit]), log_signal(initbits.at(bit)));
- initbits.at(bit) = State::Sx;
- }
- continue;
- }
-
- initbits[bit] = val;
- initbit_to_wire[bit] = SigBit(wire, i);
- }
- }
-
- pool<IdString> sb_dff_types = {
- ID(SB_DFF), ID(SB_DFFE), ID(SB_DFFSR), ID(SB_DFFR), ID(SB_DFFSS), ID(SB_DFFS), ID(SB_DFFESR),
- ID(SB_DFFER), ID(SB_DFFESS), ID(SB_DFFES), ID(SB_DFFN), ID(SB_DFFNE), ID(SB_DFFNSR), ID(SB_DFFNR),
- ID(SB_DFFNSS), ID(SB_DFFNS), ID(SB_DFFNESR), ID(SB_DFFNER), ID(SB_DFFNESS), ID(SB_DFFNES)
- };
-
- for (auto cell : module->selected_cells())
- {
- if (!sb_dff_types.count(cell->type))
- continue;
-
- SigSpec sig_d = cell->getPort(ID::D);
- SigSpec sig_q = cell->getPort(ID::Q);
-
- if (GetSize(sig_d) < 1 || GetSize(sig_q) < 1)
- continue;
-
- SigBit bit_d = sigmap(sig_d[0]);
- SigBit bit_q = sigmap(sig_q[0]);
-
- if (!initbits.count(bit_q))
- continue;
-
- State val = initbits.at(bit_q);
-
- if (val == State::Sx)
- continue;
-
- handled_initbits.insert(bit_q);
-
- log("FF init value for cell %s (%s): %s = %c\n", log_id(cell), log_id(cell->type),
- log_signal(bit_q), val != State::S0 ? '1' : '0');
-
- if (val == State::S0)
- continue;
-
- string type_str = cell->type.str();
-
- if (type_str.back() == 'S') {
- type_str.back() = 'R';
- cell->type = type_str;
- cell->setPort(ID::R, cell->getPort(ID::S));
- cell->unsetPort(ID::S);
- } else
- if (type_str.back() == 'R') {
- type_str.back() = 'S';
- cell->type = type_str;
- cell->setPort(ID::S, cell->getPort(ID::R));
- cell->unsetPort(ID::R);
- }
-
- Wire *new_bit_d = module->addWire(NEW_ID);
- Wire *new_bit_q = module->addWire(NEW_ID);
-
- module->addNotGate(NEW_ID, bit_d, new_bit_d);
- module->addNotGate(NEW_ID, new_bit_q, bit_q);
-
- cell->setPort(ID::D, new_bit_d);
- cell->setPort(ID::Q, new_bit_q);
- }
-
- for (auto wire : init_wires)
- {
- if (wire->attributes.count(ID::init) == 0)
- continue;
-
- SigSpec wirebits = sigmap(wire);
- Const &initval = wire->attributes.at(ID::init);
- bool remove_attribute = true;
-
- for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++) {
- if (handled_initbits.count(wirebits[i]))
- initval[i] = State::Sx;
- else if (initval[i] != State::Sx)
- remove_attribute = false;
- }
-
- if (remove_attribute)
- wire->attributes.erase(ID::init);
- }
- }
- }
-} Ice40FfinitPass;
-
-PRIVATE_NAMESPACE_END
diff --git a/techlibs/ice40/ice40_ffssr.cc b/techlibs/ice40/ice40_ffssr.cc
deleted file mode 100644
index 492029b77..000000000
--- a/techlibs/ice40/ice40_ffssr.cc
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * yosys -- Yosys Open SYnthesis Suite
- *
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#include "kernel/yosys.h"
-#include "kernel/sigtools.h"
-
-USING_YOSYS_NAMESPACE
-PRIVATE_NAMESPACE_BEGIN
-
-struct Ice40FfssrPass : public Pass {
- Ice40FfssrPass() : Pass("ice40_ffssr", "iCE40: merge synchronous set/reset into FF cells") { }
- void help() override
- {
- log("\n");
- log(" ice40_ffssr [options] [selection]\n");
- log("\n");
- log("Merge synchronous set/reset $_MUX_ cells into iCE40 FFs.\n");
- log("\n");
- }
- void execute(std::vector<std::string> args, RTLIL::Design *design) override
- {
- log_header(design, "Executing ICE40_FFSSR pass (merge synchronous set/reset into FF cells).\n");
-
- size_t argidx;
- for (argidx = 1; argidx < args.size(); argidx++)
- {
- // if (args[argidx] == "-singleton") {
- // singleton_mode = true;
- // continue;
- // }
- break;
- }
- extra_args(args, argidx, design);
-
- pool<IdString> sb_dff_types;
- sb_dff_types.insert(ID(SB_DFF));
- sb_dff_types.insert(ID(SB_DFFE));
- sb_dff_types.insert(ID(SB_DFFN));
- sb_dff_types.insert(ID(SB_DFFNE));
-
- for (auto module : design->selected_modules())
- {
- log("Merging set/reset $_MUX_ cells into SB_FFs in %s.\n", log_id(module));
-
- SigMap sigmap(module);
- dict<SigBit, Cell*> sr_muxes;
- vector<Cell*> ff_cells;
-
- for (auto cell : module->selected_cells())
- {
- if (sb_dff_types.count(cell->type)) {
- ff_cells.push_back(cell);
- continue;
- }
-
- if (cell->type != ID($_MUX_))
- continue;
-
- SigBit bit_a = sigmap(cell->getPort(ID::A));
- SigBit bit_b = sigmap(cell->getPort(ID::B));
-
- if (bit_a.wire == nullptr || bit_b.wire == nullptr)
- sr_muxes[sigmap(cell->getPort(ID::Y))] = cell;
- }
-
- for (auto cell : ff_cells)
- {
- if (cell->get_bool_attribute(ID(dont_touch)))
- continue;
-
- SigSpec sig_d = cell->getPort(ID::D);
-
- if (GetSize(sig_d) < 1)
- continue;
-
- SigBit bit_d = sigmap(sig_d[0]);
-
- if (sr_muxes.count(bit_d) == 0)
- continue;
-
- Cell *mux_cell = sr_muxes.at(bit_d);
- SigBit bit_a = sigmap(mux_cell->getPort(ID::A));
- SigBit bit_b = sigmap(mux_cell->getPort(ID::B));
- SigBit bit_s = sigmap(mux_cell->getPort(ID::S));
-
- log(" Merging %s (A=%s, B=%s, S=%s) into %s (%s).\n", log_id(mux_cell),
- log_signal(bit_a), log_signal(bit_b), log_signal(bit_s), log_id(cell), log_id(cell->type));
-
- SigBit sr_val, sr_sig;
- if (bit_a.wire == nullptr) {
- bit_d = bit_b;
- sr_val = bit_a;
- sr_sig = module->NotGate(NEW_ID, bit_s);
- } else {
- log_assert(bit_b.wire == nullptr);
- bit_d = bit_a;
- sr_val = bit_b;
- sr_sig = bit_s;
- }
-
- if (sr_val == State::S1) {
- cell->type = cell->type.str() + "SS";
- cell->setPort(ID::S, sr_sig);
- cell->setPort(ID::D, bit_d);
- } else {
- cell->type = cell->type.str() + "SR";
- cell->setPort(ID::R, sr_sig);
- cell->setPort(ID::D, bit_d);
- }
- }
- }
- }
-} Ice40FfssrPass;
-
-PRIVATE_NAMESPACE_END
diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc
index 1a70fa8c0..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
@@ -215,7 +215,7 @@ struct Ice40OptPass : public Pass {
log(" <ice40 specific optimizations>\n");
log(" opt_expr -mux_undef -undriven [-full]\n");
log(" opt_merge\n");
- log(" opt_rmdff\n");
+ log(" opt_dff\n");
log(" opt_clean\n");
log(" while <changed design>\n");
log("\n");
@@ -247,7 +247,7 @@ struct Ice40OptPass : public Pass {
Pass::call(design, "opt_expr " + opt_expr_args);
Pass::call(design, "opt_merge");
- Pass::call(design, "opt_rmdff");
+ Pass::call(design, "opt_dff");
Pass::call(design, "opt_clean");
if (design->scratchpad_get_bool("opt.did_something") == false)
diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc
index 6464368eb..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
@@ -292,6 +292,8 @@ struct SynthIce40Pass : public ScriptPass
run("opt_expr");
run("opt_clean");
run("check");
+ run("opt -nodffe -nosdff");
+ run("fsm");
run("opt");
run("wreduce");
run("peepopt");
@@ -316,8 +318,6 @@ struct SynthIce40Pass : public ScriptPass
}
run("alumacc");
run("opt");
- run("fsm");
- run("opt -fast");
run("memory -nomap");
run("opt_clean");
}
@@ -354,20 +354,13 @@ struct SynthIce40Pass : public ScriptPass
if (check_label("map_ffs"))
{
- if (!nodffe)
- run("dff2dffe -direct-match $_DFF_*");
- if (min_ce_use >= 0) {
- run("opt_merge");
- run(stringf("dff2dffe -unmap-mince %d", min_ce_use));
- run("simplemap t:$dff");
- }
- if ((abc9 && dff) || help_mode)
- run("zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$_SDFF*", "(only if -abc9 and -dff");
+ if (nodffe)
+ run(stringf("dfflegalize -cell $_DFF_?_ 0 -cell $_DFF_?P?_ 0 -cell $_SDFF_?P?_ 0 -cell $_DLATCH_?_ x"));
+ else
+ run(stringf("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 %d", min_ce_use));
run("techmap -map +/ice40/ff_map.v");
run("opt_expr -mux_undef");
run("simplemap");
- run("ice40_ffinit");
- run("ice40_ffssr");
run("ice40_opt -full");
}
@@ -406,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"))
@@ -424,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/Makefile.inc b/techlibs/intel/Makefile.inc
index f751e341f..b06cf5b72 100644
--- a/techlibs/intel/Makefile.inc
+++ b/techlibs/intel/Makefile.inc
@@ -5,9 +5,10 @@ $(eval $(call add_share_file,share/intel/common,techlibs/intel/common/m9k_bb.v))
$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/altpll_bb.v))
$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_m9k.txt))
$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_map_m9k.v))
+$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/ff_map.v))
# Add the cell models and mappings for the VQM backend
-families := max10 arria10gx cyclonev cyclone10lp cycloneiv cycloneive
+families := max10 cyclone10lp cycloneiv cycloneive
$(foreach family,$(families), $(eval $(call add_share_file,share/intel/$(family),techlibs/intel/$(family)/cells_sim.v)))
$(foreach family,$(families), $(eval $(call add_share_file,share/intel/$(family),techlibs/intel/$(family)/cells_map.v)))
#$(eval $(call add_share_file,share/intel/cycloneive,techlibs/intel/cycloneive/arith_map.v))
diff --git a/techlibs/intel/arria10gx/cells_map.v b/techlibs/intel/arria10gx/cells_map.v
deleted file mode 100644
index 83f5881da..000000000
--- a/techlibs/intel/arria10gx/cells_map.v
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * yosys -- Yosys Open SYnthesis Suite
- *
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-// Input buffer map
-module \$__inpad (input I, output O);
- twentynm_io_ibuf _TECHMAP_REPLACE_ (.o(O), .i(I), .ibar(1'b0));
-endmodule
-
-// Output buffer map
-module \$__outpad (input I, output O);
- twentynm_io_obuf _TECHMAP_REPLACE_ (.o(O), .i(I), .oe(1'b1));
-endmodule
-
-// LUT Map
-module \$lut (A, Y);
- parameter WIDTH = 0;
- parameter LUT = 0;
- (* force_downto *)
- input [WIDTH-1:0] A;
- output Y;
- generate
- if (WIDTH == 1) begin
- assign Y = ~A[0]; // Not need to spend 1 logic cell for such an easy function
- end else
- if (WIDTH == 2) begin
- twentynm_lcell_comb #(.lut_mask({16{LUT}}), .shared_arith("off"), .extended_lut("off"))
- _TECHMAP_REPLACE_ (.combout(Y), .dataa(A[0]), .datab(A[1]), .datac(1'b1),.datad(1'b1), .datae(1'b1), .dataf(1'b1), .datag(1'b1));
- end /*else
- if(WIDTH == 3) begin
- fiftyfivenm_lcell_comb #(.lut_mask({2{LUT}}), .sum_lutc_input("datac")) _TECHMAP_REPLACE_ (.combout(Y), .dataa(A[0]), .datab(A[1]), .datac(A[2]),.datad(1'b1));
- end else
- if(WIDTH == 4) begin
- fiftyfivenm_lcell_comb #(.lut_mask(LUT), .sum_lutc_input("datac")) _TECHMAP_REPLACE_ (.combout(Y), .dataa(A[0]), .datab(A[1]), .datac(A[2]),.datad(A[3]));
- end*/ else
- wire _TECHMAP_FAIL_ = 1;
- endgenerate
-endmodule //
-
-
diff --git a/techlibs/intel/arria10gx/cells_sim.v b/techlibs/intel/arria10gx/cells_sim.v
deleted file mode 100644
index e892b377e..000000000
--- a/techlibs/intel/arria10gx/cells_sim.v
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * yosys -- Yosys Open SYnthesis Suite
- *
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-module VCC (output V);
- assign V = 1'b1;
-endmodule // VCC
-
-module GND (output G);
- assign G = 1'b0;
-endmodule // GND
-
-/* Altera Arria 10 GX devices Input Buffer Primitive */
-module twentynm_io_ibuf (output o, input i, input ibar);
- assign ibar = ibar;
- assign o = i;
-endmodule // twentynm_io_ibuf
-
-/* Altera Arria 10 GX devices Output Buffer Primitive */
-module twentynm_io_obuf (output o, input i, input oe);
- assign o = i;
- assign oe = oe;
-endmodule // twentynm_io_obuf
-
-/* Altera Arria 10 GX LUT Primitive */
-module twentynm_lcell_comb (output combout, cout, sumout,
- input dataa, datab, datac, datad,
- input datae, dataf, datag, cin,
- input sharein);
-
-parameter lut_mask = 64'hFFFFFFFFFFFFFFFF;
-parameter dont_touch = "off";
-parameter lpm_type = "twentynm_lcell_comb";
-parameter shared_arith = "off";
-parameter extended_lut = "off";
-
-// TODO: This is still WIP
-initial begin
- $display("Simulation model is still under investigation\n");
-end
-
-endmodule // twentynm_lcell_comb
-
-
-
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/ff_map.v b/techlibs/intel/common/ff_map.v
new file mode 100644
index 000000000..e3f92adbb
--- /dev/null
+++ b/techlibs/intel/common/ff_map.v
@@ -0,0 +1,11 @@
+// Async Active Low Reset DFF
+module \$_DFFE_PN0P_ (input D, C, R, E, output Q);
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) begin
+ dffeas #(.is_wysiwyg("TRUE"), .power_up("high")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(E), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+ end else begin
+ dffeas #(.is_wysiwyg("TRUE"), .power_up("low")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(E), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+ end
+ endgenerate
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
diff --git a/techlibs/intel/common/m9k_bb.v b/techlibs/intel/common/m9k_bb.v
index b18a752f5..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
@@ -32,7 +32,7 @@ module altsyncram(data_a, address_a, wren_a, rden_a, q_a, data_b, address_b, wr
parameter outdata_reg_a = "UNREGISTERED";
parameter operation_mode = "SINGLE_PORT";
parameter intended_device_family = "MAX 10 FPGA";
- parameter outdata_reg_a = "UNREGISTERED";
+ parameter outdata_reg_b = "UNREGISTERED";
parameter lpm_type = "altsyncram";
parameter init_type = "unused";
parameter ram_block_type = "AUTO";
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 25d73711c..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
@@ -19,41 +19,6 @@
// > c60k28 (Viacheslav, VT) [at] yandex [dot] com
// > Intel FPGA technology mapping. User must first simulate the generated \
// > netlist before going to test it on board.
-// > Changelog: 1) The missing power_up parameter in the techmap introduces a problem in Quartus mapper. Fixed.
-
-// Normal mode DFF negedge clk, negedge reset
-module \$_DFF_N_ (input D, C, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
-endmodule
-// Normal mode DFF
-module \$_DFF_P_ (input D, C, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
-endmodule
-
-// Async Active Low Reset DFF
-module \$_DFF_PN0_ (input D, C, R, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up("power_up")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
-endmodule
-// Async Active High Reset DFF
-module \$_DFF_PP0_ (input D, C, R, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- wire R_i = ~ R;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R_i), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
-endmodule
-
-module \$_DFFE_PP0P_ (input D, C, E, R, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- wire E_i = ~ E;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0));
-endmodule
// Input buffer map
module \$__inpad (input I, output O);
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 56d32e586..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
@@ -19,41 +19,6 @@
// > c60k28 (Viacheslav, VT) [at] yandex [dot] com
// > Intel FPGA technology mapping. User must first simulate the generated \
// > netlist before going to test it on board.
-// > Changelog: 1) The missing power_up parameter in the techmap introduces a problem in Quartus mapper. Fixed.
-
-// Normal mode DFF negedge clk, negedge reset
-module \$_DFF_N_ (input D, C, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
-endmodule
-// Normal mode DFF
-module \$_DFF_P_ (input D, C, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
-endmodule
-
-// Async Active Low Reset DFF
-module \$_DFF_PN0_ (input D, C, R, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up("power_up")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
-endmodule
-// Async Active High Reset DFF
-module \$_DFF_PP0_ (input D, C, R, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- wire R_i = ~ R;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R_i), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
-endmodule
-
-module \$_DFFE_PP0P_ (input D, C, E, R, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- wire E_i = ~ E;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0));
-endmodule
// Input buffer map
module \$__inpad (input I, output O);
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 43a1183de..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
@@ -19,41 +19,6 @@
// > c60k28 (Viacheslav, VT) [at] yandex [dot] com
// > Intel FPGA technology mapping. User must first simulate the generated \
// > netlist before going to test it on board.
-// > Changelog: 1) The missing power_up parameter in the techmap introduces a problem in Quartus mapper. Fixed.
-
-// Normal mode DFF negedge clk, negedge reset
-module \$_DFF_N_ (input D, C, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
-endmodule
-// Normal mode DFF
-module \$_DFF_P_ (input D, C, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
-endmodule
-
-// Async Active Low Reset DFF
-module \$_DFF_PN0_ (input D, C, R, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up("power_up")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
-endmodule
-// Async Active High Reset DFF
-module \$_DFF_PP0_ (input D, C, R, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- wire R_i = ~ R;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R_i), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
-endmodule
-
-module \$_DFFE_PP0P_ (input D, C, E, R, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- wire E_i = ~ E;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0));
-endmodule
// Input buffer map
module \$__inpad (input I, output O);
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/cyclonev/cells_arith.v b/techlibs/intel/cyclonev/cells_arith.v
deleted file mode 100644
index 6a52a0f95..000000000
--- a/techlibs/intel/cyclonev/cells_arith.v
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * yosys -- Yosys Open SYnthesis Suite
- *
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-// NOTE: This is still WIP.
-(* techmap_celltype = "$alu" *)
-module _80_altera_a10gx_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;
- //output [Y_WIDTH-1:0] CO;
- output CO;
-
- wire _TECHMAP_FAIL_ = Y_WIDTH <= 4;
-
- (* 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;
- //wire [Y_WIDTH:0] C = {CO, CI};
- wire [Y_WIDTH+1:0] COx;
- wire [Y_WIDTH+1:0] C = {COx, CI};
-
- /* Start implementation */
- (* keep *) fiftyfivenm_lcell_comb #(.lut_mask(16'b0000_0000_1010_1010), .sum_lutc_input("cin")) carry_start (.cout(COx[0]), .dataa(C[0]), .datab(1'b1), .datac(1'b1), .datad(1'b1));
-
- genvar i;
- generate for (i = 0; i < Y_WIDTH; i = i + 1) begin: slice
- if(i==Y_WIDTH-1) begin
- (* keep *) fiftyfivenm_lcell_comb #(.lut_mask(16'b1111_0000_1110_0000), .sum_lutc_input("cin")) carry_end (.combout(COx[Y_WIDTH]), .dataa(1'b1), .datab(1'b1), .datac(1'b1), .datad(1'b1), .cin(C[Y_WIDTH]));
- assign CO = COx[Y_WIDTH];
- end
- else
- fiftyfivenm_lcell_comb #(.lut_mask(16'b1001_0110_1110_1000), .sum_lutc_input("cin")) arith_cell (.combout(Y[i]), .cout(COx[i+1]), .dataa(AA[i]), .datab(BB[i]), .datac(1'b1), .datad(1'b1), .cin(C[i+1]));
- end: slice
- endgenerate
- /* End implementation */
- assign X = AA ^ BB;
-
-endmodule
diff --git a/techlibs/intel/cyclonev/cells_map.v b/techlibs/intel/cyclonev/cells_map.v
deleted file mode 100644
index 8223df3c6..000000000
--- a/techlibs/intel/cyclonev/cells_map.v
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * yosys -- Yosys Open SYnthesis Suite
- *
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-// > c60k28 (Viacheslav, VT) [at] yandex [dot] com
-// > Intel FPGA technology mapping. User must first simulate the generated \
-// > netlist before going to test it on board.
-// > Changelog: 1) The missing power_up parameter in the techmap introduces a problem in Quartus mapper. Fixed.
-// 2) Cyclone V 7-input LUT function was wrong implemented. Removed abc option to map this function \
-// and added the explanation in this file instead. Such function needs to be implemented.
-
-// Normal mode DFF negedge clk, negedge reset
-module \$_DFF_N_ (input D, C, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
-endmodule
-// Normal mode DFF
-module \$_DFF_P_ (input D, C, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
-endmodule
-
-// Async Active Low Reset DFF
-module \$_DFF_PN0_ (input D, C, R, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up("power_up")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
-endmodule
-// Async Active High Reset DFF
-module \$_DFF_PP0_ (input D, C, R, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- wire R_i = ~ R;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R_i), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
-endmodule
-
-module \$_DFFE_PP0P_ (input D, C, E, R, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- wire E_i = ~ E;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0));
-endmodule
-
-// Input buffer map
-module \$__inpad (input I, output O);
- cyclonev_io_ibuf _TECHMAP_REPLACE_ (.o(O), .i(I), .ibar(1'b0));
-endmodule
-
-// Output buffer map
-module \$__outpad (input I, output O);
- cyclonev_io_obuf _TECHMAP_REPLACE_ (.o(O), .i(I), .oe(1'b1));
-endmodule
-
-// LUT Map
-module \$lut (A, Y);
- parameter WIDTH = 0;
- parameter LUT = 0;
- (* force_downto *)
- input [WIDTH-1:0] A;
- output Y;
- wire VCC;
- wire GND;
- assign {VCC,GND} = {1'b1,1'b0};
-
- generate
- if (WIDTH == 1) begin
- assign Y = ~A[0]; // Not need to spend 1 logic cell for such an easy function
- end
- else
- if (WIDTH == 2) begin
- cyclonev_lcell_comb #(.lut_mask({16{LUT}}), .shared_arith("off"), .extended_lut("off"))
- _TECHMAP_REPLACE_
- (.combout(Y),
- .dataa(A[0]),
- .datab(A[1]),
- .datac(VCC),
- .datad(VCC),
- .datae(VCC),
- .dataf(VCC),
- .datag(VCC));
- end
- else
- if(WIDTH == 3) begin
- cyclonev_lcell_comb #(.lut_mask({8{LUT}}), .shared_arith("off"), .extended_lut("off"))
- _TECHMAP_REPLACE_
- (.combout(Y),
- .dataa(A[0]),
- .datab(A[1]),
- .datac(A[2]),
- .datad(VCC),
- .datae(VCC),
- .dataf(VCC),
- .datag(VCC));
- end
- else
- if(WIDTH == 4) begin
- cyclonev_lcell_comb #(.lut_mask({4{LUT}}), .shared_arith("off"), .extended_lut("off"))
- _TECHMAP_REPLACE_
- (.combout(Y),
- .dataa(A[0]),
- .datab(A[1]),
- .datac(A[2]),
- .datad(A[3]),
- .datae(VCC),
- .dataf(VCC),
- .datag(VCC));
- end
- else
- if(WIDTH == 5) begin
- cyclonev_lcell_comb #(.lut_mask({2{LUT}}), .shared_arith("off"), .extended_lut("off"))
- _TECHMAP_REPLACE_
- (.combout(Y),
- .dataa(A[0]),
- .datab(A[1]),
- .datac(A[2]),
- .datad(A[3]),
- .datae(A[4]),
- .dataf(VCC),
- .datag(VCC));
- end
- else
- if(WIDTH == 6) begin
- cyclonev_lcell_comb #(.lut_mask(LUT), .shared_arith("off"), .extended_lut("off"))
- _TECHMAP_REPLACE_
- (.combout(Y),
- .dataa(A[0]),
- .datab(A[1]),
- .datac(A[2]),
- .datad(A[3]),
- .datae(A[4]),
- .dataf(A[5]),
- .datag(VCC));
- end
- /*else
- if(WIDTH == 7) begin
- TODO: There's not a just 7-input function on Cyclone V, see the following note:
- **Extended LUT Mode**
- Use extended LUT mode to implement a specific set of 7-input functions. The set must
- be a 2-to-1 multiplexer fed by two arbitrary 5-input functions sharing four inputs.
- [source](Device Interfaces and Integration Basics for Cyclone V Devices).
- end*/
- else
- wire _TECHMAP_FAIL_ = 1;
- endgenerate
-endmodule // lut
-
-
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 55b393080..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
@@ -19,41 +19,6 @@
// > c60k28 (Viacheslav, VT) [at] yandex [dot] com
// > Intel FPGA technology mapping. User must first simulate the generated \
// > netlist before going to test it on board.
-// > Changelog: 1) The missing power_up parameter in the techmap introduces a problem in Quartus mapper. Fixed.
-
-// Normal mode DFF negedge clk, negedge reset
-module \$_DFF_N_ (input D, C, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
-endmodule
-// Normal mode DFF
-module \$_DFF_P_ (input D, C, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
-endmodule
-
-// Async Active Low Reset DFF
-module \$_DFF_PN0_ (input D, C, R, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up("power_up")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
-endmodule
-// Async Active High Reset DFF
-module \$_DFF_PP0_ (input D, C, R, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- wire R_i = ~ R;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R_i), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
-endmodule
-
-module \$_DFFE_PP0P_ (input D, C, E, R, output Q);
- parameter WYSIWYG="TRUE";
- parameter power_up=1'bx;
- wire E_i = ~ E;
- dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0));
-endmodule
// Input buffer map
module \$__inpad (input I, output O);
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 f3709498c..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
@@ -36,11 +36,11 @@ struct SynthIntelPass : public ScriptPass {
log("\n");
log("This command runs synthesis for Intel FPGAs.\n");
log("\n");
- log(" -family <max10 | arria10gx | cyclone10lp | cyclonev | cycloneiv | cycloneive>\n");
+ log(" -family <max10 | cyclone10lp | cycloneiv | cycloneive>\n");
log(" generate the synthesis netlist for the specified family.\n");
log(" MAX10 is the default target if no family argument specified.\n");
log(" For Cyclone IV GX devices, use cycloneiv argument; for Cyclone IV E, use cycloneive.\n");
- log(" Cyclone V and Arria 10 GX devices are experimental.\n");
+ log(" For Cyclone V and Cyclone 10 GX, use the synth_intel_alm backend instead.\n");
log("\n");
log(" -top <module>\n");
log(" use the specified module as top module (default='top')\n");
@@ -147,9 +147,11 @@ struct SynthIntelPass : public ScriptPass {
if (!design->full_selection())
log_cmd_error("This command only operates on fully selected designs!\n");
+
+ if (family_opt == "cyclonev")
+ log_cmd_error("Cyclone V synthesis has been moved to synth_intel_alm.\n");
+
if (family_opt != "max10" &&
- family_opt != "arria10gx" &&
- family_opt != "cyclonev" &&
family_opt != "cycloneiv" &&
family_opt != "cycloneive" &&
family_opt != "cyclone10lp")
@@ -202,8 +204,6 @@ struct SynthIntelPass : public ScriptPass {
run("opt -fast -mux_undef -undriven -fine -full");
run("memory_map");
run("opt -undriven -fine");
- run("dff2dffe -direct-match $_DFF_*");
- run("opt -fine");
run("techmap -map +/techmap.v");
run("opt -full");
run("clean -purge");
@@ -212,11 +212,13 @@ struct SynthIntelPass : public ScriptPass {
run("abc -markgroups -dff -D 1", "(only if -retime)");
}
+ if (check_label("map_ffs")) {
+ run("dfflegalize -cell $_DFFE_PN0P_ 01");
+ run("techmap -map +/intel/common/ff_map.v");
+ }
+
if (check_label("map_luts")) {
- if (family_opt == "arria10gx" || family_opt == "cyclonev")
- run("abc -luts 2:2,3,6:5" + string(retime ? " -dff" : ""));
- else
- run("abc -lut 4" + string(retime ? " -dff" : ""));
+ run("abc -lut 4" + string(retime ? " -dff" : ""));
run("clean");
}
@@ -224,7 +226,6 @@ struct SynthIntelPass : public ScriptPass {
if (iopads || help_mode)
run("iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I", "(if -iopads)");
run(stringf("techmap -map +/intel/%s/cells_map.v", family_opt.c_str()));
- run("dffinit -highlow -ff dffeas q power_up");
run("clean -purge");
}
@@ -232,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 ed6c4510b..614d5802c 100644
--- a/techlibs/intel_alm/Makefile.inc
+++ b/techlibs/intel_alm/Makefile.inc
@@ -2,17 +2,25 @@
OBJS += techlibs/intel_alm/synth_intel_alm.o
# Techmap
+$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/abc9_map.v))
+$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/abc9_unmap.v))
+$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/abc9_model.v))
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/alm_map.v))
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/alm_sim.v))
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/arith_alm_map.v))
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/dff_map.v))
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/dff_sim.v))
+$(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))
# RAM
-bramtypes := m10k m20k
-$(foreach bramtype, $(bramtypes), $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/bram_$(bramtype).txt)))
-$(foreach bramtype, $(bramtypes), $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/bram_$(bramtype)_map.v)))
+$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/bram_m10k.txt))
+$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/bram_m20k.txt))
+$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/bram_m20k_map.v))
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/lutram_mlab.txt))
# Miscellaneous
diff --git a/techlibs/intel_alm/common/abc9_map.v b/techlibs/intel_alm/common/abc9_map.v
new file mode 100644
index 000000000..9d11bb240
--- /dev/null
+++ b/techlibs/intel_alm/common/abc9_map.v
@@ -0,0 +1,18 @@
+// This file exists to map purely-synchronous flops to ABC9 flops, while
+// mapping flops with asynchronous-clear as boxes, this is because ABC9
+// doesn't support asynchronous-clear flops in sequential synthesis.
+
+module MISTRAL_FF(
+ input DATAIN, CLK, ACLR, ENA, SCLR, SLOAD, SDATA,
+ output reg Q
+);
+
+parameter _TECHMAP_CONSTMSK_ACLR_ = 1'b0;
+
+// If the async-clear is constant, we assume it's disabled.
+if (_TECHMAP_CONSTMSK_ACLR_ != 1'b0)
+ $__MISTRAL_FF_SYNCONLY _TECHMAP_REPLACE_ (.DATAIN(DATAIN), .CLK(CLK), .ENA(ENA), .SCLR(SCLR), .SLOAD(SLOAD), .SDATA(SDATA), .Q(Q));
+else
+ wire _TECHMAP_FAIL_ = 1;
+
+endmodule
diff --git a/techlibs/intel_alm/common/abc9_model.v b/techlibs/intel_alm/common/abc9_model.v
new file mode 100644
index 000000000..8f06d3835
--- /dev/null
+++ b/techlibs/intel_alm/common/abc9_model.v
@@ -0,0 +1,10 @@
+// This is a purely-synchronous flop, that ABC9 can use for sequential synthesis.
+(* abc9_flop, lib_whitebox *)
+module $__MISTRAL_FF_SYNCONLY (
+ input DATAIN, CLK, ENA, SCLR, SLOAD, SDATA,
+ output reg Q
+);
+
+MISTRAL_FF ff (.DATAIN(DATAIN), .CLK(CLK), .ENA(ENA), .ACLR(1'b1), .SCLR(SCLR), .SLOAD(SLOAD), .SDATA(SDATA), .Q(Q));
+
+endmodule
diff --git a/techlibs/intel_alm/common/abc9_unmap.v b/techlibs/intel_alm/common/abc9_unmap.v
new file mode 100644
index 000000000..4b28866a3
--- /dev/null
+++ b/techlibs/intel_alm/common/abc9_unmap.v
@@ -0,0 +1,11 @@
+// After performing sequential synthesis, map the synchronous flops back to
+// standard MISTRAL_FF flops.
+
+module $__MISTRAL_FF_SYNCONLY (
+ input DATAIN, CLK, ENA, SCLR, SLOAD, SDATA,
+ output reg Q
+);
+
+MISTRAL_FF _TECHMAP_REPLACE_ (.DATAIN(DATAIN), .CLK(CLK), .ACLR(1'b1), .ENA(ENA), .SCLR(SCLR), .SLOAD(SLOAD), .SDATA(SDATA), .Q(Q));
+
+endmodule
diff --git a/techlibs/intel_alm/common/alm_sim.v b/techlibs/intel_alm/common/alm_sim.v
index 979c51132..242f1003f 100644
--- a/techlibs/intel_alm/common/alm_sim.v
+++ b/techlibs/intel_alm/common/alm_sim.v
@@ -69,6 +69,22 @@
`default_nettype none
+// Cyclone V LUT output timings (picoseconds):
+//
+// CARRY A B C D E F G
+// COMBOUT - 605 583 510 512 - 97 400 (LUT6)
+// COMBOUT - 602 583 457 510 302 93 483 (LUT7)
+// 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);
@@ -76,12 +92,22 @@ parameter [63:0] LUT = 64'h0000_0000_0000_0000;
`ifdef cyclonev
specify
- (A => Q) = 602;
- (B => Q) = 584;
+ (A => Q) = 605;
+ (B => Q) = 583;
(C => Q) = 510;
- (D => Q) = 510;
- (E => Q) = 339;
- (F => Q) = 94;
+ (D => Q) = 512;
+ (E => Q) = 400;
+ (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
@@ -107,11 +133,20 @@ parameter [31:0] LUT = 32'h0000_0000;
`ifdef cyclonev
specify
- (A => Q) = 584;
+ (A => Q) = 583;
(B => Q) = 510;
- (C => Q) = 510;
- (D => Q) = 339;
- (E => Q) = 94;
+ (C => Q) = 512;
+ (D => Q) = 400;
+ (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
@@ -137,9 +172,17 @@ parameter [15:0] LUT = 16'h0000;
`ifdef cyclonev
specify
(A => Q) = 510;
- (B => Q) = 510;
- (C => Q) = 339;
- (D => Q) = 94;
+ (B => Q) = 512;
+ (C => Q) = 400;
+ (D => Q) = 97;
+endspecify
+`endif
+`ifdef arriav
+specify
+ (A => Q) = 316;
+ (B => Q) = 317;
+ (C => Q) = 319;
+ (D => Q) = 76;
endspecify
`endif
`ifdef cyclone10gx
@@ -164,8 +207,15 @@ parameter [7:0] LUT = 8'h00;
`ifdef cyclonev
specify
(A => Q) = 510;
- (B => Q) = 339;
- (C => Q) = 94;
+ (B => Q) = 400;
+ (C => Q) = 97;
+endspecify
+`endif
+`ifdef arriav
+specify
+ (A => Q) = 316;
+ (B => Q) = 317;
+ (C => Q) = 76;
endspecify
`endif
`ifdef cyclone10gx
@@ -188,8 +238,14 @@ parameter [3:0] LUT = 4'h0;
`ifdef cyclonev
specify
- (A => Q) = 339;
- (B => Q) = 94;
+ (A => Q) = 400;
+ (B => Q) = 97;
+endspecify
+`endif
+`ifdef arriav
+specify
+ (A => Q) = 316;
+ (B => Q) = 76;
endspecify
`endif
`ifdef cyclone10gx
@@ -209,7 +265,12 @@ module MISTRAL_NOT(input A, output Q);
`ifdef cyclonev
specify
- (A => Q) = 94;
+ (A => Q) = 97;
+endspecify
+`endif
+`ifdef arriav
+specify
+ (A => Q) = 76;
endspecify
`endif
`ifdef cyclone10gx
@@ -222,39 +283,60 @@ 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;
`ifdef cyclonev
specify
- (A => SO) = 1283;
- (B => SO) = 1167;
- (C => SO) = 866;
- (D0 => SO) = 756;
- (D1 => SO) = 756;
- (CI => SO) = 355;
- (A => CO) = 950;
- (B => CO) = 1039;
- (C => CO) = 820;
- (D0 => CO) = 1006;
- (D1 => CO) = 1006;
- (CI => CO) = 23;
+ (A => SO) = 1342;
+ (B => SO) = 1323;
+ (C => SO) = 927;
+ (D0 => SO) = 887;
+ (D1 => SO) = 785;
+ (CI => SO) = 368;
+
+ (A => CO) = 1082;
+ (B => CO) = 1062;
+ (C => CO) = 813;
+ (D0 => CO) = 866;
+ (D1 => CO) = 1198;
+ (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;
- (B => SO) = 477;
- (C => SO) = 416;
+ (A => SO) = 644;
+ (B => SO) = 477;
+ (C => SO) = 416;
(D0 => SO) = 380;
(D1 => SO) = 431;
(CI => SO) = 276;
- (A => CO) = 525;
- (B => CO) = 433;
- (C => CO) = 712;
+
+ (A => CO) = 525;
+ (B => CO) = 433;
+ (C => CO) = 712;
(D0 => CO) = 653;
(D1 => CO) = 593;
(CI => CO) = 16;
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 837e3a330..0d9a49b7d 100644
--- a/techlibs/intel_alm/common/bram_m10k.txt
+++ b/techlibs/intel_alm/common/bram_m10k.txt
@@ -1,21 +1,15 @@
-bram __MISTRAL_M10K_SDP
+bram MISTRAL_M10K
init 0 # TODO: Re-enable when I figure out how BRAM init works
abits 13 @D8192x1
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
@@ -27,7 +21,7 @@ bram __MISTRAL_M10K_SDP
endbram
-match __MISTRAL_M10K_SDP
+match MISTRAL_M10K
min efficiency 5
make_transp
endmatch
diff --git a/techlibs/intel_alm/common/bram_m10k_map.v b/techlibs/intel_alm/common/bram_m10k_map.v
deleted file mode 100644
index 061463c3e..000000000
--- a/techlibs/intel_alm/common/bram_m10k_map.v
+++ /dev/null
@@ -1,31 +0,0 @@
-module __MISTRAL_M10K_SDP(CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
-
-parameter CFG_ABITS = 10;
-parameter CFG_DBITS = 10;
-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("m10k"),
- .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/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_map.v b/techlibs/intel_alm/common/dff_map.v
index 962be670c..1a4b5d65a 100644
--- a/techlibs/intel_alm/common/dff_map.v
+++ b/techlibs/intel_alm/common/dff_map.v
@@ -1,124 +1,13 @@
`default_nettype none
-// D flip-flops
-module \$_DFF_P_ (input D, C, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
+// D flip-flop with async reset and enable
+module \$_DFFE_PN0P_ (input D, C, R, E, output Q);
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(1'b1), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
-end else $error("Cannot implement a flip-flop that initialises to one");
+ MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(R), .ENA(E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
endmodule
-module \$_DFF_N_ (input D, C, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
+// D flip-flop with sync reset and enable (enable has priority)
+module \$_SDFFCE_PP0P_ (input D, C, R, E, output Q);
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(1'b1), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
-end else $error("Cannot implement a flip-flop that initialises to one");
-endmodule
-
-// D flip-flops with reset
-module \$_DFF_PP0_ (input D, C, R, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
- wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(~R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
-end else $error("Cannot implement a flip-flop with reset that initialises to one");
-endmodule
-
-module \$_DFF_PN0_ (input D, C, R, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
- wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
-end else $error("Cannot implement a flip-flop with reset that initialises to one");
-endmodule
-
-module \$_DFF_NP0_ (input D, C, R, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
- wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(~R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
-end else $error("Cannot implement a flip-flop with reset that initialises to one");
-endmodule
-
-module \$_DFF_NN0_ (input D, C, R, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
- wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
-end else $error("Cannot implement a flip-flop with reset that initialises to one");
-endmodule
-
-// D flip-flops with set
-module \$_DFF_PP1_ (input D, C, R, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b1;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b0) begin
- wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- wire Q_tmp;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(~D), .CLK(C), .ACLR(~R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q_tmp));
- assign Q = ~Q_tmp;
-end else $error("Cannot implement a flip-flop with set that initialises to zero");
-endmodule
-
-module \$_DFF_PN1_ (input D, C, R, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b1;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b0) begin
- wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- wire Q_tmp;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(~D), .CLK(C), .ACLR(R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q_tmp));
-end else $error("Cannot implement a flip-flop with set that initialises to zero");
-endmodule
-
-module \$_DFF_NP1_ (input D, C, R, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b1;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b0) begin
- wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- wire Q_tmp;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(~D), .CLK(~C), .ACLR(~R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q_tmp));
- assign Q = ~Q_tmp;
-end else $error("Cannot implement a flip-flop with set that initialises to zero");
-endmodule
-
-module \$_DFF_NN1_ (input D, C, R, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b1;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b0) begin
- wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- wire Q_tmp;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(~D), .CLK(~C), .ACLR(R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q_tmp));
- assign Q = ~Q_tmp;
-end else $error("Cannot implement a flip-flop with set that initialises to zero");
-endmodule
-
-// D flip-flops with clock enable
-module \$_DFFE_PP_ (input D, C, E, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
- wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(1'b1), .ENA(E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
-end else $error("Cannot implement a flip-flop with enable that initialises to one");
-endmodule
-
-module \$_DFFE_PN_ (input D, C, E, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
- wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(1'b1), .ENA(~E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
-end else $error("Cannot implement a flip-flop with enable that initialises to one");
-endmodule
-
-module \$_DFFE_NP_ (input D, C, E, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
- wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(1'b1), .ENA(E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
-end else $error("Cannot implement a flip-flop with enable that initialises to one");
-endmodule
-
-module \$_DFFE_NN_ (input D, C, E, output Q);
-parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
-if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin
- wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
- MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(1'b1), .ENA(~E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
-end else $error("Cannot implement a flip-flop with enable that initialises to one");
+ MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(1'b1), .ENA(E), .SCLR(R), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q));
endmodule
diff --git a/techlibs/intel_alm/common/dff_sim.v b/techlibs/intel_alm/common/dff_sim.v
index 32444dd46..8d58bf614 100644
--- a/techlibs/intel_alm/common/dff_sim.v
+++ b/techlibs/intel_alm/common/dff_sim.v
@@ -53,21 +53,60 @@
// Q: data output
//
// Note: the DFFEAS primitive is mostly emulated; it does not reflect what the hardware implements.
+
+(* 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
);
`ifdef cyclonev
specify
- (posedge CLK => (Q : DATAIN)) = 262;
- $setup(DATAIN, posedge CLK, 522);
+ if (ENA && ACLR !== 1'b0 && !SCLR && !SLOAD) (posedge CLK => (Q : DATAIN)) = 731;
+ if (ENA && SCLR) (posedge CLK => (Q : 1'b0)) = 890;
+ if (ENA && !SCLR && SLOAD) (posedge CLK => (Q : SDATA)) = 618;
+
+ $setup(DATAIN, posedge CLK, /* -196 */ 0);
+ $setup(ENA, posedge CLK, /* -196 */ 0);
+ $setup(SCLR, posedge CLK, /* -196 */ 0);
+ $setup(SLOAD, posedge CLK, /* -196 */ 0);
+ $setup(SDATA, posedge CLK, /* -196 */ 0);
+
+ 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
- (posedge CLK => (Q : DATAIN)) = 219;
+ // TODO (long-term): investigate these numbers.
+ // It seems relying on the Quartus Timing Analyzer was not the best idea; it's too fiddly.
+ if (ENA && ACLR !== 1'b0 && !SCLR && !SLOAD) (posedge CLK => (Q : DATAIN)) = 219;
+ if (ENA && SCLR) (posedge CLK => (Q : 1'b0)) = 219;
+ if (ENA && !SCLR && SLOAD) (posedge CLK => (Q : SDATA)) = 219;
+
$setup(DATAIN, posedge CLK, 268);
+ $setup(ENA, posedge CLK, 268);
+ $setup(SCLR, posedge CLK, 268);
+ $setup(SLOAD, posedge CLK, 268);
+ $setup(SDATA, posedge CLK, 268);
+
+ if (ACLR === 1'b0) (ACLR => Q) = 0;
endspecify
`endif
diff --git a/techlibs/intel_alm/common/dsp_map.v b/techlibs/intel_alm/common/dsp_map.v
new file mode 100644
index 000000000..e12e777a4
--- /dev/null
+++ b/techlibs/intel_alm/common/dsp_map.v
@@ -0,0 +1,51 @@
+`default_nettype none
+
+module __MUL27X27(A, B, Y);
+
+parameter A_SIGNED = 1;
+parameter B_SIGNED = 1;
+parameter A_WIDTH = 27;
+parameter B_WIDTH = 27;
+parameter Y_WIDTH = 54;
+
+input [A_WIDTH-1:0] A;
+input [B_WIDTH-1:0] B;
+output [Y_WIDTH-1:0] Y;
+
+MISTRAL_MUL27X27 _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y));
+
+endmodule
+
+
+module __MUL18X18(A, B, Y);
+
+parameter A_SIGNED = 1;
+parameter B_SIGNED = 1;
+parameter A_WIDTH = 18;
+parameter B_WIDTH = 18;
+parameter Y_WIDTH = 36;
+
+input [A_WIDTH-1:0] A;
+input [B_WIDTH-1:0] B;
+output [Y_WIDTH-1:0] Y;
+
+MISTRAL_MUL18X18 _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y));
+
+endmodule
+
+
+module __MUL9X9(A, B, Y);
+
+parameter A_SIGNED = 1;
+parameter B_SIGNED = 1;
+parameter A_WIDTH = 9;
+parameter B_WIDTH = 9;
+parameter Y_WIDTH = 18;
+
+input [A_WIDTH-1:0] A;
+input [B_WIDTH-1:0] B;
+output [Y_WIDTH-1:0] Y;
+
+MISTRAL_MUL9X9 _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y));
+
+endmodule
diff --git a/techlibs/intel_alm/common/dsp_sim.v b/techlibs/intel_alm/common/dsp_sim.v
new file mode 100644
index 000000000..3d4b5590b
--- /dev/null
+++ b/techlibs/intel_alm/common/dsp_sim.v
@@ -0,0 +1,130 @@
+`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_;
+
+if (A_SIGNED)
+ assign A_ = $signed(A);
+else
+ assign A_ = $unsigned(A);
+
+if (B_SIGNED)
+ assign B_ = $signed(B);
+else
+ assign B_ = $unsigned(B);
+
+assign Y = A_ * B_;
+
+endmodule
+
+(* abc9_box *)
+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_;
+
+if (A_SIGNED)
+ assign A_ = $signed(A);
+else
+ assign A_ = $unsigned(A);
+
+if (B_SIGNED)
+ assign B_ = $signed(B);
+else
+ assign B_ = $unsigned(B);
+
+assign Y = A_ * B_;
+
+endmodule
+
+(* abc9_box *)
+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_;
+
+if (A_SIGNED)
+ assign A_ = $signed(A);
+else
+ assign A_ = $unsigned(A);
+
+if (B_SIGNED)
+ assign B_ = $signed(B);
+else
+ assign B_ = $unsigned(B);
+
+assign Y = A_ * B_;
+
+endmodule
diff --git a/techlibs/intel_alm/common/megafunction_bb.v b/techlibs/intel_alm/common/megafunction_bb.v
index c749fa70b..d4ed95173 100644
--- a/techlibs/intel_alm/common/megafunction_bb.v
+++ b/techlibs/intel_alm/common/megafunction_bb.v
@@ -2,6 +2,306 @@
`default_nettype none
(* blackbox *)
+module altera_pll
+#(
+ parameter reference_clock_frequency = "0 ps",
+ parameter fractional_vco_multiplier = "false",
+ parameter pll_type = "General",
+ parameter pll_subtype = "General",
+ parameter number_of_clocks = 1,
+ parameter operation_mode = "internal feedback",
+ parameter deserialization_factor = 4,
+ parameter data_rate = 0,
+
+ parameter sim_additional_refclk_cycles_to_lock = 0,
+ parameter output_clock_frequency0 = "0 ps",
+ parameter phase_shift0 = "0 ps",
+ parameter duty_cycle0 = 50,
+
+ parameter output_clock_frequency1 = "0 ps",
+ parameter phase_shift1 = "0 ps",
+ parameter duty_cycle1 = 50,
+
+ parameter output_clock_frequency2 = "0 ps",
+ parameter phase_shift2 = "0 ps",
+ parameter duty_cycle2 = 50,
+
+ parameter output_clock_frequency3 = "0 ps",
+ parameter phase_shift3 = "0 ps",
+ parameter duty_cycle3 = 50,
+
+ parameter output_clock_frequency4 = "0 ps",
+ parameter phase_shift4 = "0 ps",
+ parameter duty_cycle4 = 50,
+
+ parameter output_clock_frequency5 = "0 ps",
+ parameter phase_shift5 = "0 ps",
+ parameter duty_cycle5 = 50,
+
+ parameter output_clock_frequency6 = "0 ps",
+ parameter phase_shift6 = "0 ps",
+ parameter duty_cycle6 = 50,
+
+ parameter output_clock_frequency7 = "0 ps",
+ parameter phase_shift7 = "0 ps",
+ parameter duty_cycle7 = 50,
+
+ parameter output_clock_frequency8 = "0 ps",
+ parameter phase_shift8 = "0 ps",
+ parameter duty_cycle8 = 50,
+
+ parameter output_clock_frequency9 = "0 ps",
+ parameter phase_shift9 = "0 ps",
+ parameter duty_cycle9 = 50,
+
+
+ parameter output_clock_frequency10 = "0 ps",
+ parameter phase_shift10 = "0 ps",
+ parameter duty_cycle10 = 50,
+
+ parameter output_clock_frequency11 = "0 ps",
+ parameter phase_shift11 = "0 ps",
+ parameter duty_cycle11 = 50,
+
+ parameter output_clock_frequency12 = "0 ps",
+ parameter phase_shift12 = "0 ps",
+ parameter duty_cycle12 = 50,
+
+ parameter output_clock_frequency13 = "0 ps",
+ parameter phase_shift13 = "0 ps",
+ parameter duty_cycle13 = 50,
+
+ parameter output_clock_frequency14 = "0 ps",
+ parameter phase_shift14 = "0 ps",
+ parameter duty_cycle14 = 50,
+
+ parameter output_clock_frequency15 = "0 ps",
+ parameter phase_shift15 = "0 ps",
+ parameter duty_cycle15 = 50,
+
+ parameter output_clock_frequency16 = "0 ps",
+ parameter phase_shift16 = "0 ps",
+ parameter duty_cycle16 = 50,
+
+ parameter output_clock_frequency17 = "0 ps",
+ parameter phase_shift17 = "0 ps",
+ parameter duty_cycle17 = 50,
+
+ parameter clock_name_0 = "",
+ parameter clock_name_1 = "",
+ parameter clock_name_2 = "",
+ parameter clock_name_3 = "",
+ parameter clock_name_4 = "",
+ parameter clock_name_5 = "",
+ parameter clock_name_6 = "",
+ parameter clock_name_7 = "",
+ parameter clock_name_8 = "",
+
+ parameter clock_name_global_0 = "false",
+ parameter clock_name_global_1 = "false",
+ parameter clock_name_global_2 = "false",
+ parameter clock_name_global_3 = "false",
+ parameter clock_name_global_4 = "false",
+ parameter clock_name_global_5 = "false",
+ parameter clock_name_global_6 = "false",
+ parameter clock_name_global_7 = "false",
+ parameter clock_name_global_8 = "false",
+
+ parameter m_cnt_hi_div = 1,
+ parameter m_cnt_lo_div = 1,
+ parameter m_cnt_bypass_en = "false",
+ parameter m_cnt_odd_div_duty_en = "false",
+ parameter n_cnt_hi_div = 1,
+ parameter n_cnt_lo_div = 1,
+ parameter n_cnt_bypass_en = "false",
+ parameter n_cnt_odd_div_duty_en = "false",
+ parameter c_cnt_hi_div0 = 1,
+ parameter c_cnt_lo_div0 = 1,
+ parameter c_cnt_bypass_en0 = "false",
+ parameter c_cnt_in_src0 = "ph_mux_clk",
+ parameter c_cnt_odd_div_duty_en0 = "false",
+ parameter c_cnt_prst0 = 1,
+ parameter c_cnt_ph_mux_prst0 = 0,
+ parameter c_cnt_hi_div1 = 1,
+ parameter c_cnt_lo_div1 = 1,
+ parameter c_cnt_bypass_en1 = "false",
+ parameter c_cnt_in_src1 = "ph_mux_clk",
+ parameter c_cnt_odd_div_duty_en1 = "false",
+ parameter c_cnt_prst1 = 1,
+ parameter c_cnt_ph_mux_prst1 = 0,
+ parameter c_cnt_hi_div2 = 1,
+ parameter c_cnt_lo_div2 = 1,
+ parameter c_cnt_bypass_en2 = "false",
+ parameter c_cnt_in_src2 = "ph_mux_clk",
+ parameter c_cnt_odd_div_duty_en2 = "false",
+ parameter c_cnt_prst2 = 1,
+ parameter c_cnt_ph_mux_prst2 = 0,
+ parameter c_cnt_hi_div3 = 1,
+ parameter c_cnt_lo_div3 = 1,
+ parameter c_cnt_bypass_en3 = "false",
+ parameter c_cnt_in_src3 = "ph_mux_clk",
+ parameter c_cnt_odd_div_duty_en3 = "false",
+ parameter c_cnt_prst3 = 1,
+ parameter c_cnt_ph_mux_prst3 = 0,
+ parameter c_cnt_hi_div4 = 1,
+ parameter c_cnt_lo_div4 = 1,
+ parameter c_cnt_bypass_en4 = "false",
+ parameter c_cnt_in_src4 = "ph_mux_clk",
+ parameter c_cnt_odd_div_duty_en4 = "false",
+ parameter c_cnt_prst4 = 1,
+ parameter c_cnt_ph_mux_prst4 = 0,
+ parameter c_cnt_hi_div5 = 1,
+ parameter c_cnt_lo_div5 = 1,
+ parameter c_cnt_bypass_en5 = "false",
+ parameter c_cnt_in_src5 = "ph_mux_clk",
+ parameter c_cnt_odd_div_duty_en5 = "false",
+ parameter c_cnt_prst5 = 1,
+ parameter c_cnt_ph_mux_prst5 = 0,
+ parameter c_cnt_hi_div6 = 1,
+ parameter c_cnt_lo_div6 = 1,
+ parameter c_cnt_bypass_en6 = "false",
+ parameter c_cnt_in_src6 = "ph_mux_clk",
+ parameter c_cnt_odd_div_duty_en6 = "false",
+ parameter c_cnt_prst6 = 1,
+ parameter c_cnt_ph_mux_prst6 = 0,
+ parameter c_cnt_hi_div7 = 1,
+ parameter c_cnt_lo_div7 = 1,
+ parameter c_cnt_bypass_en7 = "false",
+ parameter c_cnt_in_src7 = "ph_mux_clk",
+ parameter c_cnt_odd_div_duty_en7 = "false",
+ parameter c_cnt_prst7 = 1,
+ parameter c_cnt_ph_mux_prst7 = 0,
+ parameter c_cnt_hi_div8 = 1,
+ parameter c_cnt_lo_div8 = 1,
+ parameter c_cnt_bypass_en8 = "false",
+ parameter c_cnt_in_src8 = "ph_mux_clk",
+ parameter c_cnt_odd_div_duty_en8 = "false",
+ parameter c_cnt_prst8 = 1,
+ parameter c_cnt_ph_mux_prst8 = 0,
+ parameter c_cnt_hi_div9 = 1,
+ parameter c_cnt_lo_div9 = 1,
+ parameter c_cnt_bypass_en9 = "false",
+ parameter c_cnt_in_src9 = "ph_mux_clk",
+ parameter c_cnt_odd_div_duty_en9 = "false",
+ parameter c_cnt_prst9 = 1,
+ parameter c_cnt_ph_mux_prst9 = 0,
+ parameter c_cnt_hi_div10 = 1,
+ parameter c_cnt_lo_div10 = 1,
+ parameter c_cnt_bypass_en10 = "false",
+ parameter c_cnt_in_src10 = "ph_mux_clk",
+ parameter c_cnt_odd_div_duty_en10 = "false",
+ parameter c_cnt_prst10 = 1,
+ parameter c_cnt_ph_mux_prst10 = 0,
+ parameter c_cnt_hi_div11 = 1,
+ parameter c_cnt_lo_div11 = 1,
+ parameter c_cnt_bypass_en11 = "false",
+ parameter c_cnt_in_src11 = "ph_mux_clk",
+ parameter c_cnt_odd_div_duty_en11 = "false",
+ parameter c_cnt_prst11 = 1,
+ parameter c_cnt_ph_mux_prst11 = 0,
+ parameter c_cnt_hi_div12 = 1,
+ parameter c_cnt_lo_div12 = 1,
+ parameter c_cnt_bypass_en12 = "false",
+ parameter c_cnt_in_src12 = "ph_mux_clk",
+ parameter c_cnt_odd_div_duty_en12 = "false",
+ parameter c_cnt_prst12 = 1,
+ parameter c_cnt_ph_mux_prst12 = 0,
+ parameter c_cnt_hi_div13 = 1,
+ parameter c_cnt_lo_div13 = 1,
+ parameter c_cnt_bypass_en13 = "false",
+ parameter c_cnt_in_src13 = "ph_mux_clk",
+ parameter c_cnt_odd_div_duty_en13 = "false",
+ parameter c_cnt_prst13 = 1,
+ parameter c_cnt_ph_mux_prst13 = 0,
+ parameter c_cnt_hi_div14 = 1,
+ parameter c_cnt_lo_div14 = 1,
+ parameter c_cnt_bypass_en14 = "false",
+ parameter c_cnt_in_src14 = "ph_mux_clk",
+ parameter c_cnt_odd_div_duty_en14 = "false",
+ parameter c_cnt_prst14 = 1,
+ parameter c_cnt_ph_mux_prst14 = 0,
+ parameter c_cnt_hi_div15 = 1,
+ parameter c_cnt_lo_div15 = 1,
+ parameter c_cnt_bypass_en15 = "false",
+ parameter c_cnt_in_src15 = "ph_mux_clk",
+ parameter c_cnt_odd_div_duty_en15 = "false",
+ parameter c_cnt_prst15 = 1,
+ parameter c_cnt_ph_mux_prst15 = 0,
+ parameter c_cnt_hi_div16 = 1,
+ parameter c_cnt_lo_div16 = 1,
+ parameter c_cnt_bypass_en16 = "false",
+ parameter c_cnt_in_src16 = "ph_mux_clk",
+ parameter c_cnt_odd_div_duty_en16 = "false",
+ parameter c_cnt_prst16 = 1,
+ parameter c_cnt_ph_mux_prst16 = 0,
+ parameter c_cnt_hi_div17 = 1,
+ parameter c_cnt_lo_div17 = 1,
+ parameter c_cnt_bypass_en17 = "false",
+ parameter c_cnt_in_src17 = "ph_mux_clk",
+ parameter c_cnt_odd_div_duty_en17 = "false",
+ parameter c_cnt_prst17 = 1,
+ parameter c_cnt_ph_mux_prst17 = 0,
+ parameter pll_vco_div = 1,
+ parameter pll_slf_rst = "false",
+ parameter pll_bw_sel = "low",
+ parameter pll_output_clk_frequency = "0 MHz",
+ parameter pll_cp_current = 0,
+ parameter pll_bwctrl = 0,
+ parameter pll_fractional_division = 1,
+ parameter pll_fractional_cout = 24,
+ parameter pll_dsm_out_sel = "1st_order",
+ parameter mimic_fbclk_type = "gclk",
+ parameter pll_fbclk_mux_1 = "glb",
+ parameter pll_fbclk_mux_2 = "fb_1",
+ parameter pll_m_cnt_in_src = "ph_mux_clk",
+ parameter pll_vcoph_div = 1,
+ parameter refclk1_frequency = "0 MHz",
+ parameter pll_clkin_0_src = "clk_0",
+ parameter pll_clkin_1_src = "clk_0",
+ parameter pll_clk_loss_sw_en = "false",
+ parameter pll_auto_clk_sw_en = "false",
+ parameter pll_manu_clk_sw_en = "false",
+ parameter pll_clk_sw_dly = 0,
+ parameter pll_extclk_0_cnt_src = "pll_extclk_cnt_src_vss",
+ parameter pll_extclk_1_cnt_src = "pll_extclk_cnt_src_vss"
+) (
+ //input
+ input refclk,
+ input refclk1,
+ input fbclk,
+ input rst,
+ input phase_en,
+ input updn,
+ input [2:0] num_phase_shifts,
+ input scanclk,
+ input [4:0] cntsel,
+ input [63:0] reconfig_to_pll,
+ input extswitch,
+ input adjpllin,
+ input cclk,
+
+ //output
+ output [ number_of_clocks -1 : 0] outclk,
+ output fboutclk,
+ output locked,
+ output phase_done,
+ output [63:0] reconfig_from_pll,
+ output activeclk,
+ output [1:0] clkbad,
+ output [7:0] phout,
+ output [1:0] lvds_clk,
+ output [1:0] loaden,
+ output [1:0] extclk_out,
+ output [ number_of_clocks -1 : 0] cascade_out,
+
+ //inout
+ inout zdbfbclk
+);
+
+endmodule
+
+
+(* blackbox *)
module altera_std_synchronizer(clk, din, dout, reset_n);
parameter depth = 2;
@@ -14,6 +314,137 @@ output dout;
endmodule
(* blackbox *)
+module altddio_in (
+ datain, // required port, DDR input data
+ inclock, // required port, input reference clock to sample data by
+ inclocken, // enable data clock
+ aset, // asynchronous set
+ aclr, // asynchronous clear
+ sset, // synchronous set
+ sclr, // synchronous clear
+ dataout_h, // data sampled at the rising edge of inclock
+ dataout_l // data sampled at the falling edge of inclock
+);
+
+parameter width = 1;
+parameter power_up_high = "OFF";
+parameter invert_input_clocks = "OFF";
+parameter intended_device_family = "Stratix";
+parameter lpm_type = "altddio_in";
+parameter lpm_hint = "UNUSED";
+
+input [width-1:0] datain;
+input inclock;
+input inclocken;
+input aset;
+input aclr;
+input sset;
+input sclr;
+
+output [width-1:0] dataout_h;
+output [width-1:0] dataout_l;
+
+endmodule
+
+
+(* blackbox *)
+module altddio_out (
+ datain_h,
+ datain_l,
+ outclock,
+ outclocken,
+ aset,
+ aclr,
+ sset,
+ sclr,
+ oe,
+ dataout,
+ oe_out
+);
+
+parameter width = 1;
+parameter power_up_high = "OFF";
+parameter oe_reg = "UNUSED";
+parameter extend_oe_disable = "UNUSED";
+parameter intended_device_family = "Stratix";
+parameter invert_output = "OFF";
+parameter lpm_type = "altddio_out";
+parameter lpm_hint = "UNUSED";
+
+input [width-1:0] datain_h;
+input [width-1:0] datain_l;
+input outclock;
+input outclocken;
+input aset;
+input aclr;
+input sset;
+input sclr;
+input oe;
+
+output [width-1:0] dataout;
+output [width-1:0] oe_out;
+
+endmodule
+
+
+(* blackbox *)
+module altddio_bidir (
+ datain_h,
+ datain_l,
+ inclock,
+ inclocken,
+ outclock,
+ outclocken,
+ aset,
+ aclr,
+ sset,
+ sclr,
+ oe,
+ dataout_h,
+ dataout_l,
+ combout,
+ oe_out,
+ dqsundelayedout,
+ padio
+);
+
+// GLOBAL PARAMETER DECLARATION
+parameter width = 1; // required parameter
+parameter power_up_high = "OFF";
+parameter oe_reg = "UNUSED";
+parameter extend_oe_disable = "UNUSED";
+parameter implement_input_in_lcell = "UNUSED";
+parameter invert_output = "OFF";
+parameter intended_device_family = "Stratix";
+parameter lpm_type = "altddio_bidir";
+parameter lpm_hint = "UNUSED";
+
+// INPUT PORT DECLARATION
+input [width-1:0] datain_h;
+input [width-1:0] datain_l;
+input inclock;
+input inclocken;
+input outclock;
+input outclocken;
+input aset;
+input aclr;
+input sset;
+input sclr;
+input oe;
+
+// OUTPUT PORT DECLARATION
+output [width-1:0] dataout_h;
+output [width-1:0] dataout_l;
+output [width-1:0] combout;
+output [width-1:0] oe_out;
+output [width-1:0] dqsundelayedout;
+// BIDIRECTIONAL PORT DECLARATION
+inout [width-1:0] padio;
+
+endmodule
+
+
+(* blackbox *)
module altiobuf_in(datain, dataout);
parameter enable_bus_hold = "FALSE";
@@ -129,3 +560,158 @@ output [data_width-1:0] portbdataout;
input ena0, clk0, clk1;
endmodule
+
+(* blackbox *)
+module cyclonev_mac(ax, ay, resulta);
+
+parameter ax_width = 9;
+parameter signed_max = "true";
+parameter ay_scan_in_width = 9;
+parameter signed_may = "true";
+parameter result_a_width = 18;
+parameter operation_mode = "M9x9";
+
+input [ax_width-1:0] ax;
+input [ay_scan_in_width-1:0] ay;
+output [result_a_width-1:0] resulta;
+
+endmodule
+
+(* blackbox *)
+module cyclone10gx_mac(ax, ay, resulta);
+
+parameter ax_width = 18;
+parameter signed_max = "true";
+parameter ay_scan_in_width = 18;
+parameter signed_may = "true";
+parameter result_a_width = 36;
+parameter operation_mode = "M18X18_FULL";
+
+input [ax_width-1:0] ax;
+input [ay_scan_in_width-1:0] ay;
+output [result_a_width-1:0] resulta;
+
+endmodule
+
+(* blackbox *)
+module cyclonev_ram_block(portaaddr, portadatain, portawe, portbaddr, portbdataout, portbre, clk0);
+
+parameter operation_mode = "dual_port";
+parameter logical_ram_name = "";
+parameter port_a_address_width = 10;
+parameter port_a_data_width = 10;
+parameter port_a_logical_ram_depth = 1024;
+parameter port_a_logical_ram_width = 10;
+parameter port_a_first_address = 0;
+parameter port_a_last_address = 1023;
+parameter port_a_first_bit_number = 0;
+parameter port_b_address_width = 10;
+parameter port_b_data_width = 10;
+parameter port_b_logical_ram_depth = 1024;
+parameter port_b_logical_ram_width = 10;
+parameter port_b_first_address = 0;
+parameter port_b_last_address = 1023;
+parameter port_b_first_bit_number = 0;
+parameter port_b_address_clock = "clock0";
+parameter port_b_read_enable_clock = "clock0";
+parameter mem_init0 = "";
+parameter mem_init1 = "";
+parameter mem_init2 = "";
+parameter mem_init3 = "";
+parameter mem_init4 = "";
+
+input [port_a_address_width-1:0] portaaddr;
+input [port_b_address_width-1:0] portbaddr;
+input [port_a_data_width-1:0] portadatain;
+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 ae79b19a4..370e17f27 100644
--- a/techlibs/intel_alm/common/mem_sim.v
+++ b/techlibs/intel_alm/common/mem_sim.v
@@ -48,13 +48,108 @@
// the following model because it's very difficult to trigger this in practice
// as clock cycles will be much longer than any potential blip of 'x, so the
// model can be treated as always returning a defined result.
-module MISTRAL_MLAB(input [4:0] A1ADDR, input A1DATA, A1EN, CLK1, input [4:0] B1ADDR, output B1DATA);
+
+(* abc9_box, lib_whitebox *)
+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);
+ $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
+
always @(posedge CLK1)
if (A1EN) mem[A1ADDR] <= A1DATA;
assign B1DATA = mem[B1ADDR];
endmodule
+
+// The M10K
+// --------
+// TODO
+
+module MISTRAL_M10K(CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+
+parameter CFG_ABITS = 10;
+parameter CFG_DBITS = 10;
+
+(* clkbuf_sink *) input CLK1;
+input [CFG_ABITS-1:0] A1ADDR, B1ADDR;
+input [CFG_DBITS-1:0] A1DATA;
+input A1EN, B1EN;
+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, 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)) = 787;
+endspecify
+`endif
+
+always @(posedge CLK1) begin
+ if (A1EN)
+ mem[(A1ADDR + 1) * CFG_DBITS - 1 : A1ADDR * CFG_DBITS] <= A1DATA;
+
+ if (B1EN)
+ B1DATA <= mem[(B1ADDR + 1) * CFG_DBITS - 1 : B1ADDR * CFG_DBITS];
+end
+
+endmodule
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 c40a4e02d..5850f6907 100644
--- a/techlibs/intel_alm/common/quartus_rename.v
+++ b/techlibs/intel_alm/common/quartus_rename.v
@@ -1,10 +1,29 @@
`ifdef cyclonev
`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);
@@ -86,6 +105,8 @@ endmodule
module MISTRAL_MLAB(input [4:0] A1ADDR, input A1DATA, A1EN, CLK1, input [4:0] B1ADDR, output B1DATA);
+parameter _TECHMAP_CELLNAME_ = "";
+
// Here we get to an unfortunate situation. The cell has a mem_init0 parameter,
// which takes in a hexadecimal string that could be used to initialise RAM.
// In the vendor simulation models, this appears to work fine, but Quartus,
@@ -97,7 +118,7 @@ module MISTRAL_MLAB(input [4:0] A1ADDR, input A1DATA, A1EN, CLK1, input [4:0] B1
// or an undocumented way to get Quartus to initialise from mem_init0 is found.
`MLAB #(
- .logical_ram_name("MISTRAL_MLAB"),
+ .logical_ram_name(_TECHMAP_CELLNAME_),
.logical_ram_depth(32),
.logical_ram_width(1),
.mixed_port_feed_through_mode("Dont Care"),
@@ -119,3 +140,167 @@ module MISTRAL_MLAB(input [4:0] A1ADDR, input A1DATA, A1EN, CLK1, input [4:0] B1
);
endmodule
+
+
+module MISTRAL_M10K(A1ADDR, A1DATA, A1EN, CLK1, B1ADDR, B1DATA, B1EN);
+
+parameter CFG_ABITS = 10;
+parameter CFG_DBITS = 10;
+
+parameter _TECHMAP_CELLNAME_ = "";
+
+input [CFG_ABITS-1:0] A1ADDR, B1ADDR;
+input [CFG_DBITS-1:0] A1DATA;
+input CLK1, A1EN, B1EN;
+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.
+
+`RAM_BLOCK #(
+ .operation_mode("dual_port"),
+ .logical_ram_name(_TECHMAP_CELLNAME_),
+ .port_a_address_width(CFG_ABITS),
+ .port_a_data_width(CFG_DBITS),
+ .port_a_logical_ram_depth(2**CFG_ABITS),
+ .port_a_logical_ram_width(CFG_DBITS),
+ .port_a_first_address(0),
+ .port_a_last_address(2**CFG_ABITS - 1),
+ .port_a_first_bit_number(0),
+ .port_b_address_width(CFG_ABITS),
+ .port_b_data_width(CFG_DBITS),
+ .port_b_logical_ram_depth(2**CFG_ABITS),
+ .port_b_logical_ram_width(CFG_DBITS),
+ .port_b_first_address(0),
+ .port_b_last_address(2**CFG_ABITS - 1),
+ .port_b_first_bit_number(0),
+ .port_b_address_clock("clock0"),
+ .port_b_read_enable_clock("clock0")
+) _TECHMAP_REPLACE_ (
+ .portaaddr(A1ADDR),
+ .portadatain(A1DATA),
+ .portawe(A1EN),
+ .portbaddr(B1ADDR),
+ .portbdataout(B1DATA),
+ .portbre(B1EN),
+ .clk0(CLK1)
+);
+
+endmodule
+
+
+module MISTRAL_MUL27X27(input [26:0] A, B, output [53:0] Y);
+
+parameter A_SIGNED = 1;
+parameter B_SIGNED = 1;
+
+`MAC #(
+ .ax_width(27),
+ .signed_max(A_SIGNED ? "true" : "false"),
+ .ay_scan_in_width(27),
+ .signed_may(B_SIGNED ? "true" : "false"),
+ .result_a_width(54),
+ .operation_mode("M27x27")
+) _TECHMAP_REPLACE_ (
+ .ax(A),
+ .ay(B),
+ .resulta(Y)
+);
+
+endmodule
+
+
+module MISTRAL_MUL18X18(input [17:0] A, B, output [35:0] Y);
+
+parameter A_SIGNED = 1;
+parameter B_SIGNED = 1;
+
+`MAC #(
+ .ax_width(18),
+ .signed_max(A_SIGNED ? "true" : "false"),
+ .ay_scan_in_width(18),
+ .signed_may(B_SIGNED ? "true" : "false"),
+ .result_a_width(36),
+ .operation_mode("M18x18_FULL")
+) _TECHMAP_REPLACE_ (
+ .ax(A),
+ .ay(B),
+ .resulta(Y)
+);
+
+endmodule
+
+
+module MISTRAL_MUL9X9(input [8:0] A, B, output [17:0] Y);
+
+parameter A_SIGNED = 1;
+parameter B_SIGNED = 1;
+
+`MAC #(
+ .ax_width(9),
+ .signed_max(A_SIGNED ? "true" : "false"),
+ .ay_scan_in_width(9),
+ .signed_may(B_SIGNED ? "true" : "false"),
+ .result_a_width(18),
+ .operation_mode("M9x9")
+) _TECHMAP_REPLACE_ (
+ .ax(A),
+ .ay(B),
+ .resulta(Y)
+);
+
+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/cyclonev/cells_sim.v b/techlibs/intel_alm/cyclonev/cells_sim.v
index 9b2a10e72..14bb756cf 100644
--- a/techlibs/intel/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 fabfc9003..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
@@ -38,20 +38,27 @@ struct SynthIntelALMPass : public ScriptPass {
log("This command runs synthesis for ALM-based Intel FPGAs.\n");
log("\n");
log(" -top <module>\n");
- log(" use the specified module as top module (default='top')\n");
+ log(" use the specified module as top module\n");
log("\n");
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(" -quartus\n");
- log(" output a netlist using Quartus cells instead of MISTRAL_* cells\n");
- log("\n");
log(" -vqm <file>\n");
log(" write the design to the specified Verilog Quartus Mapping File. Writing of an\n");
log(" output file is omitted if this parameter is not specified. Implies -quartus.\n");
log("\n");
+ log(" -noflatten\n");
+ log(" do not flatten design before synthesis; useful for per-module area statistics\n");
+ log("\n");
+ log(" -quartus\n");
+ log(" output a netlist using Quartus cells instead of MISTRAL_* cells\n");
+ log("\n");
+ log(" -dff\n");
+ log(" pass DFFs to ABC to perform sequential logic optimisations (EXPERIMENTAL)\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");
@@ -63,8 +70,14 @@ struct SynthIntelALMPass : public ScriptPass {
log(" -nobram\n");
log(" do not use block RAM cells in output netlist\n");
log("\n");
- log(" -noflatten\n");
- log(" do not flatten design before synthesis\n");
+ 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();
@@ -72,7 +85,7 @@ struct SynthIntelALMPass : public ScriptPass {
}
string top_opt, family_opt, bram_type, vout_file;
- bool flatten, quartus, nolutram, nobram;
+ bool flatten, quartus, nolutram, nobram, dff, nodsp, noiopad, noclkbuf;
void clear_flags() override
{
@@ -84,6 +97,10 @@ struct SynthIntelALMPass : public ScriptPass {
quartus = false;
nolutram = false;
nobram = false;
+ dff = false;
+ nodsp = false;
+ noiopad = false;
+ noclkbuf = false;
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
@@ -126,10 +143,26 @@ struct SynthIntelALMPass : public ScriptPass {
nobram = true;
continue;
}
+ if (args[argidx] == "-nodsp") {
+ nodsp = true;
+ continue;
+ }
if (args[argidx] == "-noflatten") {
flatten = false;
continue;
}
+ if (args[argidx] == "-dff") {
+ dff = true;
+ continue;
+ }
+ if (args[argidx] == "-noiopad") {
+ noiopad = true;
+ continue;
+ }
+ if (args[argidx] == "-noclkbuf") {
+ noclkbuf = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -137,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());
}
@@ -161,32 +198,72 @@ struct SynthIntelALMPass : public ScriptPass {
}
if (check_label("begin")) {
- run(stringf("read_verilog -sv -lib +/intel/%s/cells_sim.v", family_opt.c_str()));
+ if (family_opt == "cyclonev")
+ run(stringf("read_verilog -sv -lib +/intel_alm/%s/cells_sim.v", family_opt.c_str()));
run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/alm_sim.v", family_opt.c_str()));
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");
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
}
- if (flatten && check_label("flatten", "(unless -noflatten)")) {
+ if (check_label("coarse")) {
run("proc");
- run("flatten");
+ if (flatten || help_mode)
+ run("flatten", "(skip if -noflatten)");
run("tribuf -logic");
run("deminout");
- }
-
- if (check_label("coarse")) {
- run("synth -run coarse -lut 6");
- run("techmap -map +/intel_alm/common/arith_alm_map.v");
+ 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=6");
+ run("opt_expr");
+ run("opt_clean");
+ if (help_mode) {
+ run("techmap -map +/mul2dsp.v [...]", "(unless -nodsp)");
+ } else if (!nodsp) {
+ // 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" || 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");
+ run("chtype -set $mul t:$__soft_mul");
+ run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=9 -D DSP_B_MAXWIDTH=9 -D DSP_A_MINWIDTH=4 -D DSP_B_MINWIDTH=4 -D DSP_NAME=__MUL9X9");
+ run("chtype -set $mul t:$__soft_mul");
+ } else if (family_opt == "cyclone10gx") {
+ run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 -D DSP_A_MINWIDTH=4 -D DSP_B_MINWIDTH=4 -D DSP_NAME=__MUL18X18");
+ run("chtype -set $mul t:$__soft_mul");
+ }
+ }
+ 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");
+ run("opt_clean");
}
if (!nobram && check_label("map_bram", "(skip if -nobram)")) {
run(stringf("memory_bram -rules +/intel_alm/common/bram_%s.txt", bram_type.c_str()));
- run(stringf("techmap -map +/intel_alm/common/bram_%s_map.v", bram_type.c_str()));
+ if (help_mode || bram_type != "m10k")
+ run(stringf("techmap -map +/intel_alm/common/bram_%s_map.v", bram_type.c_str()));
}
if (!nolutram && check_label("map_lutram", "(skip if -nolutram)")) {
@@ -199,17 +276,19 @@ struct SynthIntelALMPass : public ScriptPass {
}
if (check_label("map_ffs")) {
- run("dff2dffe");
- // As mentioned in common/dff_sim.v, Intel flops power up to zero,
- // so use `zinit` to add inverters where needed.
- run("zinit");
- run("techmap -map +/techmap.v -map +/intel_alm/common/dff_map.v");
+ run("techmap");
+ run("dfflegalize -cell $_DFFE_PN0P_ 0 -cell $_SDFFCE_PP0P_ 0");
+ 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")) {
- run("abc9 -maxlut 6 -W 200");
+ run("techmap -map +/intel_alm/common/abc9_map.v");
+ run(stringf("abc9 %s -maxlut 6 -W 600", help_mode ? "[-dff]" : dff ? "-dff" : ""));
+ run("techmap -map +/intel_alm/common/abc9_unmap.v");
run("techmap -map +/intel_alm/common/alm_map.v");
run("opt -fast");
run("autoname");
@@ -220,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/Makefile.inc b/techlibs/machxo2/Makefile.inc
new file mode 100644
index 000000000..6f6f6ce94
--- /dev/null
+++ b/techlibs/machxo2/Makefile.inc
@@ -0,0 +1,5 @@
+
+OBJS += techlibs/machxo2/synth_machxo2.o
+
+$(eval $(call add_share_file,share/machxo2,techlibs/machxo2/cells_map.v))
+$(eval $(call add_share_file,share/machxo2,techlibs/machxo2/cells_sim.v))
diff --git a/techlibs/machxo2/cells_map.v b/techlibs/machxo2/cells_map.v
new file mode 100644
index 000000000..9c370f246
--- /dev/null
+++ b/techlibs/machxo2/cells_map.v
@@ -0,0 +1,34 @@
+module \$lut (A, Y);
+ parameter WIDTH = 0;
+ parameter LUT = 0;
+ input [WIDTH-1:0] A;
+ output Y;
+
+ localparam rep = 1<<(4-WIDTH);
+ wire [3:0] I;
+
+ generate
+ if(WIDTH == 1) begin
+ assign I = {1'b0, 1'b0, 1'b0, A[0]};
+ end else if(WIDTH == 2) begin
+ assign I = {1'b0, 1'b0, A[1], A[0]};
+ end else if(WIDTH == 3) begin
+ assign I = {1'b0, A[2], A[1], A[0]};
+ end else if(WIDTH == 4) begin
+ assign I = {A[3], A[2], A[1], A[0]};
+ end else begin
+ wire _TECHMAP_FAIL_ = 1;
+ end
+ endgenerate
+
+ LUT4 #(.INIT({rep{LUT}})) _TECHMAP_REPLACE_ (.A(I[0]), .B(I[1]), .C(I[2]), .D(I[3]), .Z(Y));
+endmodule
+
+// DFFs
+module \$_DFF_P_ (input D, C, output Q); FACADE_FF #(.CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
+
+// 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, 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
new file mode 100644
index 000000000..dc68a3127
--- /dev/null
+++ b/techlibs/machxo2/cells_sim.v
@@ -0,0 +1,212 @@
+module LUT4 #(
+ parameter [15:0] INIT = 0
+) (
+ input A, B, C, D,
+ output Z
+);
+ // This form of LUT propagates as few x's as possible.
+ wire [7:0] s3 = D ? INIT[15:8] : INIT[7:0];
+ wire [3:0] s2 = C ? s3[ 7:4] : s3[3:0];
+ wire [1:0] s1 = B ? s2[ 3:2] : s2[1:0];
+ assign Z = A ? s1[1] : s1[0];
+endmodule
+
+module FACADE_FF #(
+ parameter GSR = "ENABLED",
+ parameter CEMUX = "1",
+ parameter CLKMUX = "0",
+ parameter LSRMUX = "LSR",
+ parameter LSRONMUX = "LSRMUX",
+ parameter SRMODE = "LSR_OVER_CE",
+ parameter REGSET = "SET",
+ parameter REGMODE = "FF"
+) (
+ input CLK, DI, LSR, CE,
+ output reg Q
+);
+
+ wire muxce;
+ generate
+ case (CEMUX)
+ "1": assign muxce = 1'b1;
+ "0": assign muxce = 1'b0;
+ "INV": assign muxce = ~CE;
+ default: assign muxce = CE;
+ endcase
+ endgenerate
+
+ wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR;
+ wire muxlsron = (LSRONMUX == "LSRMUX") ? muxlsr : 1'b0;
+ wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK;
+ wire srval = (REGSET == "SET") ? 1'b1 : 1'b0;
+
+ initial Q = srval;
+
+ generate
+ if (REGMODE == "FF") begin
+ if (SRMODE == "ASYNC") begin
+ always @(posedge muxclk, posedge muxlsron)
+ if (muxlsron)
+ Q <= srval;
+ else if (muxce)
+ Q <= DI;
+ end else begin
+ always @(posedge muxclk)
+ if (muxlsron)
+ Q <= srval;
+ else if (muxce)
+ Q <= DI;
+ end
+ end else if (REGMODE == "LATCH") begin
+ ERROR_UNSUPPORTED_FF_MODE error();
+ end else begin
+ ERROR_UNKNOWN_FF_MODE error();
+ end
+ endgenerate
+endmodule
+
+/* For consistency with ECP5; represents F0/F1 => OFX0 mux in a slice. */
+module PFUMX (input ALUT, BLUT, C0, output Z);
+ assign Z = C0 ? ALUT : BLUT;
+endmodule
+
+/* For consistency with ECP5; represents FXA/FXB => OFX1 mux in a slice. */
+module L6MUX21 (input D0, D1, SD, output Z);
+ assign Z = SD ? D1 : D0;
+endmodule
+
+/* For consistency, input order matches TRELLIS_SLICE even though the BELs in
+prjtrellis were filled in clockwise order from bottom left. */
+module FACADE_SLICE #(
+ parameter MODE = "LOGIC",
+ parameter GSR = "ENABLED",
+ parameter SRMODE = "LSR_OVER_CE",
+ parameter CEMUX = "1",
+ parameter CLKMUX = "0",
+ parameter LSRMUX = "LSR",
+ parameter LSRONMUX = "LSRMUX",
+ parameter LUT0_INITVAL = 16'hFFFF,
+ parameter LUT1_INITVAL = 16'hFFFF,
+ parameter REGMODE = "FF",
+ parameter REG0_SD = "1",
+ parameter REG1_SD = "1",
+ parameter REG0_REGSET = "SET",
+ parameter REG1_REGSET = "SET",
+ parameter CCU2_INJECT1_0 = "YES",
+ parameter CCU2_INJECT1_1 = "YES",
+ parameter WREMUX = "INV"
+) (
+ input A0, B0, C0, D0,
+ input A1, B1, C1, D1,
+ input M0, M1,
+ input FCI, FXA, FXB,
+
+ input CLK, LSR, CE,
+ input DI0, DI1,
+
+ input WD0, WD1,
+ input WAD0, WAD1, WAD2, WAD3,
+ input WRE, WCK,
+
+ output F0, Q0,
+ output F1, Q1,
+ output FCO, OFX0, OFX1,
+
+ output WDO0, WDO1, WDO2, WDO3,
+ output WADO0, WADO1, WADO2, WADO3
+);
+
+ generate
+ if (MODE == "LOGIC") begin
+ L6MUX21 FXMUX (.D0(FXA), .D1(FXB), .SD(M1), .Z(OFX1));
+
+ wire k0;
+ wire k1;
+ PFUMX K0K1MUX (.ALUT(k1), .BLUT(k0), .C0(M0), .Z(OFX0));
+
+ LUT4 #(.INIT(LUT0_INITVAL)) LUT_0 (.A(A0), .B(B0), .C(C0), .D(D0), .Z(k0));
+ LUT4 #(.INIT(LUT1_INITVAL)) LUT_1 (.A(A0), .B(B0), .C(C0), .D(D0), .Z(k1));
+
+ assign F0 = k0;
+ assign F1 = k1;
+ end else if (MODE == "CCU2") begin
+ ERROR_UNSUPPORTED_SLICE_MODE error();
+ end else if (MODE == "DPRAM") begin
+ ERROR_UNSUPPORTED_SLICE_MODE error();
+ end else begin
+ ERROR_UNKNOWN_SLICE_MODE error();
+ end
+ endgenerate
+
+ /* Reg can be fed either by M, or DI inputs; DI inputs muxes OFX and F
+ outputs (in other words, feeds back into FACADE_SLICE). */
+ wire di0 = (REG0_SD == "1") ? DI0 : M0;
+ wire di1 = (REG1_SD == "1") ? DI1 : M1;
+
+ FACADE_FF#(.GSR(GSR), .CEMUX(CEMUX), .CLKMUX(CLKMUX), .LSRMUX(LSRMUX),
+ .LSRONMUX(LSRONMUX), .SRMODE(SRMODE), .REGSET(REG0_REGSET),
+ .REGMODE(REGMODE)) REG_0 (.CLK(CLK), .DI(di0), .LSR(LSR), .CE(CE), .Q(Q0));
+ FACADE_FF#(.GSR(GSR), .CEMUX(CEMUX), .CLKMUX(CLKMUX), .LSRMUX(LSRMUX),
+ .LSRONMUX(LSRONMUX), .SRMODE(SRMODE), .REGSET(REG1_REGSET),
+ .REGMODE(REGMODE)) REG_1 (.CLK(CLK), .DI(di1), .LSR(LSR), .CE(CE), .Q(Q1));
+endmodule
+
+module FACADE_IO #(
+ parameter DIR = "INPUT"
+) (
+ inout PAD,
+ input I, T,
+ output O
+);
+ generate
+ if (DIR == "INPUT") begin
+ assign O = PAD;
+ end else if (DIR == "OUTPUT") begin
+ assign PAD = T ? 1'bz : I;
+ end else if (DIR == "BIDIR") begin
+ assign PAD = T ? 1'bz : I;
+ assign O = PAD;
+ end else begin
+ ERROR_UNKNOWN_IO_MODE error();
+ end
+ endgenerate
+endmodule
+
+(* blackbox *)
+module OSCH #(
+ parameter NOM_FREQ = "2.08"
+) (
+ input STDBY,
+ output OSC,
+ output SEDSTDBY
+);
+endmodule
+
+(* blackbox *)
+module DCCA (
+ input CLKI,
+ input CE,
+ output CLKO
+);
+endmodule
+
+(* blackbox *)
+module DCMA (
+ input CLK0,
+ input CLK1,
+ input SEL,
+ output DCMOUT
+);
+endmodule
+
+// IO- "$__" cells for the iopadmap pass. These are temporary cells not meant
+// to be instantiated by the end user. They are required in this file for
+// attrmvcp to work.
+(* blackbox *)
+module \$__FACADE_OUTPAD (input I, output O); endmodule
+(* blackbox *)
+module \$__FACADE_INPAD (input I, output O); endmodule
+(* blackbox *)
+module \$__FACADE_TOUTPAD (input I, T, output O); endmodule
+(* blackbox *)
+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
new file mode 100644
index 000000000..e86ec5aaf
--- /dev/null
+++ b/techlibs/machxo2/synth_machxo2.cc
@@ -0,0 +1,249 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2020 William D. Jones <wjones@wdj-consulting.com>
+ *
+ * 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 SynthMachXO2Pass : public ScriptPass
+{
+ SynthMachXO2Pass() : ScriptPass("synth_machxo2", "synthesis for MachXO2 FPGAs. This work is experimental.") { }
+
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" synth_machxo2 [options]\n");
+ log("\n");
+ log("This command runs synthesis for MachXO2 FPGAs.\n");
+ log("\n");
+ log(" -top <module>\n");
+ log(" use the specified module as top module\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(" -edif <file>\n");
+ log(" write the design to the specified EDIF file. writing of an output file\n");
+ log(" 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(" -noiopad\n");
+ log(" do not insert IO buffers\n");
+ log("\n");
+ log(" -vpr\n");
+ log(" generate an output netlist (and BLIF file) suitable for VPR\n");
+ log(" (this feature is experimental and incomplete)\n");
+ log("\n");
+ log("\n");
+ log("The following commands are executed by this synthesis command:\n");
+ help_script();
+ log("\n");
+ }
+
+ string top_opt, blif_file, edif_file, json_file;
+ bool flatten, vpr, noiopad;
+
+ void clear_flags() override
+ {
+ top_opt = "-auto-top";
+ blif_file = "";
+ edif_file = "";
+ json_file = "";
+ flatten = true;
+ vpr = false;
+ noiopad = 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] == "-blif" && argidx+1 < args.size()) {
+ blif_file = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-edif" && argidx+1 < args.size()) {
+ edif_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] == "-flatten") {
+ flatten = true;
+ continue;
+ }
+ if (args[argidx] == "-noflatten") {
+ flatten = false;
+ continue;
+ }
+ if (args[argidx] == "-noiopad") {
+ noiopad = true;
+ continue;
+ }
+ if (args[argidx] == "-vpr") {
+ vpr = 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_MACHXO2 pass.\n");
+ log_push();
+
+ run_script(design, run_from, run_to);
+
+ log_pop();
+ }
+
+ void script() override
+ {
+ if (check_label("begin"))
+ {
+ run("read_verilog -lib -icells +/machxo2/cells_sim.v");
+ run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
+ }
+
+ if (check_label("flatten", "(unless -noflatten)"))
+ {
+ if (flatten || help_mode) {
+ run("proc");
+ run("flatten");
+ run("tribuf -logic");
+ run("deminout");
+ }
+ }
+
+ if (check_label("coarse"))
+ {
+ run("synth -run coarse");
+ }
+
+ if (check_label("fine"))
+ {
+ run("memory_map");
+ run("opt -full");
+ run("techmap -map +/techmap.v");
+ run("opt -fast");
+ }
+
+ if (check_label("map_ios", "(unless -noiopad)"))
+ {
+ if (!noiopad || help_mode)
+ {
+ 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]");
+ }
+ }
+
+ if (check_label("map_ffs"))
+ {
+ run("dfflegalize -cell $_DFF_P_ 0");
+ }
+
+ if (check_label("map_luts"))
+ {
+ run("abc -lut 4 -dress");
+ run("clean");
+ }
+
+ if (check_label("map_cells"))
+ {
+ run("techmap -map +/machxo2/cells_map.v");
+ run("clean");
+ }
+
+ if (check_label("check"))
+ {
+ run("hierarchy -check");
+ run("stat");
+ run("blackbox =A:whitebox");
+ }
+
+ if (check_label("blif"))
+ {
+ if (!blif_file.empty() || help_mode) {
+ if (vpr || help_mode) {
+ run(stringf("opt_clean -purge"),
+ " (vpr mode)");
+ run(stringf("write_blif -attr -cname -conn -param %s",
+ help_mode ? "<file-name>" : blif_file.c_str()),
+ " (vpr mode)");
+ }
+ if (!vpr)
+ run(stringf("write_blif -gates -attr -param %s",
+ help_mode ? "<file-name>" : blif_file.c_str()),
+ " (non-vpr mode)");
+ }
+ }
+
+ if (check_label("edif"))
+ {
+ if (!edif_file.empty() || help_mode)
+ run(stringf("write_edif %s", help_mode ? "<file-name>" : edif_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()));
+ }
+ }
+} SynthMachXO2Pass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/nexus/Makefile.inc b/techlibs/nexus/Makefile.inc
new file mode 100644
index 000000000..9828d32c1
--- /dev/null
+++ b/techlibs/nexus/Makefile.inc
@@ -0,0 +1,18 @@
+OBJS += techlibs/nexus/synth_nexus.o
+
+$(eval $(call add_share_file,share/nexus,techlibs/nexus/cells_map.v))
+$(eval $(call add_share_file,share/nexus,techlibs/nexus/cells_sim.v))
+$(eval $(call add_share_file,share/nexus,techlibs/nexus/parse_init.vh))
+$(eval $(call add_share_file,share/nexus,techlibs/nexus/cells_xtra.v))
+$(eval $(call add_share_file,share/nexus,techlibs/nexus/lutrams_map.v))
+$(eval $(call add_share_file,share/nexus,techlibs/nexus/lutrams.txt))
+$(eval $(call add_share_file,share/nexus,techlibs/nexus/brams_init.vh))
+$(eval $(call add_share_file,share/nexus,techlibs/nexus/brams_map.v))
+$(eval $(call add_share_file,share/nexus,techlibs/nexus/brams.txt))
+$(eval $(call add_share_file,share/nexus,techlibs/nexus/lrams_init.vh))
+$(eval $(call add_share_file,share/nexus,techlibs/nexus/lrams_map.v))
+$(eval $(call add_share_file,share/nexus,techlibs/nexus/lrams.txt))
+$(eval $(call add_share_file,share/nexus,techlibs/nexus/arith_map.v))
+$(eval $(call add_share_file,share/nexus,techlibs/nexus/latches_map.v))
+$(eval $(call add_share_file,share/nexus,techlibs/nexus/dsp_map.v))
+
diff --git a/techlibs/nexus/arith_map.v b/techlibs/nexus/arith_map.v
new file mode 100644
index 000000000..81ab7ba54
--- /dev/null
+++ b/techlibs/nexus/arith_map.v
@@ -0,0 +1,99 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * 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
+ * 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_nexus_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 <= 4;
+
+ (* 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));
+
+ function integer round_up2;
+ input integer N;
+ begin
+ round_up2 = ((N + 1) / 2) * 2;
+ end
+ endfunction
+
+ localparam Y_WIDTH2 = round_up2(Y_WIDTH);
+
+ (* force_downto *)
+ wire [Y_WIDTH2-1:0] AA = A_buf;
+ (* force_downto *)
+ wire [Y_WIDTH2-1:0] BB = BI ? ~B_buf : B_buf;
+ (* force_downto *)
+ wire [Y_WIDTH2-1:0] BX = B_buf;
+ (* force_downto *)
+ wire [Y_WIDTH2+1:0] FCO, Y1;
+
+ genvar i;
+
+ // Carry feed-in
+ CCU2 #(
+ .INIT0("0xFFFF"),
+ .INIT1("0x00AA"),
+ .INJECT("NO")
+ ) ccu2c_i (
+ .A0(1'b1), .B0(1'b1), .C0(1'b1), .D0(1'b1),
+ .A1(CI), .B1(1'b1), .C1(1'b1), .D1(1'b1),
+ .COUT(FCO[0])
+ );
+
+ generate for (i = 0; i < Y_WIDTH2; i = i + 2) begin:slice
+ CCU2 #(
+ .INIT0("0x96AA"),
+ .INIT1("0x96AA"),
+ .INJECT("NO")
+ ) ccu2c_i (
+ .CIN(FCO[i]),
+ .A0(AA[i]), .B0(BX[i]), .C0(BI), .D0(1'b1),
+ .A1(AA[i+1]), .B1(BX[i+1]), .C1(BI), .D1(1'b1),
+ .S0(Y[i]), .S1(Y1[i]),
+ .COUT(FCO[i+2])
+ );
+
+ 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 + 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
+
+ assign X = AA ^ BB;
+endmodule
diff --git a/techlibs/nexus/brams.txt b/techlibs/nexus/brams.txt
new file mode 100644
index 000000000..086afe8bf
--- /dev/null
+++ b/techlibs/nexus/brams.txt
@@ -0,0 +1,63 @@
+bram $__NX_PDP16K
+ init 1
+
+ abits 9 @a9d36
+ dbits 36 @a9d36
+ abits 10 @a10d18
+ dbits 18 @a10d18
+ abits 11 @a11d9
+ dbits 9 @a11d9
+ abits 12 @a12d4
+ dbits 4 @a12d4
+ abits 13 @a13d2
+ dbits 2 @a13d2
+ abits 14 @a14d1
+ dbits 1 @a14d1
+
+ groups 2
+ ports 1 1
+ wrmode 1 0
+ enable 4 1 @a9d36
+ enable 2 1 @a10d18
+ enable 1 1 @a11d9 @a12d4 @a13d2 @a14d1
+ transp 0 0
+ clocks 2 3
+ clkpol 2 3
+endbram
+
+match $__NX_PDP16K
+ # 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 2048
+ min efficiency 5
+ shuffle_enable A
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__NX_PDP16K
+ # 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 $__NX_PDP16K
+ # explicitly requested ROM
+ attribute syn_romstyle=ebr rom_block
+ attribute !syn_ramstyle
+ attribute !ram_block
+ attribute !logic_block
+ max wports 0
+ make_transp
+ shuffle_enable A
+endmatch
diff --git a/techlibs/nexus/brams_init.vh b/techlibs/nexus/brams_init.vh
new file mode 100644
index 000000000..5b1d0188a
--- /dev/null
+++ b/techlibs/nexus/brams_init.vh
@@ -0,0 +1,64 @@
+.INITVAL_00($sformatf("0x%080x", permute_init(INIT[0 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_01($sformatf("0x%080x", permute_init(INIT[1 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_02($sformatf("0x%080x", permute_init(INIT[2 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_03($sformatf("0x%080x", permute_init(INIT[3 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_04($sformatf("0x%080x", permute_init(INIT[4 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_05($sformatf("0x%080x", permute_init(INIT[5 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_06($sformatf("0x%080x", permute_init(INIT[6 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_07($sformatf("0x%080x", permute_init(INIT[7 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_08($sformatf("0x%080x", permute_init(INIT[8 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_09($sformatf("0x%080x", permute_init(INIT[9 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_0A($sformatf("0x%080x", permute_init(INIT[10 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_0B($sformatf("0x%080x", permute_init(INIT[11 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_0C($sformatf("0x%080x", permute_init(INIT[12 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_0D($sformatf("0x%080x", permute_init(INIT[13 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_0E($sformatf("0x%080x", permute_init(INIT[14 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_0F($sformatf("0x%080x", permute_init(INIT[15 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_10($sformatf("0x%080x", permute_init(INIT[16 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_11($sformatf("0x%080x", permute_init(INIT[17 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_12($sformatf("0x%080x", permute_init(INIT[18 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_13($sformatf("0x%080x", permute_init(INIT[19 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_14($sformatf("0x%080x", permute_init(INIT[20 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_15($sformatf("0x%080x", permute_init(INIT[21 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_16($sformatf("0x%080x", permute_init(INIT[22 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_17($sformatf("0x%080x", permute_init(INIT[23 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_18($sformatf("0x%080x", permute_init(INIT[24 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_19($sformatf("0x%080x", permute_init(INIT[25 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_1A($sformatf("0x%080x", permute_init(INIT[26 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_1B($sformatf("0x%080x", permute_init(INIT[27 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_1C($sformatf("0x%080x", permute_init(INIT[28 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_1D($sformatf("0x%080x", permute_init(INIT[29 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_1E($sformatf("0x%080x", permute_init(INIT[30 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_1F($sformatf("0x%080x", permute_init(INIT[31 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_20($sformatf("0x%080x", permute_init(INIT[32 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_21($sformatf("0x%080x", permute_init(INIT[33 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_22($sformatf("0x%080x", permute_init(INIT[34 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_23($sformatf("0x%080x", permute_init(INIT[35 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_24($sformatf("0x%080x", permute_init(INIT[36 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_25($sformatf("0x%080x", permute_init(INIT[37 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_26($sformatf("0x%080x", permute_init(INIT[38 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_27($sformatf("0x%080x", permute_init(INIT[39 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_28($sformatf("0x%080x", permute_init(INIT[40 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_29($sformatf("0x%080x", permute_init(INIT[41 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_2A($sformatf("0x%080x", permute_init(INIT[42 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_2B($sformatf("0x%080x", permute_init(INIT[43 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_2C($sformatf("0x%080x", permute_init(INIT[44 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_2D($sformatf("0x%080x", permute_init(INIT[45 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_2E($sformatf("0x%080x", permute_init(INIT[46 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_2F($sformatf("0x%080x", permute_init(INIT[47 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_30($sformatf("0x%080x", permute_init(INIT[48 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_31($sformatf("0x%080x", permute_init(INIT[49 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_32($sformatf("0x%080x", permute_init(INIT[50 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_33($sformatf("0x%080x", permute_init(INIT[51 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_34($sformatf("0x%080x", permute_init(INIT[52 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_35($sformatf("0x%080x", permute_init(INIT[53 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_36($sformatf("0x%080x", permute_init(INIT[54 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_37($sformatf("0x%080x", permute_init(INIT[55 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_38($sformatf("0x%080x", permute_init(INIT[56 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_39($sformatf("0x%080x", permute_init(INIT[57 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_3A($sformatf("0x%080x", permute_init(INIT[58 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_3B($sformatf("0x%080x", permute_init(INIT[59 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_3C($sformatf("0x%080x", permute_init(INIT[60 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_3D($sformatf("0x%080x", permute_init(INIT[61 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_3E($sformatf("0x%080x", permute_init(INIT[62 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_3F($sformatf("0x%080x", permute_init(INIT[63 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])))
diff --git a/techlibs/nexus/brams_map.v b/techlibs/nexus/brams_map.v
new file mode 100644
index 000000000..214da4326
--- /dev/null
+++ b/techlibs/nexus/brams_map.v
@@ -0,0 +1,115 @@
+module \$__NX_PDP16K (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+ parameter CFG_ABITS = 9;
+ parameter CFG_DBITS = 36;
+ parameter CFG_ENABLE_A = 4;
+
+ parameter CLKPOL2 = 1;
+ parameter CLKPOL3 = 1;
+ parameter [18431:0] INIT = 18432'b0;
+
+ parameter _TECHMAP_BITS_CONNMAP_ = 8;
+ parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_CLK2_ = 0;
+ parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_CLK3_ = 0;
+
+ input CLK2;
+ input CLK3;
+
+ input [CFG_ABITS-1:0] A1ADDR;
+ input [CFG_DBITS-1:0] A1DATA;
+ input [CFG_ENABLE_A-1:0] A1EN;
+
+ input [CFG_ABITS-1:0] B1ADDR;
+ output [CFG_DBITS-1:0] B1DATA;
+ input B1EN;
+
+ // Address is left justified, in x18 and above lower bits are byte enables
+ localparam A_SHIFT =
+ (CFG_DBITS == 36) ? 5 :
+ (CFG_DBITS == 18) ? 4 :
+ (CFG_DBITS == 9) ? 3 :
+ (CFG_DBITS == 4) ? 2 :
+ (CFG_DBITS == 2) ? 1 :
+ 0;
+
+ // Different primitives needed for single vs dual clock case
+ localparam SINGLE_CLOCK = (_TECHMAP_CONNMAP_CLK2_ == _TECHMAP_CONNMAP_CLK3_);
+
+ localparam WIDTH = $sformatf("X%d", CFG_DBITS);
+
+ wire [13:0] ra, wa;
+ wire [35:0] rd, wd;
+
+ assign ra = {B1ADDR, {A_SHIFT{1'b1}}};
+
+ generate
+ if (CFG_ENABLE_A > 1)
+ assign wa = {A1ADDR, {(A_SHIFT-CFG_ENABLE_A){1'b1}}, A1EN};
+ else
+ assign wa = {A1ADDR, {A_SHIFT{1'b1}}};
+ endgenerate
+
+ assign wd = A1DATA;
+ assign B1DATA = rd[CFG_DBITS-1:0];
+
+ wire wck, rck;
+
+ generate
+ if (CLKPOL2)
+ assign wck = CLK2;
+ else
+ INV wck_inv_i (.A(CLK2), .Z(wck));
+ if (CLKPOL3)
+ assign rck = CLK3;
+ else
+ INV wck_inv_i (.A(CLK3), .Z(rck));
+ endgenerate
+
+ wire we = |A1EN;
+
+ localparam INIT_CHUNK_SIZE = (CFG_DBITS <= 4) ? 256 : 288;
+
+ function [319:0] permute_init;
+ input [INIT_CHUNK_SIZE-1:0] chunk;
+ integer i;
+ begin
+ if (CFG_DBITS <= 4) begin
+ for (i = 0; i < 32; i = i + 1'b1)
+ permute_init[i * 10 +: 10] = {2'b00, chunk[i * 8 +: 8]};
+ end else begin
+ for (i = 0; i < 32; i = i + 1'b1)
+ permute_init[i * 10 +: 10] = {1'b0, chunk[i * 9 +: 9]};
+ end
+ end
+ endfunction
+
+ generate
+ if (SINGLE_CLOCK) begin
+ PDPSC16K #(
+ .DATA_WIDTH_W(WIDTH),
+ .DATA_WIDTH_R(WIDTH),
+ .OUTREG("BYPASSED"),
+ .ECC("DISABLED"),
+ .GSR("DISABLED"),
+`include "brams_init.vh"
+ ) _TECHMAP_REPLACE_ (
+ .CLK(wck), .RST(1'b0),
+ .DI(wd), .ADW(wa), .CEW(we), .CSW(3'b111),
+ .ADR(ra), .DO(rd), .CER(B1EN), .CSR(3'b111)
+ );
+ end else begin
+ PDP16K #(
+ .DATA_WIDTH_W(WIDTH),
+ .DATA_WIDTH_R(WIDTH),
+ .OUTREG("BYPASSED"),
+ .ECC("DISABLED"),
+ .GSR("DISABLED"),
+`include "brams_init.vh"
+ ) _TECHMAP_REPLACE_ (
+ .CLKW(wck), .CLKR(rck), .RST(1'b0),
+ .DI(wd), .ADW(wa), .CEW(we), .CSW(3'b111),
+ .ADR(ra), .DO(rd), .CER(B1EN), .CSR(3'b111)
+ );
+ end
+ endgenerate
+
+endmodule
diff --git a/techlibs/nexus/cells_map.v b/techlibs/nexus/cells_map.v
new file mode 100644
index 000000000..b70edbcf4
--- /dev/null
+++ b/techlibs/nexus/cells_map.v
@@ -0,0 +1,98 @@
+// Flipflop intermediate map level
+module \$__FF_NOLSR (input D, C, E, output Q);
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
+ generate
+ if (_TECHMAP_WIREINIT_Q_ === 1'b1)
+ FD1P3JX #(.GSR("DISABLED")) _TECHMAP_REPLACE_ (.D(D), .CK(C), .SP(E), .PD(1'b0), .Q(Q));
+ else
+ FD1P3IX #(.GSR("DISABLED")) _TECHMAP_REPLACE_ (.D(D), .CK(C), .SP(E), .CD(1'b0), .Q(Q));
+ endgenerate
+endmodule
+
+module \$__FF_SYNCLSR (input D, C, E, R, output Q);
+ parameter SR_VAL = 1'b0;
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
+ wire Ci, Ei, Ri, Rg, Dd;
+ generate
+ if (SR_VAL)
+ FD1P3JX #(.GSR("DISABLED")) _TECHMAP_REPLACE_ (.D(D), .CK(C), .SP(E), .PD(R), .Q(Q));
+ else
+ FD1P3IX #(.GSR("DISABLED")) _TECHMAP_REPLACE_ (.D(D), .CK(C), .SP(E), .CD(R), .Q(Q));
+ endgenerate
+endmodule
+
+module \$__FF_ASYNCLSR (input D, C, E, R, output Q);
+ parameter SR_VAL = 1'b0;
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ wire _TECHMAP_REMOVEINIT_Q_ = (_TECHMAP_WIREINIT_Q_ === 1'bx || _TECHMAP_WIREINIT_Q_ === SR_VAL);
+ wire Ci, Ei, Ri, Rg, Dd;
+ generate
+ if (SR_VAL)
+ FD1P3BX #(.GSR("DISABLED")) _TECHMAP_REPLACE_ (.D(D), .CK(C), .SP(E), .PD(R), .Q(Q));
+ else
+ FD1P3DX #(.GSR("DISABLED")) _TECHMAP_REPLACE_ (.D(D), .CK(C), .SP(E), .CD(R), .Q(Q));
+ endgenerate
+endmodule
+
+
+module \$_DFF_P_ (input D, C, output Q); \$__FF_NOLSR _TECHMAP_REPLACE_ (.D(D), .C(C), .E(1'b1), .Q(Q)); endmodule
+
+module \$_DFFE_PP_ (input D, C, E, output Q); \$__FF_NOLSR _TECHMAP_REPLACE_ (.D(D), .C(C), .E(E), .Q(Q)); endmodule
+
+module \$_DFF_PP0_ (input D, C, R, output Q); \$__FF_ASYNCLSR #(0) _TECHMAP_REPLACE_ (.D(D), .C(C), .R(R), .E(1'b1), .Q(Q)); endmodule
+module \$_DFF_PP1_ (input D, C, R, output Q); \$__FF_ASYNCLSR #(1) _TECHMAP_REPLACE_ (.D(D), .C(C), .R(R), .E(1'b1), .Q(Q)); endmodule
+
+module \$_SDFF_PP0_ (input D, C, R, output Q); \$__FF_SYNCLSR #(0) _TECHMAP_REPLACE_ (.D(D), .C(C), .R(R), .E(1'b1), .Q(Q)); endmodule
+module \$_SDFF_PP1_ (input D, C, R, output Q); \$__FF_SYNCLSR #(1) _TECHMAP_REPLACE_ (.D(D), .C(C), .R(R), .E(1'b1), .Q(Q)); endmodule
+
+module \$_DFFE_PP0P_ (input D, C, E, R, output Q); \$__FF_ASYNCLSR #(0) _TECHMAP_REPLACE_ (.D(D), .C(C), .R(R), .E(E), .Q(Q)); endmodule
+module \$_DFFE_PP1P_ (input D, C, E, R, output Q); \$__FF_ASYNCLSR #(1) _TECHMAP_REPLACE_ (.D(D), .C(C), .R(R), .E(E), .Q(Q)); endmodule
+
+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
+
+`ifndef NO_LUT
+module \$lut (A, Y);
+ parameter WIDTH = 0;
+ parameter LUT = 0;
+
+ input [WIDTH-1:0] A;
+ output Y;
+
+ generate
+ if (WIDTH == 1) begin
+ if (LUT == 2'b01)
+ INV _TECHMAP_REPLACE_ (.A(A[0]), .Z(Y));
+ else
+ LUT4 #(.INIT($sformatf("0x%04x", {{8{LUT[1]}}, {8{LUT[0]}}}))) _TECHMAP_REPLACE_ (.Z(Y),
+ .D(A[0]));
+ end else
+ if (WIDTH == 2) begin
+ localparam [15:0] INIT = {{4{LUT[3]}}, {4{LUT[2]}}, {4{LUT[1]}}, {4{LUT[0]}}};
+ LUT4 #(.INIT($sformatf("0x%04x", INIT))) _TECHMAP_REPLACE_ (.Z(Y),
+ .C(A[0]), .D(A[1]));
+ end else
+ if (WIDTH == 3) begin
+ localparam [15:0] INIT = {{2{LUT[7]}}, {2{LUT[6]}}, {2{LUT[5]}}, {2{LUT[4]}}, {2{LUT[3]}}, {2{LUT[2]}}, {2{LUT[1]}}, {2{LUT[0]}}};
+ LUT4 #(.INIT($sformatf("0x%04x", INIT))) _TECHMAP_REPLACE_ (.Z(Y),
+ .B(A[0]), .C(A[1]), .D(A[2]));
+ end else
+ if (WIDTH == 4) begin
+ LUT4 #(.INIT($sformatf("0x%04x", LUT))) _TECHMAP_REPLACE_ (.Z(Y),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+ end else
+ if (WIDTH == 5) begin
+ WIDEFN9 #(
+ .INIT0($sformatf("0x%04x", LUT[15:0 ])),
+ .INIT1($sformatf("0x%04x", LUT[31:16])),
+ ) _TECHMAP_REPLACE_ (
+ .A0(A[0]), .B0(A[1]), .C0(A[2]), .D0(A[3]),
+ .A1(A[0]), .B1(A[1]), .C1(A[2]), .D1(A[3]),
+ .SEL(A[4]), .Z(Y)
+ );
+ end
+ endgenerate
+endmodule
+`endif
diff --git a/techlibs/nexus/cells_sim.v b/techlibs/nexus/cells_sim.v
new file mode 100644
index 000000000..d1c8bf0d7
--- /dev/null
+++ b/techlibs/nexus/cells_sim.v
@@ -0,0 +1,1058 @@
+(* abc9_lut=1, lib_whitebox *)
+module LUT4(input A, B, C, D, output Z);
+ parameter INIT = "0x0000";
+`include "parse_init.vh"
+ localparam initp = parse_init(INIT);
+ wire [7:0] s3 = D ? initp[15:8] : initp[7:0];
+ wire [3:0] s2 = C ? s3[ 7:4] : s3[3:0];
+ wire [1:0] s1 = B ? s2[ 3:2] : s2[1:0];
+ assign Z = A ? s1[1] : s1[0];
+
+ // Per-input delay differences are considered 'interconnect'
+ // so not known yet
+ specify
+ (A => Z) = 233;
+ (B => Z) = 233;
+ (C => Z) = 233;
+ (D => Z) = 233;
+ endspecify
+
+endmodule
+
+// This is a placeholder for ABC9 to extract the area/delay
+// cost of 5-input LUTs and is not intended to be instantiated
+(* abc9_lut=2 *)
+module \$__ABC9_LUT5 (input SEL, D, C, B, A, output Z);
+ specify
+ (SEL => Z) = 171;
+ (D => Z) = 303;
+ (C => Z) = 311;
+ (B => Z) = 309;
+ (A => Z) = 306;
+ endspecify
+endmodule
+
+// Two LUT4s and MUX2
+module WIDEFN9(input A0, B0, C0, D0, A1, B1, C1, D1, SEL, output Z);
+ parameter INIT0 = "0x0000";
+ parameter INIT1 = "0x0000";
+ wire z0, z1;
+ LUT4 #(.INIT(INIT0)) lut4_0 (.A(A0), .B(B0), .C(C0), .D(D0), .Z(z0));
+ LUT4 #(.INIT(INIT1)) lut4_1 (.A(A1), .B(B1), .C(C1), .D(D1), .Z(z1));
+ assign Z = SEL ? z1 : z0;
+endmodule
+
+(* abc9_box, lib_whitebox *)
+module INV(input A, output Z);
+ assign Z = !A;
+
+ specify
+ (A => Z) = 10;
+ endspecify
+endmodule
+
+// Bidirectional IO buffer
+module BB(input T, I, output O,
+ (* iopad_external_pin *) inout B);
+ assign B = T ? 1'bz : I;
+ assign O = B;
+endmodule
+
+// Input buffer
+module IB(
+ (* iopad_external_pin *) input I,
+ output O);
+ assign O = I;
+endmodule
+
+// Output buffer
+module OB(input I,
+ (* iopad_external_pin *) output O);
+ assign O = I;
+endmodule
+
+// Output buffer with tristate
+module OBZ(input I, T,
+ (* iopad_external_pin *) output O);
+ assign O = T ? 1'bz : I;
+endmodule
+
+// Constants
+module VLO(output Z);
+ assign Z = 1'b0;
+endmodule
+
+module VHI(output Z);
+ assign Z = 1'b1;
+endmodule
+
+// Vendor flipflops
+// (all have active high clock, enable and set/reset - use INV to invert)
+
+// Async preset
+(* abc9_box, lib_whitebox *)
+module FD1P3BX(input D, CK, SP, PD, output reg Q);
+ parameter GSR = "DISABLED";
+ initial Q = 1'b1;
+ always @(posedge CK or posedge PD)
+ if (PD)
+ Q <= 1'b1;
+ else if (SP)
+ Q <= D;
+ specify
+ $setup(D, posedge CK, 0);
+ $setup(SP, posedge CK, 212);
+ $setup(PD, posedge CK, 224);
+`ifndef YOSYS
+ if (PD) (posedge CLK => (Q : 1)) = 0;
+`else
+ if (PD) (PD => Q) = 0; // Technically, this should be an edge sensitive path
+ // but for facilitating a bypass box, let's pretend it's
+ // a simple path
+`endif
+ if (!PD && SP) (posedge CK => (Q : D)) = 336;
+ endspecify
+endmodule
+
+// Async clear
+(* abc9_box, lib_whitebox *)
+module FD1P3DX(input D, CK, SP, CD, output reg Q);
+ parameter GSR = "DISABLED";
+ initial Q = 1'b0;
+ always @(posedge CK or posedge CD)
+ if (CD)
+ Q <= 1'b0;
+ else if (SP)
+ Q <= D;
+ specify
+ $setup(D, posedge CK, 0);
+ $setup(SP, posedge CK, 212);
+ $setup(CD, posedge CK, 224);
+`ifndef YOSYS
+ if (CD) (posedge CLK => (Q : 0)) = 0;
+`else
+ if (CD) (CD => Q) = 0; // Technically, this should be an edge sensitive path
+ // but for facilitating a bypass box, let's pretend it's
+ // a simple path
+`endif
+ if (!CD && SP) (posedge CK => (Q : D)) = 336;
+ endspecify
+endmodule
+
+// Sync clear
+(* abc9_flop, lib_whitebox *)
+module FD1P3IX(input D, CK, SP, CD, output reg Q);
+ parameter GSR = "DISABLED";
+ initial Q = 1'b0;
+ always @(posedge CK)
+ if (CD)
+ Q <= 1'b0;
+ else if (SP)
+ Q <= D;
+ specify
+ $setup(D, posedge CK, 0);
+ $setup(SP, posedge CK, 212);
+ $setup(CD, posedge CK, 224);
+ if (!CD && SP) (posedge CK => (Q : D)) = 336;
+ endspecify
+endmodule
+
+// Sync preset
+(* abc9_flop, lib_whitebox *)
+module FD1P3JX(input D, CK, SP, PD, output reg Q);
+ parameter GSR = "DISABLED";
+ initial Q = 1'b1;
+ always @(posedge CK)
+ if (PD)
+ Q <= 1'b1;
+ else if (SP)
+ Q <= D;
+ specify
+ $setup(D, posedge CK, 0);
+ $setup(SP, posedge CK, 212);
+ $setup(PD, posedge CK, 224);
+ if (!PD && SP) (posedge CK => (Q : D)) = 336;
+ endspecify
+endmodule
+
+// LUT4 with LUT3 tap for CCU2 use only
+(* lib_whitebox *)
+module LUT4_3(input A, B, C, D, output Z, Z3);
+ parameter INIT = "0x0000";
+`include "parse_init.vh"
+ localparam initp = parse_init(INIT);
+ wire [7:0] s3 = D ? initp[15:8] : initp[7:0];
+ wire [3:0] s2 = C ? s3[ 7:4] : s3[3:0];
+ wire [1:0] s1 = B ? s2[ 3:2] : s2[1:0];
+ assign Z = A ? s1[1] : s1[0];
+
+ wire [3:0] s2_3 = C ? initp[ 7:4] : initp[3:0];
+ wire [1:0] s1_3 = B ? s2_3[ 3:2] : s2_3[1:0];
+ assign Z3 = A ? s1_3[1] : s1_3[0];
+
+endmodule
+
+// Carry primitive (incoporating two LUTs)
+(* abc9_box, lib_whitebox *)
+module CCU2(
+ (* abc9_carry *) input CIN,
+ input A1, B1, C1, D1, A0, B0, C0, D0,
+ output S1, S0,
+ (* abc9_carry *) output COUT);
+ parameter INJECT = "YES";
+ parameter INIT0 = "0x0000";
+ parameter INIT1 = "0x1111";
+
+ localparam inject_p = (INJECT == "YES") ? 1'b1 : 1'b0;
+
+ wire LUT3_0, LUT4_0, LUT3_1, LUT4_1, carry_0;
+ LUT4_3 #(.INIT(INIT0)) lut0 (.A(A0), .B(B0), .C(C0), .D(D0), .Z(LUT4_0), .Z3(LUT3_0));
+ LUT4_3 #(.INIT(INIT1)) lut1 (.A(A1), .B(B1), .C(C1), .D(D1), .Z(LUT4_1), .Z3(LUT3_1));
+
+ assign S0 = LUT4_0 ^ (CIN & ~inject_p);
+ assign carry_0 = LUT4_0 ? CIN : (LUT3_0 & ~inject_p);
+ assign S1 = LUT4_1 ^ (carry_0 & ~inject_p);
+ assign COUT = LUT4_1 ? carry_0 : (LUT3_1 & ~inject_p);
+
+ specify
+ (A0 => S0) = 233;
+ (B0 => S0) = 233;
+ (C0 => S0) = 233;
+ (D0 => S0) = 233;
+ (CIN => S0) = 228;
+ (A0 => S1) = 481;
+ (B0 => S1) = 481;
+ (C0 => S1) = 481;
+ (D0 => S1) = 481;
+ (A1 => S1) = 233;
+ (B1 => S1) = 233;
+ (C1 => S1) = 233;
+ (D1 => S1) = 233;
+ (CIN => S1) = 307;
+ (A0 => COUT) = 347;
+ (B0 => COUT) = 347;
+ (C0 => COUT) = 347;
+ (D0 => COUT) = 347;
+ (A1 => COUT) = 347;
+ (B1 => COUT) = 347;
+ (C1 => COUT) = 347;
+ (D1 => COUT) = 347;
+ (CIN => COUT) = 59;
+ endspecify
+
+endmodule
+
+// Packed flipflop
+module OXIDE_FF(input CLK, LSR, CE, DI, M, output reg Q);
+ parameter GSR = "ENABLED";
+ parameter [127:0] CEMUX = "1";
+ parameter CLKMUX = "CLK";
+ parameter LSRMUX = "LSR";
+ parameter REGDDR = "DISABLED";
+ parameter SRMODE = "LSR_OVER_CE";
+ parameter REGSET = "RESET";
+ parameter [127:0] LSRMODE = "LSR";
+
+ wire muxce;
+ generate
+ case (CEMUX)
+ "1": assign muxce = 1'b1;
+ "0": assign muxce = 1'b0;
+ "INV": assign muxce = ~CE;
+ default: assign muxce = CE;
+ endcase
+ endgenerate
+
+ wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR;
+ wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK;
+ wire srval;
+ generate
+ if (LSRMODE == "PRLD")
+ assign srval = M;
+ else
+ assign srval = (REGSET == "SET") ? 1'b1 : 1'b0;
+ endgenerate
+
+ initial Q = srval;
+
+ generate
+ if (REGDDR == "ENABLED") begin
+ if (SRMODE == "ASYNC") begin
+ always @(posedge muxclk, negedge muxclk, posedge muxlsr)
+ if (muxlsr)
+ Q <= srval;
+ else if (muxce)
+ Q <= DI;
+ end else begin
+ always @(posedge muxclk, negedge muxclk)
+ if (muxlsr)
+ Q <= srval;
+ else if (muxce)
+ Q <= DI;
+ end
+ end else begin
+ if (SRMODE == "ASYNC") begin
+ always @(posedge muxclk, posedge muxlsr)
+ if (muxlsr)
+ Q <= srval;
+ else if (muxce)
+ Q <= DI;
+ end else begin
+ always @(posedge muxclk)
+ if (muxlsr)
+ Q <= srval;
+ else if (muxce)
+ Q <= DI;
+ end
+ end
+ endgenerate
+endmodule
+
+// Packed combinational logic (for post-pnr sim)
+module OXIDE_COMB(
+ input A, B, C, D, // LUT inputs
+ input SEL, // mux select input
+ input F1, // output from LUT 1 for mux
+ input FCI, // carry input
+ input WAD0, WAD1, WAD2, WAD3, // LUTRAM write address inputs
+ input WD, // LUTRAM write data input
+ input WCK, WRE, // LUTRAM write clock and enable
+ output F, // LUT/carry output
+ output OFX // mux output
+);
+ parameter MODE = "LOGIC"; // LOGIC, CCU2, DPRAM
+ parameter [15:0] INIT = 16'h0000;
+ parameter INJECT = "YES";
+
+ localparam inject_p = (INJECT == "YES") ? 1'b1 : 1'b0;
+
+ reg [15:0] lut = INIT;
+
+ wire [7:0] s3 = D ? INIT[15:8] : INIT[7:0];
+ wire [3:0] s2 = C ? s3[ 7:4] : s3[3:0];
+ wire [1:0] s1 = B ? s2[ 3:2] : s2[1:0];
+ wire Z = A ? s1[1] : s1[0];
+
+ wire [3:0] s2_3 = C ? INIT[ 7:4] : INIT[3:0];
+ wire [1:0] s1_3 = B ? s2_3[ 3:2] : s2_3[1:0];
+ wire Z3 = A ? s1_3[1] : s1_3[0];
+
+ generate
+ if (MODE == "DPRAM") begin
+ always @(posedge WCK)
+ if (WRE)
+ lut[{WAD3, WAD2, WAD1, WAD0}] <= WD;
+ end
+ if (MODE == "CCU2") begin
+ assign F = Z ^ (FCI & ~inject_p);
+ assign FCO = Z ? FCI : (Z3 & ~inject_p);
+ end else begin
+ assign F = Z;
+ end
+ endgenerate
+
+ assign OFX = SEL ? F1 : F;
+
+endmodule
+
+// LUTRAM
+module DPR16X4(
+ input [3:0] RAD, DI, WAD,
+ input WRE, WCK,
+ output [3:0] DO
+);
+ parameter INITVAL = "0x0000000000000000";
+`include "parse_init.vh"
+ localparam [63:0] parsed_init = parse_init_64(INITVAL);
+
+ reg [3:0] mem[0:15];
+ integer i;
+ initial begin
+ for (i = 0; i < 15; i++)
+ mem[i] = parsed_init[i * 4 +: 4];
+ end
+
+ always @(posedge WCK)
+ if (WRE)
+ mem[WAD] <= DI;
+ assign DO = mem[RAD];
+endmodule
+
+// Used for all the DSP models to reduce duplication
+module OXIDE_DSP_REG #(
+ parameter W = 18,
+ parameter USED = "REGISTER",
+ parameter RESETMODE = "SYNC"
+) (
+ input CLK, CE, RST,
+ input [W-1:0] D,
+ output reg [W-1:0] Q
+);
+ generate
+ if (USED == "BYPASS")
+ always @* Q = D;
+ else if (USED == "REGISTER") begin
+ initial Q = 0;
+ if (RESETMODE == "ASYNC")
+ always @(posedge CLK, posedge RST) begin
+ if (RST)
+ Q <= 0;
+ else if (CE)
+ Q <= D;
+ end
+ else if (RESETMODE == "SYNC")
+ always @(posedge CLK) begin
+ if (RST)
+ Q <= 0;
+ else if (CE)
+ Q <= D;
+ end
+ end
+ endgenerate
+endmodule
+
+module OXIDE_DSP_SIM #(
+ // User facing parameters
+ parameter REGINPUTA = "BYPASS",
+ parameter REGINPUTB = "BYPASS",
+ parameter REGINPUTC = "BYPASS",
+ parameter REGADDSUB = "BYPASS",
+ parameter REGLOADC = "BYPASS",
+ parameter REGLOADC2 = "BYPASS",
+ parameter REGCIN = "BYPASS",
+ parameter REGPIPELINE = "BYPASS",
+ parameter REGOUTPUT = "BYPASS",
+ parameter GSR = "ENABLED",
+ parameter RESETMODE = "SYNC",
+ // Internally used parameters
+ parameter A_WIDTH = 36,
+ parameter B_WIDTH = 36,
+ parameter C_WIDTH = 36,
+ parameter Z_WIDTH = 72,
+ parameter PREADD_USED = 0,
+ parameter ADDSUB_USED = 0
+) (
+ input [A_WIDTH-1:0] A,
+ input [B_WIDTH-1:0] B,
+ input [C_WIDTH-1:0] C,
+ input SIGNEDA,
+ input SIGNEDB,
+ input SIGNEDC,
+ input CIN,
+ input LOADC,
+ input ADDSUB,
+ input CLK,
+ input CEA, CEB, CEC, CEPIPE, CECTRL, CECIN, CEOUT,
+ input RSTA, RSTB, RSTC, RSTPIPE, RSTCTRL, RSTCIN, RSTOUT,
+ output wire [Z_WIDTH-1:0] Z
+);
+
+ localparam M_WIDTH = (A_WIDTH+B_WIDTH);
+
+ /******** REGISTERS ********/
+
+ wire [M_WIDTH-1:0] pipe_d, pipe_q;
+ wire [Z_WIDTH-1:0] z_d;
+
+ wire [A_WIDTH-1:0] a_r;
+ wire [B_WIDTH-1:0] b_r;
+ wire [C_WIDTH-1:0] c_r, c_r2;
+ wire asgd_r, bsgd_r, csgd_r, csgd_r2;
+
+ wire addsub_r, addsub_r2, cin_r, cin_r2, sgd_r, sgd_r2;
+ wire loadc_r, loadc_r2;
+
+ OXIDE_DSP_REG #(A_WIDTH+1, REGINPUTA, RESETMODE) a_reg(CLK, CEA, RSTA, {SIGNEDA, A}, {asgd_r, a_r});
+ OXIDE_DSP_REG #(B_WIDTH+1, REGINPUTB, RESETMODE) b_reg(CLK, CEB, RSTB, {SIGNEDB, B}, {bsgd_r, b_r});
+ OXIDE_DSP_REG #(C_WIDTH+1, REGINPUTC, RESETMODE) c_reg(CLK, CEC, RSTC, {SIGNEDC, C}, {csgd_r, c_r});
+
+ OXIDE_DSP_REG #(M_WIDTH, REGPIPELINE, RESETMODE) pipe_reg(CLK, CEPIPE, RSTPIPE, pipe_d, pipe_q);
+
+ OXIDE_DSP_REG #(2, REGADDSUB, RESETMODE) addsub_reg(CLK, CECTRL, RSTCTRL, {SIGNEDA, ADDSUB}, {sgd_r, addsub_r});
+ OXIDE_DSP_REG #(1, REGLOADC, RESETMODE) loadc_reg(CLK, CECTRL, RSTCTRL, LOADC, loadc_r);
+ OXIDE_DSP_REG #(2, REGPIPELINE, RESETMODE) addsub2_reg(CLK, CECTRL, RSTCTRL, {sgd_r, addsub_r}, {sgd_r2, addsub_r2});
+ OXIDE_DSP_REG #(1, REGLOADC2, RESETMODE) loadc2_reg(CLK, CECTRL, RSTCTRL, loadc_r, loadc_r2);
+
+ OXIDE_DSP_REG #(1, REGCIN, RESETMODE) cin_reg(CLK, CECIN, RSTCIN, CIN, cin_r);
+ OXIDE_DSP_REG #(1, REGPIPELINE, RESETMODE) cin2_reg(CLK, CECIN, RSTCIN, cin_r, cin_r2);
+
+ OXIDE_DSP_REG #(C_WIDTH+1, REGPIPELINE, RESETMODE) c2_reg(CLK, CEC, RSTC, {csgd_r, c_r}, {csgd_r2, c_r2});
+
+ OXIDE_DSP_REG #(Z_WIDTH, REGOUTPUT, RESETMODE) z_reg(CLK, CEOUT, RSTOUT, z_d, Z);
+
+ /******** PREADDER ********/
+
+ wire [B_WIDTH-1:0] mult_b;
+ wire mult_b_sgd;
+
+ generate
+ if (PREADD_USED) begin
+ assign mult_b = (b_r + c_r);
+ assign mult_b_sgd = (bsgd_r | csgd_r);
+ end else begin
+ assign mult_b = b_r;
+ assign mult_b_sgd = bsgd_r;
+ end
+ endgenerate
+
+ /******** MULTIPLIER ********/
+
+ // sign extend operands if needed
+ wire [M_WIDTH-1:0] mult_a_ext = {{(M_WIDTH-A_WIDTH){asgd_r ? a_r[A_WIDTH-1] : 1'b0}}, a_r};
+ wire [M_WIDTH-1:0] mult_b_ext = {{(M_WIDTH-B_WIDTH){mult_b_sgd ? mult_b[B_WIDTH-1] : 1'b0}}, mult_b};
+
+ wire [M_WIDTH-1:0] mult_m = mult_a_ext * mult_b_ext;
+
+ /******** ACCUMULATOR ********/
+
+ wire [Z_WIDTH-1:0] m_ext;
+
+ generate
+ if (ADDSUB_USED) begin
+ assign pipe_d = mult_m;
+ assign m_ext = {{(Z_WIDTH-M_WIDTH){sgd_r2 ? pipe_q[M_WIDTH-1] : 1'b0}}, pipe_q};
+ assign z_d = (loadc_r2 ? c_r2 : Z) + cin_r2 + (addsub_r2 ? -m_ext : m_ext);
+ end else begin
+ assign z_d = mult_m;
+ end
+ endgenerate
+
+
+endmodule
+
+module MULT9X9 #(
+ parameter REGINPUTA = "REGISTER",
+ parameter REGINPUTB = "REGISTER",
+ parameter REGOUTPUT = "REGISTER",
+ parameter GSR = "ENABLED",
+ parameter RESETMODE = "SYNC"
+) (
+ input [8:0] A,
+ input [8:0] B,
+ input CLK,
+ input CEA,
+ input RSTA,
+ input CEB,
+ input RSTB,
+ input SIGNEDA,
+ input SIGNEDB,
+ input RSTOUT,
+ input CEOUT,
+ output [17:0] Z
+);
+ OXIDE_DSP_SIM #(
+ .REGINPUTA(REGINPUTA),
+ .REGINPUTB(REGINPUTB),
+ .REGOUTPUT(REGOUTPUT),
+ .GSR(GSR),
+ .RESETMODE(RESETMODE),
+
+ .A_WIDTH(9),
+ .B_WIDTH(9),
+ .Z_WIDTH(18),
+ .PREADD_USED(0),
+ .ADDSUB_USED(0)
+ ) dsp_i (
+ .A(A), .B(B),
+ .CLK(CLK),
+ .CEA(CEA), .RSTA(RSTA),
+ .CEB(CEB), .RSTB(RSTB),
+ .SIGNEDA(SIGNEDA), .SIGNEDB(SIGNEDB),
+ .RSTOUT(RSTOUT), .CEOUT(CEOUT),
+ .Z(Z)
+ );
+endmodule
+
+module MULT18X18 #(
+ parameter REGINPUTA = "REGISTER",
+ parameter REGINPUTB = "REGISTER",
+ parameter REGOUTPUT = "REGISTER",
+ parameter GSR = "ENABLED",
+ parameter RESETMODE = "SYNC"
+) (
+ input [17:0] A,
+ input [17:0] B,
+ input CLK,
+ input CEA,
+ input RSTA,
+ input CEB,
+ input RSTB,
+ input SIGNEDA,
+ input SIGNEDB,
+ input RSTOUT,
+ input CEOUT,
+ output [35:0] Z
+);
+ OXIDE_DSP_SIM #(
+ .REGINPUTA(REGINPUTA),
+ .REGINPUTB(REGINPUTB),
+ .REGOUTPUT(REGOUTPUT),
+ .GSR(GSR),
+ .RESETMODE(RESETMODE),
+
+ .A_WIDTH(18),
+ .B_WIDTH(18),
+ .Z_WIDTH(36),
+ .PREADD_USED(0),
+ .ADDSUB_USED(0)
+ ) dsp_i (
+ .A(A), .B(B),
+ .CLK(CLK),
+ .CEA(CEA), .RSTA(RSTA),
+ .CEB(CEB), .RSTB(RSTB),
+ .SIGNEDA(SIGNEDA), .SIGNEDB(SIGNEDB),
+ .RSTOUT(RSTOUT), .CEOUT(CEOUT),
+ .Z(Z)
+ );
+endmodule
+
+module MULT18X36 #(
+ parameter REGINPUTA = "REGISTER",
+ parameter REGINPUTB = "REGISTER",
+ parameter REGOUTPUT = "REGISTER",
+ parameter GSR = "ENABLED",
+ parameter RESETMODE = "SYNC"
+) (
+ input [17:0] A,
+ input [35:0] B,
+ input CLK,
+ input CEA,
+ input RSTA,
+ input CEB,
+ input RSTB,
+ input SIGNEDA,
+ input SIGNEDB,
+ input RSTOUT,
+ input CEOUT,
+ output [53:0] Z
+);
+ OXIDE_DSP_SIM #(
+ .REGINPUTA(REGINPUTA),
+ .REGINPUTB(REGINPUTB),
+ .REGOUTPUT(REGOUTPUT),
+ .GSR(GSR),
+ .RESETMODE(RESETMODE),
+
+ .A_WIDTH(18),
+ .B_WIDTH(36),
+ .Z_WIDTH(54),
+ .PREADD_USED(0),
+ .ADDSUB_USED(0)
+ ) dsp_i (
+ .A(A), .B(B),
+ .CLK(CLK),
+ .CEA(CEA), .RSTA(RSTA),
+ .CEB(CEB), .RSTB(RSTB),
+ .SIGNEDA(SIGNEDA), .SIGNEDB(SIGNEDB),
+ .RSTOUT(RSTOUT), .CEOUT(CEOUT),
+ .Z(Z)
+ );
+endmodule
+
+module MULT36X36 #(
+ parameter REGINPUTA = "REGISTER",
+ parameter REGINPUTB = "REGISTER",
+ parameter REGOUTPUT = "REGISTER",
+ parameter GSR = "ENABLED",
+ parameter RESETMODE = "SYNC"
+) (
+ input [35:0] A,
+ input [35:0] B,
+ input CLK,
+ input CEA,
+ input RSTA,
+ input CEB,
+ input RSTB,
+ input SIGNEDA,
+ input SIGNEDB,
+ input RSTOUT,
+ input CEOUT,
+ output [71:0] Z
+);
+ OXIDE_DSP_SIM #(
+ .REGINPUTA(REGINPUTA),
+ .REGINPUTB(REGINPUTB),
+ .REGOUTPUT(REGOUTPUT),
+ .GSR(GSR),
+ .RESETMODE(RESETMODE),
+
+ .A_WIDTH(36),
+ .B_WIDTH(36),
+ .Z_WIDTH(72),
+ .PREADD_USED(0),
+ .ADDSUB_USED(0)
+ ) dsp_i (
+ .A(A), .B(B),
+ .CLK(CLK),
+ .CEA(CEA), .RSTA(RSTA),
+ .CEB(CEB), .RSTB(RSTB),
+ .SIGNEDA(SIGNEDA), .SIGNEDB(SIGNEDB),
+ .RSTOUT(RSTOUT), .CEOUT(CEOUT),
+ .Z(Z)
+ );
+endmodule
+
+
+module MULTPREADD9X9 #(
+ parameter REGINPUTA = "REGISTER",
+ parameter REGINPUTB = "REGISTER",
+ parameter REGINPUTC = "REGISTER",
+ parameter REGOUTPUT = "REGISTER",
+ parameter GSR = "ENABLED",
+ parameter RESETMODE = "SYNC"
+) (
+ input [8:0] A,
+ input [8:0] B,
+ input [8:0] C,
+ input CLK,
+ input CEA,
+ input RSTA,
+ input CEB,
+ input RSTB,
+ input CEC,
+ input RSTC,
+ input SIGNEDA,
+ input SIGNEDB,
+ input SIGNEDC,
+ input RSTOUT,
+ input CEOUT,
+ output [17:0] Z
+);
+ OXIDE_DSP_SIM #(
+ .REGINPUTA(REGINPUTA),
+ .REGINPUTB(REGINPUTB),
+ .REGINPUTC(REGINPUTC),
+ .REGOUTPUT(REGOUTPUT),
+ .GSR(GSR),
+ .RESETMODE(RESETMODE),
+
+ .A_WIDTH(9),
+ .B_WIDTH(9),
+ .C_WIDTH(9),
+ .Z_WIDTH(18),
+ .PREADD_USED(1),
+ .ADDSUB_USED(0)
+ ) dsp_i (
+ .A(A), .B(B), .C(C),
+ .CLK(CLK),
+ .CEA(CEA), .RSTA(RSTA),
+ .CEB(CEB), .RSTB(RSTB),
+ .CEC(CEC), .RSTC(RSTC),
+ .SIGNEDA(SIGNEDA), .SIGNEDB(SIGNEDB), .SIGNEDC(SIGNEDC),
+ .RSTOUT(RSTOUT), .CEOUT(CEOUT),
+ .Z(Z)
+ );
+endmodule
+
+
+module MULTPREADD18X18 #(
+ parameter REGINPUTA = "REGISTER",
+ parameter REGINPUTB = "REGISTER",
+ parameter REGINPUTC = "REGISTER",
+ parameter REGOUTPUT = "REGISTER",
+ parameter GSR = "ENABLED",
+ parameter RESETMODE = "SYNC"
+) (
+ input [17:0] A,
+ input [17:0] B,
+ input [17:0] C,
+ input CLK,
+ input CEA,
+ input RSTA,
+ input CEB,
+ input RSTB,
+ input CEC,
+ input RSTC,
+ input SIGNEDA,
+ input SIGNEDB,
+ input SIGNEDC,
+ input RSTOUT,
+ input CEOUT,
+ output [35:0] Z
+);
+ OXIDE_DSP_SIM #(
+ .REGINPUTA(REGINPUTA),
+ .REGINPUTB(REGINPUTB),
+ .REGINPUTC(REGINPUTC),
+ .REGOUTPUT(REGOUTPUT),
+ .GSR(GSR),
+ .RESETMODE(RESETMODE),
+
+ .A_WIDTH(18),
+ .B_WIDTH(18),
+ .C_WIDTH(18),
+ .Z_WIDTH(36),
+ .PREADD_USED(1),
+ .ADDSUB_USED(0)
+ ) dsp_i (
+ .A(A), .B(B), .C(C),
+ .CLK(CLK),
+ .CEA(CEA), .RSTA(RSTA),
+ .CEB(CEB), .RSTB(RSTB),
+ .CEC(CEC), .RSTC(RSTC),
+ .SIGNEDA(SIGNEDA), .SIGNEDB(SIGNEDB), .SIGNEDC(SIGNEDC),
+ .RSTOUT(RSTOUT), .CEOUT(CEOUT),
+ .Z(Z)
+ );
+endmodule
+
+
+module MULTADDSUB18X18 #(
+ parameter REGINPUTA = "REGISTER",
+ parameter REGINPUTB = "REGISTER",
+ parameter REGINPUTC = "REGISTER",
+ parameter REGADDSUB = "REGISTER",
+ parameter REGLOADC = "REGISTER",
+ parameter REGLOADC2 = "REGISTER",
+ parameter REGCIN = "REGISTER",
+ parameter REGPIPELINE = "REGISTER",
+ parameter REGOUTPUT = "REGISTER",
+ parameter GSR = "ENABLED",
+ parameter RESETMODE = "SYNC"
+) (
+ input [17:0] A,
+ input [17:0] B,
+ input [53:0] C,
+ input CLK,
+ input CEA,
+ input RSTA,
+ input CEB,
+ input RSTB,
+ input CEC,
+ input RSTC,
+ input SIGNED,
+ input RSTPIPE,
+ input CEPIPE,
+ input RSTCTRL,
+ input CECTRL,
+ input RSTCIN,
+ input CECIN,
+ input LOADC,
+ input ADDSUB,
+ output [53:0] Z,
+ input RSTOUT,
+ input CEOUT,
+ input CIN
+);
+ OXIDE_DSP_SIM #(
+ .REGINPUTA(REGINPUTA),
+ .REGINPUTB(REGINPUTB),
+ .REGINPUTC(REGINPUTC),
+ .REGADDSUB(REGADDSUB),
+ .REGLOADC(REGLOADC),
+ .REGLOADC2(REGLOADC2),
+ .REGCIN(REGCIN),
+ .REGPIPELINE(REGPIPELINE),
+ .REGOUTPUT(REGOUTPUT),
+ .GSR(GSR),
+ .RESETMODE(RESETMODE),
+
+ .A_WIDTH(18),
+ .B_WIDTH(18),
+ .C_WIDTH(54),
+ .Z_WIDTH(54),
+ .PREADD_USED(0),
+ .ADDSUB_USED(1)
+ ) dsp_i (
+ .A(A), .B(B), .C(C),
+ .CLK(CLK),
+ .CEA(CEA), .RSTA(RSTA),
+ .CEB(CEB), .RSTB(RSTB),
+ .CEC(CEC), .RSTC(RSTC),
+ .CEPIPE(CEPIPE), .RSTPIPE(RSTPIPE),
+ .CECTRL(CECTRL), .RSTCTRL(RSTCTRL),
+ .CECIN(CECIN), .RSTCIN(RSTCIN),
+ .CIN(CIN), .LOADC(LOADC), .ADDSUB(ADDSUB),
+ .SIGNEDA(SIGNED), .SIGNEDB(SIGNED), .SIGNEDC(SIGNED),
+ .RSTOUT(RSTOUT), .CEOUT(CEOUT),
+ .Z(Z)
+ );
+endmodule
+
+
+module MULTADDSUB36X36 #(
+ parameter REGINPUTA = "REGISTER",
+ parameter REGINPUTB = "REGISTER",
+ parameter REGINPUTC = "REGISTER",
+ parameter REGADDSUB = "REGISTER",
+ parameter REGLOADC = "REGISTER",
+ parameter REGLOADC2 = "REGISTER",
+ parameter REGCIN = "REGISTER",
+ parameter REGPIPELINE = "REGISTER",
+ parameter REGOUTPUT = "REGISTER",
+ parameter GSR = "ENABLED",
+ parameter RESETMODE = "SYNC"
+) (
+ input [35:0] A,
+ input [35:0] B,
+ input [107:0] C,
+ input CLK,
+ input CEA,
+ input RSTA,
+ input CEB,
+ input RSTB,
+ input CEC,
+ input RSTC,
+ input SIGNED,
+ input RSTPIPE,
+ input CEPIPE,
+ input RSTCTRL,
+ input CECTRL,
+ input RSTCIN,
+ input CECIN,
+ input LOADC,
+ input ADDSUB,
+ output [107:0] Z,
+ input RSTOUT,
+ input CEOUT,
+ input CIN
+);
+ OXIDE_DSP_SIM #(
+ .REGINPUTA(REGINPUTA),
+ .REGINPUTB(REGINPUTB),
+ .REGINPUTC(REGINPUTC),
+ .REGADDSUB(REGADDSUB),
+ .REGLOADC(REGLOADC),
+ .REGLOADC2(REGLOADC2),
+ .REGCIN(REGCIN),
+ .REGPIPELINE(REGPIPELINE),
+ .REGOUTPUT(REGOUTPUT),
+ .GSR(GSR),
+ .RESETMODE(RESETMODE),
+
+ .A_WIDTH(36),
+ .B_WIDTH(36),
+ .C_WIDTH(108),
+ .Z_WIDTH(108),
+ .PREADD_USED(0),
+ .ADDSUB_USED(1)
+ ) dsp_i (
+ .A(A), .B(B), .C(C),
+ .CLK(CLK),
+ .CEA(CEA), .RSTA(RSTA),
+ .CEB(CEB), .RSTB(RSTB),
+ .CEC(CEC), .RSTC(RSTC),
+ .CEPIPE(CEPIPE), .RSTPIPE(RSTPIPE),
+ .CECTRL(CECTRL), .RSTCTRL(RSTCTRL),
+ .CECIN(CECIN), .RSTCIN(RSTCIN),
+ .CIN(CIN), .LOADC(LOADC), .ADDSUB(ADDSUB),
+ .SIGNEDA(SIGNED), .SIGNEDB(SIGNED), .SIGNEDC(SIGNED),
+ .RSTOUT(RSTOUT), .CEOUT(CEOUT),
+ .Z(Z)
+ );
+endmodule
+
+module MULTADDSUB9X9WIDE #(
+ parameter REGINPUTAB0 = "REGISTER",
+ parameter REGINPUTAB1 = "REGISTER",
+ parameter REGINPUTAB2 = "REGISTER",
+ parameter REGINPUTAB3 = "REGISTER",
+ parameter REGINPUTC = "REGISTER",
+ parameter REGADDSUB = "REGISTER",
+ parameter REGLOADC = "REGISTER",
+ parameter REGLOADC2 = "REGISTER",
+ parameter REGPIPELINE = "REGISTER",
+ parameter REGOUTPUT = "REGISTER",
+ parameter GSR = "ENABLED",
+ parameter RESETMODE = "SYNC"
+) (
+ input [8:0] A0, B0, A1, B1, A2, B2, A3, B3,
+ input [53:0] C,
+ input CLK,
+ input CEA0A1, CEA2A3,
+ input RSTA0A1, RSTA2A3,
+ input CEB0B1, CEB2B3,
+ input RSTB0B1, RSTB2B3,
+ input CEC, RSTC,
+ input CECTRL, RSTCTRL,
+ input SIGNED,
+ input RSTPIPE, CEPIPE,
+ input RSTOUT, CEOUT,
+ input LOADC,
+ input [3:0] ADDSUB,
+ output [53:0] Z
+);
+ wire [17:0] m0, m1, m2, m3;
+
+ localparam M_WIDTH = 18;
+ localparam Z_WIDTH = 54;
+
+ MULT9X9 #(
+ .REGINPUTA(REGINPUTAB0), .REGINPUTB(REGINPUTAB0), .REGOUTPUT(REGPIPELINE), .GSR(GSR), .RESETMODE(RESETMODE)
+ ) m9_0 (
+ .A(A0), .B(B0), .SIGNEDA(SIGNED), .SIGNEDB(SIGNED),
+ .CLK(CLK),
+ .CEA(CEA0A1), .RSTA(RSTA0A1),
+ .CEB(CEB0B1), .RSTB(RSTB0B1),
+ .CEOUT(CEPIPE), .RSTOUT(RSTPIPE),
+ .Z(m0)
+ );
+ MULT9X9 #(
+ .REGINPUTA(REGINPUTAB1), .REGINPUTB(REGINPUTAB1), .REGOUTPUT(REGPIPELINE), .GSR(GSR), .RESETMODE(RESETMODE)
+ ) m9_1 (
+ .A(A1), .B(B1), .SIGNEDA(SIGNED), .SIGNEDB(SIGNED),
+ .CLK(CLK),
+ .CEA(CEA0A1), .RSTA(RSTA0A1),
+ .CEB(CEB0B1), .RSTB(RSTB0B1),
+ .CEOUT(CEPIPE), .RSTOUT(RSTPIPE),
+ .Z(m1)
+ );
+ MULT9X9 #(
+ .REGINPUTA(REGINPUTAB2), .REGINPUTB(REGINPUTAB2), .REGOUTPUT(REGPIPELINE), .GSR(GSR), .RESETMODE(RESETMODE)
+ ) m9_2 (
+ .A(A2), .B(B2), .SIGNEDA(SIGNED), .SIGNEDB(SIGNED),
+ .CLK(CLK),
+ .CEA(CEA2A3), .RSTA(RSTA2A3),
+ .CEB(CEB2B3), .RSTB(RSTB2B3),
+ .CEOUT(CEPIPE), .RSTOUT(RSTPIPE),
+ .Z(m2)
+ );
+ MULT9X9 #(
+ .REGINPUTA(REGINPUTAB3), .REGINPUTB(REGINPUTAB3), .REGOUTPUT(REGPIPELINE), .GSR(GSR), .RESETMODE(RESETMODE)
+ ) m9_3 (
+ .A(A3), .B(B3), .SIGNEDA(SIGNED), .SIGNEDB(SIGNED),
+ .CLK(CLK),
+ .CEA(CEA2A3), .RSTA(RSTA2A3),
+ .CEB(CEB2B3), .RSTB(RSTB2B3),
+ .CEOUT(CEPIPE), .RSTOUT(RSTPIPE),
+ .Z(m3)
+ );
+
+ wire [53:0] c_r, c_r2;
+ wire [3:0] addsub_r, addsub_r2;
+ wire sgd_r, sgd_r2, csgd_r, csgd_r2;
+ wire loadc_r, loadc_r2;
+
+ OXIDE_DSP_REG #(5, REGADDSUB, RESETMODE) addsub_reg(CLK, CECTRL, RSTCTRL, {SIGNED, ADDSUB}, {sgd_r, addsub_r});
+ OXIDE_DSP_REG #(5, REGADDSUB, RESETMODE) addsub2_reg(CLK, CECTRL, RSTCTRL, {sgd_r, addsub_r}, {sgd_r2, addsub_r2});
+
+ OXIDE_DSP_REG #(1, REGLOADC, RESETMODE) loadc_reg(CLK, CECTRL, RSTCTRL, LOADC, loadc_r);
+ OXIDE_DSP_REG #(1, REGLOADC2, RESETMODE) loadc2_reg(CLK, CECTRL, RSTCTRL, loadc_r, loadc_r2);
+
+ OXIDE_DSP_REG #(55, REGINPUTC, RESETMODE) c_reg(CLK, CEC, RSTC, {SIGNED, C}, {csgd_r, c_r});
+ OXIDE_DSP_REG #(55, REGPIPELINE, RESETMODE) c2_reg(CLK, CEC, RSTC, {csgd_r, c_r}, {csgd_r2, c_r2});
+
+
+ wire [18:0] m0_ext, m1_ext, m2_ext, m3_ext;
+
+ assign m0_ext = {sgd_r2 ? m0[M_WIDTH-1] : 1'b0, m0};
+ assign m1_ext = {sgd_r2 ? m1[M_WIDTH-1] : 1'b0, m1};
+ assign m2_ext = {sgd_r2 ? m2[M_WIDTH-1] : 1'b0, m2};
+ assign m3_ext = {sgd_r2 ? m3[M_WIDTH-1] : 1'b0, m3};
+
+ wire [18:0] s0 = addsub_r2[2] ? (m0_ext - m1_ext) : (m0_ext + m1_ext);
+ wire [18:0] s1 = addsub_r2[3] ? (m2_ext - m3_ext) : (m2_ext + m3_ext);
+
+ wire [53:0] s0_ext = {{(54-19){sgd_r2 ? s0[18] : 1'b0}}, s0};
+ wire [53:0] s1_ext = {{(54-19){sgd_r2 ? s1[18] : 1'b0}}, s1};
+
+ wire [53:0] c_op = loadc_r2 ? c_r2 : Z;
+
+ // The diagram in the docs is wrong! It is not two cascaded 2-input add/subs as shown,
+ // but a three-input unit with negation controls on two inputs (i.e. addsub_r2[0]
+ // negates s1 not (s1 +/- s0))
+ wire [53:0] z_d = c_op + (addsub_r2[0] ? -s1_ext : s1_ext) + (addsub_r2[1] ? -s0_ext : s0_ext);
+
+ OXIDE_DSP_REG #(Z_WIDTH, REGOUTPUT, RESETMODE) z_reg(CLK, CEOUT, RSTOUT, z_d, Z);
+
+endmodule
diff --git a/techlibs/nexus/cells_xtra.py b/techlibs/nexus/cells_xtra.py
new file mode 100644
index 000000000..6ced76950
--- /dev/null
+++ b/techlibs/nexus/cells_xtra.py
@@ -0,0 +1,286 @@
+#!/usr/bin/env python3
+
+# Based on Xilinx cells_xtra.py; modified for Radiant's structure
+
+from argparse import ArgumentParser
+from io import StringIO
+from enum import Enum, auto
+import os.path
+import sys
+import re
+
+
+class Cell:
+ def __init__(self, name, keep=False, port_attrs={}):
+ self.name = name
+ self.keep = keep
+ self.port_attrs = port_attrs
+ self.found = False
+
+class State(Enum):
+ OUTSIDE = auto()
+ IN_MODULE = auto()
+ IN_OTHER_MODULE = auto()
+ IN_FUNCTION = auto()
+ IN_TASK = auto()
+
+devices = [
+ ("lifcl", [
+ Cell("ACC54"),
+ Cell("ADC"),
+ Cell("ALUREG"),
+ Cell("BB_ADC", keep=True),
+ Cell("BB_CDR", keep=True),
+ Cell("BB_I3C_A", keep=True),
+ Cell("BFD1P3KX"),
+ Cell("BFD1P3LX"),
+ Cell("BNKREF18", keep=True),
+ Cell("CONFIG_LMMI", keep=True),
+ Cell("DCC"),
+ Cell("DCS"),
+ Cell("DDRDLL"),
+ Cell("DELAYA"),
+ Cell("DELAYB"),
+ Cell("DIFFIO18", keep=True),
+ Cell("DLLDEL"),
+ Cell("DP16K_MODE"),
+ Cell("DP16K"),
+ Cell("DPHY", keep=True),
+ Cell("DPSC512K"),
+ Cell("DQSBUF"),
+ Cell("EBR_CORE"),
+ Cell("EBR"),
+ Cell("ECLKDIV"),
+ Cell("ECLKSYNC"),
+ Cell("FBMUX"),
+ Cell("FIFO16K_MODE"),
+ Cell("FIFO16K"),
+ Cell("GSR"),
+ Cell("HSE"),
+ Cell("I2CFIFO"),
+ Cell("IDDR71"),
+ Cell("IDDRX1"),
+ Cell("IDDRX2DQ"),
+ Cell("IDDRX2"),
+ Cell("IDDRX4DQ"),
+ Cell("IDDRX4"),
+ Cell("IDDRX5"),
+ Cell("IFD1P3BX"),
+ Cell("IFD1P3DX"),
+ Cell("IFD1P3IX"),
+ Cell("IFD1P3JX"),
+ Cell("JTAG", keep=True),
+ Cell("LRAM"),
+ Cell("M18X36"),
+ Cell("MIPI"),
+ Cell("MULT18"),
+# Cell("MULT18X18"),
+# Cell("MULT18X36"),
+ Cell("MULT36"),
+# Cell("MULT36X36"),
+ Cell("MULT9"),
+# Cell("MULT9X9"),
+# Cell("MULTADDSUB18X18"),
+ Cell("MULTADDSUB18X18WIDE"),
+# Cell("MULTADDSUB18X36"),
+# Cell("MULTADDSUB36X36"),
+ Cell("MULTADDSUB9X9WIDE"),
+ Cell("MULTIBOOT", keep=True),
+# Cell("MULTPREADD18X18"),
+# Cell("MULTPREADD9X9"),
+ Cell("ODDR71"),
+ Cell("ODDRX1"),
+ Cell("ODDRX2DQS"),
+ Cell("ODDRX2DQ"),
+ Cell("ODDRX2"),
+ Cell("ODDRX4DQS"),
+ Cell("ODDRX4DQ"),
+ Cell("ODDRX4"),
+ Cell("ODDRX5"),
+ Cell("OFD1P3BX"),
+ Cell("OFD1P3DX"),
+ Cell("OFD1P3IX"),
+ Cell("OFD1P3JX"),
+ Cell("OSC"),
+ Cell("OSCA"),
+ Cell("OSHX2"),
+ Cell("OSHX4"),
+ Cell("PCIE"),
+ Cell("PCLKDIV"),
+ Cell("PCLKDIVSP"),
+ Cell("PDP16K_MODE"),
+ Cell("PDP16K"),
+ Cell("PDPSC16K_MODE"),
+ Cell("PDPSC16K"),
+ Cell("PDPSC512K"),
+ Cell("PLL"),
+ Cell("PREADD9"),
+ Cell("PUR", keep=True),
+ Cell("REFMUX"),
+ Cell("REG18"),
+ Cell("SEDC", keep=True),
+ Cell("SEIO18"),
+ Cell("SEIO33"),
+ Cell("SGMIICDR"),
+ Cell("SP16K_MODE"),
+ Cell("SP16K"),
+ Cell("SP512K"),
+ Cell("TSALLA"),
+ Cell("TSHX2DQS"),
+ Cell("TSHX2DQ"),
+ Cell("TSHX4DQS"),
+ Cell("TSHX4DQ"),
+ Cell("WDT", keep=True),
+
+ Cell("ACC54_CORE"),
+ Cell("ADC_CORE"),
+ Cell("ALUREG_CORE"),
+ Cell("BNKREF18_CORE"),
+ Cell("BNKREF33_CORE"),
+ Cell("DIFFIO18_CORE"),
+ Cell("CONFIG_CLKRST_CORE", keep=True),
+ Cell("CONFIG_HSE_CORE", keep=True),
+ Cell("CONFIG_IP_CORE", keep=True),
+ Cell("CONFIG_JTAG_CORE", keep=True),
+ Cell("CONFIG_LMMI_CORE", keep=True),
+ Cell("CONFIG_MULTIBOOT_CORE", keep=True),
+ Cell("CONFIG_SEDC_CORE", keep=True),
+ Cell("CONFIG_WDT_CORE", keep=True),
+ Cell("DDRDLL_CORE"),
+ Cell("DLLDEL_CORE"),
+ Cell("DPHY_CORE"),
+ Cell("DQSBUF_CORE"),
+ Cell("ECLKDIV_CORE"),
+ Cell("ECLKSYNC_CORE"),
+ Cell("FBMUX_CORE"),
+ Cell("GSR_CORE"),
+ Cell("I2CFIFO_CORE"),
+ Cell("LRAM_CORE"),
+ Cell("MULT18_CORE"),
+ Cell("MULT18X36_CORE"),
+ Cell("MULT36_CORE"),
+ Cell("MULT9_CORE"),
+ Cell("OSC_CORE"),
+ Cell("PCIE_CORE"),
+ Cell("PLL_CORE"),
+ Cell("PREADD9_CORE"),
+ Cell("REFMUX_CORE"),
+ Cell("REG18_CORE"),
+ Cell("SEIO18_CORE"),
+ Cell("SEIO33_CORE"),
+ Cell("SGMIICDR_CORE"),
+ ])
+]
+
+def xtract_cells_decl(device, cells, dirs, outf):
+ fname = os.path.join(dir, device + '.v')
+ with open(fname) as f:
+ state = State.OUTSIDE
+ # Probably the most horrible Verilog "parser" ever written.
+ cell = None
+ for l in f:
+ l, _, comment = l.partition('//')
+ l = l.strip()
+ if l.startswith("module "):
+ cell_name = l[7:l.find('(')].strip()
+ cell = None
+ module_ports = []
+ iopad_pin = set()
+ if state != State.OUTSIDE:
+ print('Nested modules in {}.'.format(fname))
+ sys.exit(1)
+ for c in cells:
+ if c.name != cell_name:
+ continue
+ cell = c
+ state = State.IN_MODULE
+ if cell.keep:
+ outf.write('(* keep *)\n')
+ outf.write('module {} (...);\n'.format(cell.name))
+ cell.found = True
+
+ m = re.search(r'synthesis .*black_box_pad_pin="([^"]*)"', comment)
+ if m:
+ iopad_pin = set(m.group(1).split(","))
+
+ if cell is None:
+ state = State.IN_OTHER_MODULE
+ elif l.startswith('task '):
+ if state == State.IN_MODULE:
+ state = State.IN_TASK
+ elif l.startswith('function '):
+ if state == State.IN_MODULE:
+ state = State.IN_FUNCTION
+ elif l == 'endtask':
+ if state == State.IN_TASK:
+ state = State.IN_MODULE
+ elif l == 'endfunction':
+ if state == State.IN_FUNCTION:
+ state = State.IN_MODULE
+ elif l == 'endmodule':
+ if state == State.IN_MODULE:
+ for kind, rng, port in module_ports:
+ for attr in cell.port_attrs.get(port, []):
+ outf.write(' (* {} *)\n'.format(attr))
+ if port in iopad_pin:
+ outf.write(' (* iopad_external_pin *)\n')
+ if rng is None:
+ outf.write(' {} {};\n'.format(kind, port))
+ else:
+ outf.write(' {} {} {};\n'.format(kind, rng, port))
+ outf.write(l + '\n')
+ outf.write('\n')
+ elif state != State.IN_OTHER_MODULE:
+ print('endmodule in weird place in {}.'.format(cell.name, fname))
+ sys.exit(1)
+ state = State.OUTSIDE
+ elif l.startswith(('input ', 'output ', 'inout ')) and state == State.IN_MODULE:
+ if l.endswith((';', ',')):
+ l = l[:-1]
+ if ';' in l:
+ print('Weird port line in {} [{}].'.format(fname, l))
+ sys.exit(1)
+ kind, _, ports = l.partition(' ')
+ for port in ports.split(','):
+ port = port.strip()
+ if port.startswith('['):
+ rng, port = port.split()
+ else:
+ rng = None
+ module_ports.append((kind, rng, port))
+ elif l.startswith('parameter ') and state == State.IN_MODULE:
+ if l.endswith((';', ',')):
+ l = l[:-1]
+ while ' ' in l:
+ l = l.replace(' ', ' ')
+ if ';' in l:
+ print('Weird parameter line in {} [{}].'.format(fname, l))
+ sys.exit(1)
+ outf.write(' {};\n'.format(l))
+
+ if state != State.OUTSIDE:
+ print('endmodule not found in {}.'.format(fname))
+ sys.exit(1)
+ for cell in cells:
+ if not cell.found:
+ print('cell {} not found in {}.'.format(cell.name, fname))
+if __name__ == '__main__':
+ parser = ArgumentParser(description='Extract Lattice blackbox cell definitions from Radiant.')
+ parser.add_argument('radiant_dir', nargs='?', default='/opt/lscc/radiant/2.0/')
+ args = parser.parse_args()
+
+ dirs = [
+ os.path.join(args.radiant_dir, 'cae_library/synthesis/verilog/'),
+ ]
+ for dir in dirs:
+ if not os.path.isdir(dir):
+ print('{} is not a directory'.format(dir))
+
+ out = StringIO()
+ for device, cells in devices:
+ xtract_cells_decl(device, cells, dirs, out)
+
+ with open('cells_xtra.v', 'w') as f:
+ f.write('// Created by cells_xtra.py from Lattice models\n')
+ f.write('\n')
+ f.write(out.getvalue())
diff --git a/techlibs/nexus/cells_xtra.v b/techlibs/nexus/cells_xtra.v
new file mode 100644
index 000000000..6cf3a645d
--- /dev/null
+++ b/techlibs/nexus/cells_xtra.v
@@ -0,0 +1,10389 @@
+// Created by cells_xtra.py from Lattice models
+
+module ACC54 (...);
+ parameter SIGN = "DISABLED";
+ parameter M9ADDSUB_CTRL = "ADDITION";
+ parameter ADDSUB_CTRL = "ADD_ADD_CTRL_54_BIT_ADDER";
+ parameter STATICOPCODE_EN = "DISABLED";
+ parameter OUTREGBYPS = "REGISTER";
+ parameter GSR = "ENABLED";
+ parameter PROGCONST = "0b000000000000000000000000000000000000000000000000000000";
+ parameter CONSTSEL = "BYPASS";
+ parameter DSPCASCADE = "DISABLED";
+ parameter ACC108CASCADE = "BYPASSCASCADE";
+ parameter ACCUMODE = "MODE0";
+ parameter ACCUBYPS = "USED";
+ parameter CREGBYPS1 = "REGISTER";
+ parameter CREGBYPS2 = "REGISTER";
+ parameter CREGBYPS3 = "REGISTER";
+ parameter CINREGBYPS1 = "REGISTER";
+ parameter CINREGBYPS2 = "REGISTER";
+ parameter CINREGBYPS3 = "REGISTER";
+ parameter LOADREGBYPS1 = "REGISTER";
+ parameter LOADREGBYPS2 = "REGISTER";
+ parameter LOADREGBYPS3 = "REGISTER";
+ parameter M9ADDSUBREGBYPS1 = "REGISTER";
+ parameter M9ADDSUBREGBYPS2 = "REGISTER";
+ parameter M9ADDSUBREGBYPS3 = "REGISTER";
+ parameter ADDSUBSIGNREGBYPS1 = "REGISTER";
+ parameter ADDSUBSIGNREGBYPS2 = "REGISTER";
+ parameter ADDSUBSIGNREGBYPS3 = "REGISTER";
+ parameter ROUNDHALFUP = "DISABLED";
+ parameter ROUNDRTZI = "ROUND_TO_ZERO";
+ parameter ROUNDBIT = "ROUND_TO_BIT0";
+ parameter CASCOUTREGBYPS = "REGISTER";
+ parameter SFTEN = "DISABLED";
+ parameter RESET = "SYNC";
+ input [3:0] SFTCTRL;
+ input [53:0] DSPIN;
+ input [71:0] PP;
+ input [53:0] CINPUT;
+ input LOAD;
+ input [1:0] M9ADDSUB;
+ input [1:0] ADDSUB;
+ input CIN;
+ input [1:0] CASIN;
+ input CEO;
+ input RSTO;
+ input CEC;
+ input RSTC;
+ input CLK;
+ input SIGNEDI;
+ output [35:0] SUM1;
+ output [35:0] SUM0;
+ output [53:0] DSPOUT;
+ output [1:0] CASCOUT;
+ input ROUNDEN;
+ input CECIN;
+ input CECTRL;
+ input RSTCIN;
+ input RSTCTRL;
+endmodule
+
+module ADC (...);
+ parameter ADC_ENP = "ENABLED";
+ parameter CLK_DIV = "2";
+ parameter CTLCOMPSW1 = "DISABLED";
+ parameter CTLCOMPSW2 = "DISABLED";
+ parameter CTLCOMPSW3 = "DISABLED";
+ parameter DF = "STRAIGHT_BINARY";
+ parameter EN_COMP1 = "ENABLED";
+ parameter EN_COMP2 = "ENABLED";
+ parameter EN_COMP3 = "ENABLED";
+ parameter OMA = "BIPOLAR";
+ parameter OMB = "BIPOLAR";
+ parameter REFBUFAEN = "ENABLED";
+ parameter REFBUFBEN = "ENABLED";
+ parameter SLEEP = "DISABLED";
+ parameter VREFACFG = "1P0_TO_1P2";
+ parameter VREFASEL = "INTERNAL";
+ parameter VREFBCFG = "1P0_TO_1P2";
+ parameter VREFBSEL = "INTERNAL";
+ (* iopad_external_pin *)
+ input DN0;
+ (* iopad_external_pin *)
+ input DN1;
+ (* iopad_external_pin *)
+ input DP0;
+ (* iopad_external_pin *)
+ input DP1;
+ input ADCEN;
+ input CAL;
+ output CALRDY;
+ input CHAEN;
+ input [3:0] CHASEL;
+ input CHBEN;
+ input [3:0] CHBSEL;
+ input CLKDCLK;
+ input CLKFAB;
+ output COG;
+ input COMP1IN;
+ input COMP1IP;
+ output COMP1OL;
+ input COMP2IN;
+ input COMP2IP;
+ output COMP2OL;
+ input COMP3IN;
+ input COMP3IP;
+ output COMP3OL;
+ input CONVSTOP;
+ output [11:0] DA;
+ output [11:0] DB;
+ output EOC;
+ input [15:0] GPION;
+ input [15:0] GPIOP;
+ input RESETN;
+ input RSTN;
+ input SOC;
+ output COMP1O;
+ output COMP2O;
+ output COMP3O;
+endmodule
+
+module ALUREG (...);
+ parameter ALURST_ACTIVELOW = "DISABLE";
+ parameter GSR = "ENABLED";
+ parameter INREG = "DISABLE";
+ parameter MULFXP_ROUND = "ENABLE";
+ parameter OUTREG = "DISABLE";
+ parameter REGRST_ACTIVELOW = "DISABLE";
+ parameter RETAIN = "ENABLE";
+ parameter RFASYNC_RD = "SYNC_RD";
+ parameter RFR0_RO = "R0READONLY";
+ parameter RFUNALIA_WR = "DISABLE";
+ parameter RFWCLK_INV = "SIG";
+ input ALUCLK;
+ output ALUFLAGC;
+ output ALUFLAGV;
+ output ALUFLAGZ;
+ input ALUFORWARDA;
+ input ALUFORWARDB;
+ input ALUIREGEN;
+ input ALUOREGEN;
+ input ALURST;
+ input [31:0] DATAA;
+ input [31:0] DATAB;
+ input [4:0] DATAC;
+ input [6:0] OPC;
+ input OPCCUSTOM;
+ input [4:0] RADDRA;
+ input [4:0] RADDRB;
+ output [31:0] RDATAA;
+ output [31:0] RDATAB;
+ input REGCLK;
+ input REGCLKEN;
+ input REGRST;
+ output [31:0] RESULT;
+ input [4:0] WADDR;
+ input [1:0] WDROTATE;
+ input WDSIGNEXT;
+ input [1:0] WDSIZE;
+ input [31:0] WDATA;
+ input WREN;
+endmodule
+
+(* keep *)
+module BB_ADC (...);
+ (* iopad_external_pin *)
+ inout IOPAD;
+ output INADC;
+endmodule
+
+(* keep *)
+module BB_CDR (...);
+ (* iopad_external_pin *)
+ inout IOPAD;
+ output INADC;
+endmodule
+
+(* keep *)
+module BB_I3C_A (...);
+ (* iopad_external_pin *)
+ inout IOPAD;
+ output PADDI;
+ input PADDO;
+ input PADDT;
+ input I3CRESEN;
+ input I3CWKPU;
+endmodule
+
+module BFD1P3KX (...);
+ parameter GSR = "ENABLED";
+ parameter OUTSET = "RESET";
+ parameter INSET = "RESET";
+ parameter TSSET = "RESET";
+ input DOUT;
+ input DIN;
+ input DT;
+ input CEOUT;
+ input CLKOUT;
+ input SROUT;
+ input CEIN;
+ input CLKIN;
+ input SRIN;
+ output QOUT;
+ output QIN;
+ output QT;
+endmodule
+
+module BFD1P3LX (...);
+ parameter GSR = "ENABLED";
+ parameter OUTSET = "RESET";
+ parameter INSET = "RESET";
+ parameter TSSET = "RESET";
+ input DOUT;
+ input DIN;
+ input DT;
+ input CEOUT;
+ input CLKOUT;
+ input SROUT;
+ input CEIN;
+ input CLKIN;
+ input SRIN;
+ output QOUT;
+ output QIN;
+ output QT;
+endmodule
+
+(* keep *)
+module BNKREF18 (...);
+ parameter BANK = "0b0000";
+ parameter STANDBY_DIFFIO = "DISABLED";
+ parameter STANDBY_INR = "DISABLED";
+ input STDBYINR;
+ input STDBYDIF;
+ output [6:0] PVTCODE;
+endmodule
+
+(* keep *)
+module CONFIG_LMMI (...);
+ parameter LMMI_EN = "DIS";
+ input LMMICLK;
+ input LMMIREQUEST;
+ input LMMIWRRD_N;
+ input [7:0] LMMIOFFSET;
+ input [7:0] LMMIWDATA;
+ output [7:0] LMMIRDATA;
+ output LMMIREADY;
+ output LMMIRDATAVALID;
+ input LMMIRESETN;
+ input RSTSMCLK;
+ input SMCLK;
+endmodule
+
+module DDRDLL (...);
+ parameter GSR = "ENABLED";
+ parameter ENA_ROUNDOFF = "ENABLED";
+ parameter FORCE_MAX_DELAY = "CODE_OR_LOCK_FROM_DLL_LOOP";
+ output [8:0] CODE;
+ input FREEZE;
+ output LOCK;
+ input CLKIN;
+ input RST;
+ output [8:0] DCNTL;
+ input UDDCNTL_N;
+endmodule
+
+module DELAYA (...);
+ parameter DEL_MODE = "USER_DEFINED";
+ parameter DEL_VALUE = "0";
+ parameter COARSE_DELAY_MODE = "STATIC";
+ parameter COARSE_DELAY = "0NS";
+ parameter EDGE_MONITOR = "DISABLED";
+ parameter WAIT_FOR_EDGE = "DISABLED";
+ input A;
+ input LOAD_N;
+ input MOVE;
+ input DIRECTION;
+ input COARSE0;
+ input COARSE1;
+ input RANKSELECT;
+ input RANKENABLE;
+ input RANK0UPDATE;
+ input RANK1UPDATE;
+ output Z;
+ output EDETERR;
+ output CFLAG;
+endmodule
+
+module DELAYB (...);
+ parameter DEL_VALUE = "0";
+ parameter COARSE_DELAY = "0NS";
+ parameter DEL_MODE = "USER_DEFINED";
+ input A;
+ output Z;
+endmodule
+
+(* keep *)
+module DIFFIO18 (...);
+ parameter PULLMODE = "DOWN";
+ parameter ENADC_IN = "DISABLED";
+ parameter MIPI = "DISABLED";
+ input PADDO;
+ input DOLP;
+ (* iopad_external_pin *)
+ inout IOPAD;
+ output PADDI;
+ output INLP;
+ input PADDT;
+ output INADC;
+ input HSRXEN;
+ input HSTXEN;
+endmodule
+
+module DLLDEL (...);
+ parameter ADJUST = "0";
+ parameter DEL_ADJUST = "PLUS";
+ parameter ENABLE = "ENABLED";
+ input CLKIN;
+ output CLKOUT;
+ input [8:0] CODE;
+ output COUT;
+ input DIR;
+ input LOAD_N;
+ input MOVE;
+endmodule
+
+module DP16K_MODE (...);
+ parameter DATA_WIDTH_A = "X18";
+ parameter DATA_WIDTH_B = "X18";
+ parameter OUTREG_A = "BYPASSED";
+ parameter OUTREG_B = "BYPASSED";
+ parameter GSR = "ENABLED";
+ parameter RESETMODE_A = "SYNC";
+ parameter RESETMODE_B = "SYNC";
+ parameter INITVAL_00 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_01 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_02 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_03 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_04 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_05 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_06 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_07 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_08 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_09 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_10 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_11 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_12 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_13 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_14 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_15 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_16 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_17 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_18 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_19 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_20 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_21 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_22 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_23 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_24 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_25 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_26 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_27 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_28 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_29 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_30 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_31 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_32 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_33 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_34 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_35 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_36 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_37 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_38 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_39 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter CSDECODE_A = "000";
+ parameter CSDECODE_B = "000";
+ parameter ASYNC_RST_RELEASE_A = "SYNC";
+ parameter ASYNC_RST_RELEASE_B = "SYNC";
+ parameter INIT_DATA = "STATIC";
+ input DIA0;
+ input DIA1;
+ input DIA2;
+ input DIA3;
+ input DIA4;
+ input DIA5;
+ input DIA6;
+ input DIA7;
+ input DIA8;
+ input DIA9;
+ input DIA10;
+ input DIA11;
+ input DIA12;
+ input DIA13;
+ input DIA14;
+ input DIA15;
+ input DIA16;
+ input DIA17;
+ input DIB0;
+ input DIB1;
+ input DIB2;
+ input DIB3;
+ input DIB4;
+ input DIB5;
+ input DIB6;
+ input DIB7;
+ input DIB8;
+ input DIB9;
+ input DIB10;
+ input DIB11;
+ input DIB12;
+ input DIB13;
+ input DIB14;
+ input DIB15;
+ input DIB16;
+ input DIB17;
+ input ADA0;
+ input ADA1;
+ input ADA2;
+ input ADA3;
+ input ADA4;
+ input ADA5;
+ input ADA6;
+ input ADA7;
+ input ADA8;
+ input ADA9;
+ input ADA10;
+ input ADA11;
+ input ADA12;
+ input ADA13;
+ input ADB0;
+ input ADB1;
+ input ADB2;
+ input ADB3;
+ input ADB4;
+ input ADB5;
+ input ADB6;
+ input ADB7;
+ input ADB8;
+ input ADB9;
+ input ADB10;
+ input ADB11;
+ input ADB12;
+ input ADB13;
+ input CLKA;
+ input CLKB;
+ input CEA;
+ input CEB;
+ input WEA;
+ input WEB;
+ input CSA0;
+ input CSA1;
+ input CSA2;
+ input CSB0;
+ input CSB1;
+ input CSB2;
+ input RSTA;
+ input RSTB;
+ output DOA0;
+ output DOA1;
+ output DOA2;
+ output DOA3;
+ output DOA4;
+ output DOA5;
+ output DOA6;
+ output DOA7;
+ output DOA8;
+ output DOA9;
+ output DOA10;
+ output DOA11;
+ output DOA12;
+ output DOA13;
+ output DOA14;
+ output DOA15;
+ output DOA16;
+ output DOA17;
+ output DOB0;
+ output DOB1;
+ output DOB2;
+ output DOB3;
+ output DOB4;
+ output DOB5;
+ output DOB6;
+ output DOB7;
+ output DOB8;
+ output DOB9;
+ output DOB10;
+ output DOB11;
+ output DOB12;
+ output DOB13;
+ output DOB14;
+ output DOB15;
+ output DOB16;
+ output DOB17;
+endmodule
+
+module DP16K (...);
+ parameter DATA_WIDTH_A = "X18";
+ parameter DATA_WIDTH_B = "X18";
+ parameter OUTREG_A = "BYPASSED";
+ parameter OUTREG_B = "BYPASSED";
+ parameter GSR = "ENABLED";
+ parameter RESETMODE_A = "SYNC";
+ parameter RESETMODE_B = "SYNC";
+ parameter INITVAL_00 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_01 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_02 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_03 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_04 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_05 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_06 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_07 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_08 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_09 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_10 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_11 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_12 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_13 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_14 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_15 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_16 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_17 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_18 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_19 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_20 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_21 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_22 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_23 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_24 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_25 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_26 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_27 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_28 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_29 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_30 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_31 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_32 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_33 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_34 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_35 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_36 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_37 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_38 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_39 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter CSDECODE_A = "000";
+ parameter CSDECODE_B = "000";
+ parameter ASYNC_RST_RELEASE_A = "SYNC";
+ parameter ASYNC_RST_RELEASE_B = "SYNC";
+ parameter INIT_DATA = "STATIC";
+ input [17:0] DIA;
+ input [17:0] DIB;
+ input [13:0] ADA;
+ input [13:0] ADB;
+ input CLKA;
+ input CLKB;
+ input CEA;
+ input CEB;
+ input WEA;
+ input WEB;
+ input [2:0] CSA;
+ input [2:0] CSB;
+ input RSTA;
+ input RSTB;
+ output [17:0] DOA;
+ output [17:0] DOB;
+endmodule
+
+(* keep *)
+module DPHY (...);
+ parameter GSR = "ENABLED";
+ parameter AUTO_PD_EN = "POWERED_UP";
+ parameter CFG_NUM_LANES = "ONE_LANE";
+ parameter CM = "0b00000000";
+ parameter CN = "0b00000";
+ parameter CO = "0b000";
+ parameter CONT_CLK_MODE = "DISABLED";
+ parameter DESKEW_EN = "DISABLED";
+ parameter DSI_CSI = "CSI2_APP";
+ parameter EN_CIL = "CIL_ENABLED";
+ parameter HSEL = "DISABLED";
+ parameter LANE0_SEL = "LANE_0";
+ parameter LOCK_BYP = "GATE_TXBYTECLKHS";
+ parameter MASTER_SLAVE = "SLAVE";
+ parameter PLLCLKBYPASS = "REGISTERED";
+ parameter RSEL = "0b00";
+ parameter RXCDRP = "0b00";
+ parameter RXDATAWIDTHHS = "0b00";
+ parameter RXLPRP = "0b000";
+ parameter TEST_ENBL = "0b000000";
+ parameter TEST_PATTERN = "0b00000000000000000000000000000000";
+ parameter TST = "0b1001";
+ parameter TXDATAWIDTHHS = "0b00";
+ parameter U_PRG_HS_PREPARE = "0b00";
+ parameter U_PRG_HS_TRAIL = "0b000000";
+ parameter U_PRG_HS_ZERO = "0b000000";
+ parameter U_PRG_RXHS_SETTLE = "0b000000";
+ parameter UC_PRG_HS_PREPARE = "1P0_TXCLKESC";
+ parameter UC_PRG_HS_TRAIL = "0b00000";
+ parameter UC_PRG_HS_ZERO = "0b0000000";
+ parameter UC_PRG_RXHS_SETTLE = "0b000000";
+ input LMMICLK;
+ input LMMIRESET_N;
+ input LMMIREQUEST;
+ input LMMIWRRD_N;
+ input [4:0] LMMIOFFSET;
+ input [3:0] LMMIWDATA;
+ output [3:0] LMMIRDATA;
+ output LMMIRDATAVALID;
+ output LMMIREADY;
+ input BITCKEXT;
+ (* iopad_external_pin *)
+ inout CKN;
+ (* iopad_external_pin *)
+ inout CKP;
+ input CLKREF;
+ output [1:0] D0ACTIVE;
+ output [9:0] D0BYTCNT;
+ output [9:0] D0ERRCNT;
+ output [1:0] D0PASS;
+ output [1:0] D0VALID;
+ output [1:0] D1ACTIVE;
+ output [9:0] D1BYTCNT;
+ output [9:0] D1ERRCNT;
+ output [1:0] D1PASS;
+ output [1:0] D1VALID;
+ output [1:0] D2ACTIVE;
+ output [9:0] D2BYTCNT;
+ output [9:0] D2ERRCNT;
+ output [1:0] D2PASS;
+ output [1:0] D2VALID;
+ output [1:0] D3ACTIVE;
+ output [9:0] D3BYTCNT;
+ output [9:0] D3ERRCNT;
+ output [1:0] D3PASS;
+ output [1:0] D3VALID;
+ output [9:0] DCTSTOUT;
+ (* iopad_external_pin *)
+ inout DN0;
+ (* iopad_external_pin *)
+ inout DN1;
+ (* iopad_external_pin *)
+ inout DN2;
+ (* iopad_external_pin *)
+ inout DN3;
+ (* iopad_external_pin *)
+ inout DP0;
+ (* iopad_external_pin *)
+ inout DP1;
+ (* iopad_external_pin *)
+ inout DP2;
+ (* iopad_external_pin *)
+ inout DP3;
+ output LOCK;
+ input PDDPHY;
+ input PDPLL;
+ input SCCLKIN;
+ output UDIR;
+ input UED0THEN;
+ output UERCLP0;
+ output UERCLP1;
+ output UERCTRL;
+ output UERE;
+ output UERSTHS;
+ output UERSSHS;
+ output UERSE;
+ input UFRXMODE;
+ input UTXMDTX;
+ output URXACTHS;
+ output URXCKE;
+ input URXCKINE;
+ output [7:0] URXDE;
+ output [15:0] URXDHS;
+ output URXLPDTE;
+ output URXSKCHS;
+ output URXDRX;
+ output [3:0] URXSHS;
+ output URE0D3DP;
+ output URE1D3DN;
+ output URE2CKDP;
+ output URE3CKDN;
+ output URXULPSE;
+ output URXVDE;
+ output [3:0] URXVDHS;
+ output USSTT;
+ input UTDIS;
+ input UTXCKE;
+ input UDE0D0TN;
+ input UDE1D1TN;
+ input UDE2D2TN;
+ input UDE3D3TN;
+ input UDE4CKTN;
+ input UDE5D0RN;
+ input UDE6D1RN;
+ input UDE7D2RN;
+ input [31:0] UTXDHS;
+ input UTXENER;
+ output UTXRRS;
+ output UTXRYP;
+ output UTXRYSK;
+ input UTXRD0EN;
+ input UTRD0SEN;
+ input UTXSKD0N;
+ input UTXTGE0;
+ input UTXTGE1;
+ input UTXTGE2;
+ input UTXTGE3;
+ input UTXULPSE;
+ input UTXUPSEX;
+ input UTXVDE;
+ input [3:0] UTXWVDHS;
+ output UUSAN;
+ output U1DIR;
+ input U1ENTHEN;
+ output U1ERCLP0;
+ output U1ERCLP1;
+ output U1ERCTRL;
+ output U1ERE;
+ output U1ERSTHS;
+ output U1ERSSHS;
+ output U1ERSE;
+ input U1FRXMD;
+ input U1FTXST;
+ output U1RXATHS;
+ output U1RXCKE;
+ output [7:0] U1RXDE;
+ output [15:0] U1RXDHS;
+ output U1RXDTE;
+ output U1RXSKS;
+ output U1RXSK;
+ output [3:0] U1RXSHS;
+ output U1RE0D;
+ output U1RE1CN;
+ output U1RE2D;
+ output U1RE3N;
+ output U1RXUPSE;
+ output U1RXVDE;
+ output [3:0] U1RXVDHS;
+ output U1SSTT;
+ input U1TDIS;
+ input U1TREQ;
+ input U1TDE0D3;
+ input U1TDE1CK;
+ input U1TDE2D0;
+ input U1TDE3D1;
+ input U1TDE4D2;
+ input U1TDE5D3;
+ input U1TDE6;
+ input U1TDE7;
+ input [31:0] U1TXDHS;
+ input U1TXLPD;
+ output U1TXRYE;
+ output U1TXRY;
+ output U1TXRYSK;
+ input U1TXREQ;
+ input U1TXREQH;
+ input U1TXSK;
+ input U1TXTGE0;
+ input U1TXTGE1;
+ input U1TXTGE2;
+ input U1TXTGE3;
+ input U1TXUPSE;
+ input U1TXUPSX;
+ input U1TXVDE;
+ input [3:0] U1TXWVHS;
+ output U1USAN;
+ output U2DIR;
+ input U2END2;
+ output U2ERCLP0;
+ output U2ERCLP1;
+ output U2ERCTRL;
+ output U2ERE;
+ output U2ERSTHS;
+ output U2ERSSHS;
+ output U2ERSE;
+ input U2FRXMD;
+ input U2FTXST;
+ output U2RXACHS;
+ output U2RXCKE;
+ output [7:0] U2RXDE;
+ output [15:0] U2RXDHS;
+ output U2RPDTE;
+ output U2RXSK;
+ output U2RXSKC;
+ output [3:0] U2RXSHS;
+ output U2RE0D2;
+ output U2RE1D2;
+ output U2RE2D3;
+ output U2RE3D3;
+ output U2RXUPSE;
+ output U2RXVDE;
+ output [3:0] U2RXVDHS;
+ output U2SSTT;
+ input U2TDIS;
+ input U2TREQ;
+ input U2TDE0D0;
+ input U2TDE1D1;
+ input U2TDE2D2;
+ input U2TDE3D3;
+ input U2TDE4CK;
+ input U2TDE5D0;
+ input U2TDE6D1;
+ input U2TDE7D2;
+ input [31:0] U2TXDHS;
+ input U2TPDTE;
+ output U2TXRYE;
+ output U2TXRYH;
+ output U2TXRYSK;
+ input U2TXREQ;
+ input U2TXREQH;
+ input U2TXSKC;
+ input U2TXTGE0;
+ input U2TXTGE1;
+ input U2TXTGE2;
+ input U2TXTGE3;
+ input U2TXUPSE;
+ input U2TXUPSX;
+ input U2TXVDE;
+ input [3:0] U2TXWVHS;
+ output U2USAN;
+ output U3DIR;
+ input U3END3;
+ output U3ERCLP0;
+ output U3ERCLP1;
+ output U3ERCTRL;
+ output U3ERE;
+ output U3ERSTHS;
+ output U3ERSSHS;
+ output U3ERSE;
+ input U3FRXMD;
+ input U3FTXST;
+ output U3RXATHS;
+ output U3RXCKE;
+ output [7:0] U3RXDE;
+ output [15:0] U3RXDHS;
+ output U3RPDTE;
+ output U3RXSK;
+ output U3RXSKC;
+ output [3:0] U3RXSHS;
+ output U3RE0CK;
+ output U3RE1CK;
+ output U3RE2;
+ output U3RE3;
+ output U3RXUPSE;
+ output U3RXVDE;
+ output [3:0] U3RXVDHS;
+ output U3SSTT;
+ input U3TDISD2;
+ input U3TREQD2;
+ input U3TDE0D3;
+ input U3TDE1D0;
+ input U3TDE2D1;
+ input U3TDE3D2;
+ input U3TDE4D3;
+ input U3TDE5CK;
+ input U3TDE6;
+ input U3TDE7;
+ input [31:0] U3TXDHS;
+ input U3TXLPDT;
+ output U3TXRY;
+ output U3TXRYHS;
+ output U3TXRYSK;
+ input U3TXREQ;
+ input U3TXREQH;
+ input U3TXSKC;
+ input U3TXTGE0;
+ input U3TXTGE1;
+ input U3TXTGE2;
+ input U3TXTGE3;
+ input U3TXULPS;
+ input U3TXUPSX;
+ input U3TXVD3;
+ input [3:0] U3TXWVHS;
+ output U3USAN;
+ input UCENCK;
+ output UCRXCKAT;
+ output UCRXUCKN;
+ output UCSSTT;
+ input UCTXREQH;
+ input UCTXUPSC;
+ input UCTXUPSX;
+ output UCUSAN;
+ input LTSTEN;
+ input [1:0] LTSTLANE;
+ output URWDCKHS;
+ input UTRNREQ;
+ output UTWDCKHS;
+ output UCRXWCHS;
+ output CLKLBACT;
+endmodule
+
+module DPSC512K (...);
+ parameter OUTREG_A = "NO_REG";
+ parameter OUTREG_B = "NO_REG";
+ parameter GSR = "ENABLED";
+ parameter RESETMODE = "SYNC";
+ parameter INITVAL_00 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_01 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_02 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_03 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_04 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_05 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_06 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_07 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_08 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_09 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_10 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_11 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_12 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_13 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_14 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_15 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_16 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_17 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_18 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_19 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_20 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_21 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_22 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_23 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_24 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_25 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_26 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_27 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_28 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_29 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_30 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_31 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_32 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_33 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_34 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_35 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_36 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_37 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_38 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_39 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_40 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_41 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_42 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_43 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_44 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_45 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_46 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_47 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_48 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_49 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_50 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_51 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_52 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_53 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_54 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_55 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_56 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_57 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_58 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_59 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_60 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_61 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_62 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_63 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_64 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_65 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_66 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_67 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_68 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_69 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_70 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_71 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_72 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_73 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_74 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_75 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_76 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_77 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_78 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_79 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter ASYNC_RESET_RELEASE = "SYNC";
+ parameter ECC_BYTE_SEL = "ECC_EN";
+ input [31:0] DIA;
+ input [31:0] DIB;
+ input [13:0] ADA;
+ input [13:0] ADB;
+ input CLK;
+ input CEA;
+ input CEB;
+ input WEA;
+ input WEB;
+ input CSA;
+ input CSB;
+ input RSTA;
+ input RSTB;
+ input [3:0] BENA_N;
+ input [3:0] BENB_N;
+ input CEOUTA;
+ input CEOUTB;
+ output [31:0] DOA;
+ output [31:0] DOB;
+ output [1:0] ERRDECA;
+ output [1:0] ERRDECB;
+endmodule
+
+module DQSBUF (...);
+ parameter GSR = "ENABLED";
+ parameter ENABLE_FIFO = "DISABLED";
+ parameter FORCE_READ = "DISABLED";
+ parameter FREE_WHEEL = "DDR";
+ parameter MODX = "NOT_USED";
+ parameter MT_EN_READ = "DISABLED";
+ parameter MT_EN_WRITE = "DISABLED";
+ parameter MT_EN_WRITE_LEVELING = "DISABLED";
+ parameter RD_PNTR = "0b000";
+ parameter READ_ENABLE = "DISABLED";
+ parameter RX_CENTERED = "ENABLED";
+ parameter S_READ = "0";
+ parameter S_WRITE = "0";
+ parameter SIGN_READ = "POSITIVE";
+ parameter SIGN_WRITE = "POSITIVE";
+ parameter UPDATE_QU = "UP1_AND_UP0_SAME";
+ parameter WRITE_ENABLE = "DISABLED";
+ parameter SEL_READ_BIT_ENABLE_CYCLES = "NORMAL";
+ parameter BYPASS_WR_LEVEL_SMTH_LATCH = "SMOOTHING_PATH";
+ parameter BYPASS_WR_SMTH_LATCH = "SMOOTHING_PATH";
+ parameter BYPASS_READ_SMTH_LATCH = "SMOOTHING_PATH";
+ output BTDETECT;
+ output BURSTDETECT;
+ output DATAVALID;
+ input DQSI;
+ output DQSW;
+ output DQSWRD;
+ input PAUSE;
+ input [3:0] RDCLKSEL;
+ input RDDIR;
+ input RDLOADN;
+ output [2:0] RDPNTR;
+ input [3:0] READ;
+ output READCOUT;
+ input READMOVE;
+ input RST;
+ input SCLK;
+ input SELCLK;
+ output DQSR90;
+ output DQSW270;
+ output WRCOUT;
+ input WRDIR;
+ input WRLOAD_N;
+ output WRLVCOUT;
+ input WRLVDIR;
+ input WRLVLOAD_N;
+ input WRLVMOVE;
+ input WRMOVE;
+ output [2:0] WRPNTR;
+ input ECLKIN;
+ input RSTSMCNT;
+ input [8:0] DLLCODE;
+endmodule
+
+module EBR_CORE (...);
+ parameter INIT_DATA = "STATIC";
+ parameter DATA_WIDTH_A = "X36";
+ parameter DATA_WIDTH_B = "X36";
+ parameter REGMODE_A = "BYPASSED";
+ parameter REGMODE_B = "BYPASSED";
+ parameter GSR = "ENABLED";
+ parameter CSDECODE_A = "000";
+ parameter CSDECODE_B = "000";
+ parameter WID = "0b00000000000";
+ parameter RESETMODE_A = "SYNC";
+ parameter ASYNC_RESET_RELEASE_A = "SYNC";
+ parameter RESETMODE_B = "SYNC";
+ parameter ASYNC_RESET_RELEASE_B = "SYNC";
+ parameter ECC = "DISABLED";
+ parameter EBR_MODE = "DP";
+ parameter FULL = "0b11111111100000";
+ parameter ALMOST_FULL = "0b00000000000000";
+ parameter EMPTY = "0b11111";
+ parameter ALMOST_EMPTY = "0b00000000000000";
+ parameter INITVAL_00 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_01 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_02 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_03 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_04 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_05 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_06 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_07 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_08 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_09 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_10 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_11 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_12 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_13 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_14 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_15 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_16 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_17 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_18 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_19 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_20 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_21 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_22 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_23 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_24 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_25 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_26 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_27 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_28 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_29 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_30 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_31 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_32 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_33 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_34 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_35 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_36 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_37 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_38 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_39 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ input DIA0;
+ input DIA1;
+ input DIA2;
+ input DIA3;
+ input DIA4;
+ input DIA5;
+ input DIA6;
+ input DIA7;
+ input DIA8;
+ input DIA9;
+ input DIA10;
+ input DIA11;
+ input DIA12;
+ input DIA13;
+ input DIA14;
+ input DIA15;
+ input DIA16;
+ input DIA17;
+ input DIB0;
+ input DIB1;
+ input DIB2;
+ input DIB3;
+ input DIB4;
+ input DIB5;
+ input DIB6;
+ input DIB7;
+ input DIB8;
+ input DIB9;
+ input DIB10;
+ input DIB11;
+ input DIB12;
+ input DIB13;
+ input DIB14;
+ input DIB15;
+ input DIB16;
+ input DIB17;
+ input ADA0;
+ input ADA1;
+ input ADA2;
+ input ADA3;
+ input ADA4;
+ input ADA5;
+ input ADA6;
+ input ADA7;
+ input ADA8;
+ input ADA9;
+ input ADA10;
+ input ADA11;
+ input ADA12;
+ input ADA13;
+ input ADB0;
+ input ADB1;
+ input ADB2;
+ input ADB3;
+ input ADB4;
+ input ADB5;
+ input ADB6;
+ input ADB7;
+ input ADB8;
+ input ADB9;
+ input ADB10;
+ input ADB11;
+ input ADB12;
+ input ADB13;
+ input CLKA;
+ input CLKB;
+ input WEA;
+ input WEB;
+ input CEA;
+ input CEB;
+ input RSTA;
+ input RSTB;
+ input CSA0;
+ input CSA1;
+ input CSA2;
+ input CSB0;
+ input CSB1;
+ input CSB2;
+ output FULLF;
+ output AFULL;
+ output EMPTYF;
+ output AEMPTY;
+ output DOA0;
+ output DOA1;
+ output DOA2;
+ output DOA3;
+ output DOA4;
+ output DOA5;
+ output DOA6;
+ output DOA7;
+ output DOA8;
+ output DOA9;
+ output DOA10;
+ output DOA11;
+ output DOA12;
+ output DOA13;
+ output DOA14;
+ output DOA15;
+ output DOA16;
+ output DOA17;
+ output DOB0;
+ output DOB1;
+ output DOB2;
+ output DOB3;
+ output DOB4;
+ output DOB5;
+ output DOB6;
+ output DOB7;
+ output DOB8;
+ output DOB9;
+ output DOB10;
+ output DOB11;
+ output DOB12;
+ output DOB13;
+ output DOB14;
+ output DOB15;
+ output DOB16;
+ output DOB17;
+ output ONEERR;
+ output TWOERR;
+endmodule
+
+module EBR (...);
+ parameter INIT_DATA = "STATIC";
+ parameter DATA_WIDTH_A = "X36";
+ parameter DATA_WIDTH_B = "X36";
+ parameter REGMODE_A = "BYPASSED";
+ parameter REGMODE_B = "BYPASSED";
+ parameter GSR = "ENABLED";
+ parameter CSDECODE_A = "000";
+ parameter CSDECODE_B = "000";
+ parameter WID = "0b00000000000";
+ parameter RESETMODE_A = "SYNC";
+ parameter ASYNC_RESET_RELEASE_A = "SYNC";
+ parameter RESETMODE_B = "SYNC";
+ parameter ASYNC_RESET_RELEASE_B = "SYNC";
+ parameter ECC = "DISABLED";
+ parameter EBR_MODE = "DP";
+ parameter FULL = "0b11111111100000";
+ parameter ALMOST_FULL = "0b00000000000000";
+ parameter ALMOST_EMPTY = "0b00000000000000";
+ parameter INITVAL_00 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_01 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_02 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_03 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_04 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_05 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_06 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_07 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_08 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_09 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_10 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_11 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_12 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_13 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_14 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_15 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_16 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_17 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_18 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_19 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_20 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_21 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_22 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_23 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_24 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_25 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_26 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_27 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_28 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_29 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_30 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_31 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_32 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_33 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_34 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_35 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_36 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_37 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_38 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_39 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ input [17:0] DIA;
+ input [17:0] DIB;
+ input [13:0] ADA;
+ input [13:0] ADB;
+ input CLKA;
+ input CLKB;
+ input WEA;
+ input WEB;
+ input CEA;
+ input CEB;
+ input RSTA;
+ input RSTB;
+ input [2:0] CSA;
+ input [2:0] CSB;
+ output FULLF;
+ output AFULL;
+ output EMPTYF;
+ output AEMPTY;
+ output [17:0] DOA;
+ output [17:0] DOB;
+ output ONEERR;
+ output TWOERR;
+endmodule
+
+module ECLKDIV (...);
+ parameter ECLK_DIV = "DISABLE";
+ parameter GSR = "ENABLED";
+ output DIVOUT;
+ input DIVRST;
+ input ECLKIN;
+ input SLIP;
+endmodule
+
+module ECLKSYNC (...);
+ parameter STOP_EN = "DISABLE";
+ input ECLKIN;
+ output ECLKOUT;
+ input STOP;
+endmodule
+
+module FBMUX (...);
+ parameter INTFB = "IGNORED";
+ parameter SEL_FBK = "DIVA";
+ parameter CLKMUX_FB = "CMUX_CLKOP";
+ parameter INTFBKDEL_SEL = "DISABLED";
+ output ENEXT;
+ output FBKCK;
+ input LGYRDYN;
+ input INTLOCK;
+ input WKUPSYNC;
+ input [15:0] FBKCLK;
+endmodule
+
+module FIFO16K_MODE (...);
+ parameter DATA_WIDTH_A = "X18";
+ parameter DATA_WIDTH_B = "X18";
+ parameter OUTREG_A = "BYPASSED";
+ parameter OUTREG_B = "BYPASSED";
+ parameter GSR = "ENABLED";
+ parameter RESETMODE_A = "SYNC";
+ parameter RESETMODE_B = "SYNC";
+ parameter ASYNC_RST_RELEASE_A = "SYNC";
+ parameter ASYNC_RST_RELEASE_B = "SYNC";
+ parameter ALMOST_FULL = "0b00000000000000";
+ parameter ALMOST_EMPTY = "0b00000000000000";
+ parameter ECC = "DISABLED";
+ parameter FULLBITS = "0b11111111100000";
+ input DIA0;
+ input DIA1;
+ input DIA2;
+ input DIA3;
+ input DIA4;
+ input DIA5;
+ input DIA6;
+ input DIA7;
+ input DIA8;
+ input DIA9;
+ input DIA10;
+ input DIA11;
+ input DIA12;
+ input DIA13;
+ input DIA14;
+ input DIA15;
+ input DIA16;
+ input DIA17;
+ input DIB0;
+ input DIB1;
+ input DIB2;
+ input DIB3;
+ input DIB4;
+ input DIB5;
+ input DIB6;
+ input DIB7;
+ input DIB8;
+ input DIB9;
+ input DIB10;
+ input DIB11;
+ input DIB12;
+ input DIB13;
+ input DIB14;
+ input DIB15;
+ input DIB16;
+ input DIB17;
+ input CKA;
+ input CKB;
+ input CEA;
+ input CEB;
+ input CSA0;
+ input CSA1;
+ input CSA2;
+ input CSB0;
+ input CSB1;
+ input CSB2;
+ input RSTA;
+ input RSTB;
+ output DOA0;
+ output DOA1;
+ output DOA2;
+ output DOA3;
+ output DOA4;
+ output DOA5;
+ output DOA6;
+ output DOA7;
+ output DOA8;
+ output DOA9;
+ output DOA10;
+ output DOA11;
+ output DOA12;
+ output DOA13;
+ output DOA14;
+ output DOA15;
+ output DOA16;
+ output DOA17;
+ output DOB0;
+ output DOB1;
+ output DOB2;
+ output DOB3;
+ output DOB4;
+ output DOB5;
+ output DOB6;
+ output DOB7;
+ output DOB8;
+ output DOB9;
+ output DOB10;
+ output DOB11;
+ output DOB12;
+ output DOB13;
+ output DOB14;
+ output DOB15;
+ output DOB16;
+ output DOB17;
+ output ALMOSTFULL;
+ output FULL;
+ output ALMOSTEMPTY;
+ output EMPTY;
+ output ONEBITERR;
+ output TWOBITERR;
+endmodule
+
+module FIFO16K (...);
+ parameter DATA_WIDTH_A = "X18";
+ parameter DATA_WIDTH_B = "X18";
+ parameter OUTREG_A = "BYPASSED";
+ parameter OUTREG_B = "BYPASSED";
+ parameter GSR = "ENABLED";
+ parameter RESETMODE_A = "SYNC";
+ parameter RESETMODE_B = "SYNC";
+ parameter ASYNC_RST_RELEASE_A = "SYNC";
+ parameter ASYNC_RST_RELEASE_B = "SYNC";
+ parameter ALMOST_FULL = "0b00000000000000";
+ parameter ALMOST_EMPTY = "0b00000000000000";
+ parameter ECC = "DISABLED";
+ parameter FULLBITS = "0b11111111100000";
+ input [17:0] DIA;
+ input [17:0] DIB;
+ input CKA;
+ input CKB;
+ input CEA;
+ input CEB;
+ input [2:0] CSA;
+ input [2:0] CSB;
+ input RSTA;
+ input RSTB;
+ output [17:0] DOA;
+ output [17:0] DOB;
+ output ALMOSTFULL;
+ output FULL;
+ output ALMOSTEMPTY;
+ output EMPTY;
+ output ONEBITERR;
+ output TWOBITERR;
+endmodule
+
+module HSE (...);
+ parameter MCGLBGSRNDIS = "EN";
+ parameter MCHSEDISABLE = "EN";
+ parameter MCHSEOTPEN = "DIS";
+ input LMMICLK;
+ input LMMIRESET_N;
+ input LMMIREQUEST;
+ input LMMIWRRD_N;
+ input [17:0] LMMIOFFSET;
+ input [31:0] LMMIWDATA;
+ output [31:0] LMMIRDATA;
+ output LMMIRDATAVALID;
+ output LMMIREADY;
+ input ASFCLKI;
+ output ASFEMPTYO;
+ output ASFFULLO;
+ input ASFRDI;
+ input ASFRESETI;
+ input ASFWRI;
+ input CFG_CLK;
+ input HSE_CLK;
+ input HSELRSTN;
+endmodule
+
+module I2CFIFO (...);
+ parameter BRNBASEDELAY = "0b0000";
+ parameter CR1CKDIS = "EN";
+ parameter CR1FIFOMODE = "REG";
+ parameter CR1GCEN = "DIS";
+ parameter CR1I2CEN = "DIS";
+ parameter CR1SDADELSEL = "NDLY0";
+ parameter CR1SLPCLKEN = "DIS";
+ parameter CR2CORERSTN = "DIS";
+ parameter CR2HARDTIE = "TIE";
+ parameter CR2INTCLREN = "DIS";
+ parameter CR2MRDCMPLWKUP = "DIS";
+ parameter CR2RXFIFOAFWKUP = "DIS";
+ parameter CR2SLVADDRWKUP = "DIS";
+ parameter GSR = "ENABLED";
+ parameter I2CRXFIFOAFVAL = "0b00000";
+ parameter I2CSLVADDRA = "0b0000000000";
+ parameter I2CTXFIFOAEVAL = "0b0000";
+ parameter INTARBLIE = "DIS";
+ parameter INTBUSFREEIE = "DIS";
+ parameter INTHGCIE = "DIS";
+ parameter INTMRDCMPLIE = "DIS";
+ parameter INTRNACKIEORRSVD = "DIS";
+ parameter INTRSVDORTROEIE = "DIS";
+ parameter INTRSVDORTRRDYIE = "DIS";
+ parameter INTRXOVERFIEORRSVD = "DIS";
+ parameter INTRXUNDERFIE = "DIS";
+ parameter INTTXOVERFIE = "DIS";
+ parameter INTTXSERRIEORRSVD = "DIS";
+ parameter LMMI_EXTRA_ONE = "DIS";
+ parameter LMMI_EXTRA_TWO = "DIS";
+ parameter NCRALTIOEN = "FABRIC";
+ parameter NCRFILTERDIS = "EN";
+ parameter NCRSDAINDLYEN = "DIS";
+ parameter NCRSDAOUTDLYEN = "DIS";
+ parameter NONUSRTESTSOFTTRIMEN = "DIS";
+ parameter NONUSRTSTSOFTTRIMVALUE = "0b000";
+ parameter REGI2CBR = "0b0000000000";
+ parameter TSPTIMERVALUE = "0b10010010111";
+ input LMMICLK;
+ input LMMIRESET_N;
+ input LMMIREQUEST;
+ input LMMIWRRD_N;
+ input [5:0] LMMIOFFSET;
+ input [7:0] LMMIWDATA;
+ output [7:0] LMMIRDATA;
+ output LMMIRDATAVALID;
+ output LMMIREADY;
+ input ALTSCLIN;
+ output ALTSCLOEN;
+ output ALTSCLOUT;
+ input ALTSDAIN;
+ output ALTSDAOEN;
+ output ALTSDAOUT;
+ output BUSBUSY;
+ input FIFORESET;
+ input I2CLSRRSTN;
+ output INSLEEP;
+ output IRQ;
+ output MRDCMPL;
+ output RXFIFOAF;
+ output RXFIFOE;
+ output RXFIFOF;
+ input SCLIN;
+ output SCLOE;
+ output SCLOEN;
+ output SCLOUT;
+ input SDAIN;
+ output SDAOE;
+ output SDAOEN;
+ output SDAOUT;
+ output SLVADDRMATCH;
+ output SLVADDRMATCHSCL;
+ output SRDWR;
+ output TXFIFOAE;
+ output TXFIFOE;
+ output TXFIFOF;
+endmodule
+
+module IDDR71 (...);
+ parameter GSR = "ENABLED";
+ input D;
+ input SCLK;
+ input RST;
+ input ECLK;
+ input ALIGNWD;
+ output Q0;
+ output Q1;
+ output Q2;
+ output Q3;
+ output Q4;
+ output Q5;
+ output Q6;
+endmodule
+
+module IDDRX1 (...);
+ parameter GSR = "ENABLED";
+ input D;
+ input SCLK;
+ input RST;
+ output Q0;
+ output Q1;
+endmodule
+
+module IDDRX2DQ (...);
+ parameter GSR = "ENABLED";
+ input D;
+ input DQSR90;
+ input ECLK;
+ input SCLK;
+ input RST;
+ input RDPNTR0;
+ input RDPNTR1;
+ input RDPNTR2;
+ input WRPNTR0;
+ input WRPNTR1;
+ input WRPNTR2;
+ output Q0;
+ output Q1;
+ output Q2;
+ output Q3;
+endmodule
+
+module IDDRX2 (...);
+ parameter GSR = "ENABLED";
+ input D;
+ input SCLK;
+ input RST;
+ input ECLK;
+ input ALIGNWD;
+ output Q0;
+ output Q1;
+ output Q2;
+ output Q3;
+endmodule
+
+module IDDRX4DQ (...);
+ parameter GSR = "ENABLED";
+ input D;
+ input DQSR90;
+ input ECLK;
+ input SCLK;
+ input RST;
+ input RDPNTR0;
+ input RDPNTR1;
+ input RDPNTR2;
+ input WRPNTR0;
+ input WRPNTR1;
+ input WRPNTR2;
+ output Q0;
+ output Q1;
+ output Q2;
+ output Q3;
+ output Q4;
+ output Q5;
+ output Q6;
+ output Q7;
+endmodule
+
+module IDDRX4 (...);
+ parameter GSR = "ENABLED";
+ input D;
+ input SCLK;
+ input RST;
+ input ECLK;
+ input ALIGNWD;
+ output Q0;
+ output Q1;
+ output Q2;
+ output Q3;
+ output Q4;
+ output Q5;
+ output Q6;
+ output Q7;
+endmodule
+
+module IDDRX5 (...);
+ parameter GSR = "ENABLED";
+ input D;
+ input SCLK;
+ input RST;
+ input ECLK;
+ input ALIGNWD;
+ output Q0;
+ output Q1;
+ output Q2;
+ output Q3;
+ output Q4;
+ output Q5;
+ output Q6;
+ output Q7;
+ output Q8;
+ output Q9;
+endmodule
+
+module IFD1P3BX (...);
+ parameter GSR = "ENABLED";
+ input D;
+ input SP;
+ input CK;
+ input PD;
+ output Q;
+endmodule
+
+module IFD1P3DX (...);
+ parameter GSR = "ENABLED";
+ input D;
+ input SP;
+ input CK;
+ input CD;
+ output Q;
+endmodule
+
+module IFD1P3IX (...);
+ parameter GSR = "ENABLED";
+ input D;
+ input SP;
+ input CK;
+ input CD;
+ output Q;
+endmodule
+
+module IFD1P3JX (...);
+ parameter GSR = "ENABLED";
+ input D;
+ input SP;
+ input CK;
+ input PD;
+ output Q;
+endmodule
+
+(* keep *)
+module JTAG (...);
+ parameter MCER1EXIST = "NEXIST";
+ parameter MCER2EXIST = "NEXIST";
+ output JCE1;
+ output JCE2;
+ output JRSTN;
+ output JRTI1;
+ output JRTI2;
+ output JSHIFT;
+ output JTDI;
+ output JUPDATE;
+ input JTDO1;
+ input JTDO2;
+ input SMCLK;
+ input TCK;
+ output JTCK;
+ input TDI;
+ output TDO_OEN;
+ output TDO;
+ input TMS;
+endmodule
+
+module LRAM (...);
+ parameter INITVAL_00 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_01 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_02 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_03 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_04 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_05 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_06 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_07 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_08 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_09 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_10 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_11 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_12 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_13 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_14 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_15 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_16 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_17 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_18 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_19 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_20 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_21 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_22 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_23 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_24 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_25 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_26 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_27 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_28 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_29 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_30 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_31 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_32 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_33 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_34 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_35 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_36 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_37 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_38 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_39 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_40 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_41 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_42 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_43 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_44 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_45 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_46 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_47 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_48 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_49 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_50 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_51 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_52 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_53 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_54 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_55 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_56 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_57 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_58 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_59 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_60 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_61 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_62 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_63 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_64 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_65 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_66 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_67 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_68 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_69 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_70 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_71 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_72 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_73 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_74 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_75 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_76 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_77 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_78 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_79 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter ASYNC_RST_RELEASE = "SYNC";
+ parameter CFG_INIT_ID = "0b00000000000";
+ parameter DATA_PRESERVE = "DISABLE";
+ parameter EBR_SP_EN = "DISABLE";
+ parameter ECC_BYTE_SEL = "ECC_EN";
+ parameter GSR = "ENABLED";
+ parameter OUT_REGMODE_A = "NO_REG";
+ parameter OUT_REGMODE_B = "NO_REG";
+ parameter RESETMODE = "SYNC";
+ parameter RST_AB_EN = "RESET_AB_DISABLE";
+ parameter SP_EN = "DISABLE";
+ parameter UNALIGNED_READ = "DISABLE";
+ input [13:0] ADA;
+ input [13:0] ADB;
+ input [3:0] BENA_N;
+ input [3:0] BENB_N;
+ input CEA;
+ input CEB;
+ input CLK;
+ input CSA;
+ input CSB;
+ input [31:0] DIA;
+ input [31:0] DIB;
+ output [31:0] DOA;
+ output [31:0] DOB;
+ input DPS;
+ output [1:0] ERRDECA;
+ output [1:0] ERRDECB;
+ input OCEA;
+ input OCEB;
+ output OEA;
+ output OEB;
+ input RSTA;
+ input RSTB;
+ input WEA;
+ input WEB;
+ output ERRDET;
+ output LRAMREADY;
+endmodule
+
+module M18X36 (...);
+ parameter SFTEN = "DISABLED";
+ parameter MULT18X36 = "ENABLED";
+ parameter MULT36 = "DISABLED";
+ parameter MULT36X36H = "USED_AS_LOWER_BIT_GENERATION";
+ parameter ROUNDHALFUP = "DISABLED";
+ parameter ROUNDRTZI = "ROUND_TO_ZERO";
+ parameter ROUNDBIT = "ROUND_TO_BIT0";
+ input [3:0] SFTCTRL;
+ input [37:0] PH36;
+ input [37:0] PL36;
+ input SGNED18H;
+ input SGNED18L;
+ output [72:0] P72;
+ input ROUNDEN;
+endmodule
+
+module MULT18 (...);
+ parameter SFTEN = "DISABLED";
+ parameter MULT18X18 = "ENABLED";
+ parameter ROUNDHALFUP = "DISABLED";
+ parameter ROUNDRTZI = "ROUND_TO_ZERO";
+ parameter ROUNDBIT = "ROUND_TO_BIT0";
+ input [3:0] SFTCTRL;
+ input ARHSIGN;
+ input BRHSIGN;
+ input [8:0] ARH;
+ input [8:0] BRH;
+ input [8:0] ARL;
+ input [8:0] BRL;
+ input [19:0] PL18;
+ input [19:0] PH18;
+ output SIGNED18;
+ output [37:0] P36;
+ input ROUNDEN;
+endmodule
+
+module MULT36 (...);
+ parameter MULT36X36 = "ENABLED";
+ input [72:0] PH72;
+ input [72:0] PL72;
+ output [71:0] PML72;
+ output [71:0] PMH72;
+endmodule
+
+module MULT9 (...);
+ parameter SIGNEDSTATIC_EN = "DISABLED";
+ parameter ASIGNED_OPERAND_EN = "DISABLED";
+ parameter BYPASS_MULT9 = "USED";
+ parameter REGBYPSB = "REGISTER";
+ parameter REGBYPSA1 = "REGISTER";
+ parameter REGBYPSA2 = "REGISTER";
+ parameter SHIFTA = "DISABLED";
+ parameter SR_18BITSHIFT_EN = "DISABLED";
+ parameter GSR = "ENABLED";
+ parameter RESET = "SYNC";
+ input [8:0] A;
+ input ASIGNED;
+ input [8:0] BR;
+ input [8:0] AS1;
+ input [8:0] AS2;
+ input ASSIGNED1;
+ input ASSIGNED2;
+ input BRSIGNED;
+ input CLK;
+ input CEA;
+ input RSTA;
+ output [8:0] AO;
+ output [8:0] BO;
+ output AOSIGNED;
+ output BOSIGNED;
+ output [8:0] AR;
+ output ARSIGNED;
+ output [19:0] P18;
+ input CEP;
+ input RSTP;
+endmodule
+
+module MULTADDSUB18X18WIDE (...);
+ parameter REGINPUTAB0 = "REGISTER";
+ parameter REGINPUTAB1 = "REGISTER";
+ parameter REGINPUTC = "REGISTER";
+ parameter REGADDSUB = "REGISTER";
+ parameter REGLOADC = "REGISTER";
+ parameter REGLOADC2 = "REGISTER";
+ parameter REGPIPELINE = "REGISTER";
+ parameter REGOUTPUT = "REGISTER";
+ parameter GSR = "ENABLED";
+ parameter RESETMODE = "SYNC";
+ input [17:0] A0;
+ input [17:0] B0;
+ input [17:0] A1;
+ input [17:0] B1;
+ input [53:0] C;
+ input CLK;
+ input CEA0;
+ input CEA1;
+ input RSTA0;
+ input RSTA1;
+ input CEB0;
+ input CEB1;
+ input RSTB0;
+ input RSTB1;
+ input CEC;
+ input RSTC;
+ input RSTCTRL;
+ input CECTRL;
+ input SIGNED;
+ input RSTPIPE;
+ input CEPIPE;
+ output [53:0] Z;
+ input RSTOUT;
+ input CEOUT;
+ input LOADC;
+ input [1:0] ADDSUB;
+endmodule
+
+module MULTADDSUB9X9WIDE (...);
+ parameter REGINPUTAB0 = "REGISTER";
+ parameter REGINPUTAB1 = "REGISTER";
+ parameter REGINPUTAB2 = "REGISTER";
+ parameter REGINPUTAB3 = "REGISTER";
+ parameter REGINPUTC = "REGISTER";
+ parameter REGADDSUB = "REGISTER";
+ parameter REGLOADC = "REGISTER";
+ parameter REGLOADC2 = "REGISTER";
+ parameter REGPIPELINE = "REGISTER";
+ parameter REGOUTPUT = "REGISTER";
+ parameter GSR = "ENABLED";
+ parameter RESETMODE = "SYNC";
+ input [8:0] A0;
+ input [8:0] B0;
+ input [8:0] A1;
+ input [8:0] B1;
+ input [8:0] A2;
+ input [8:0] B2;
+ input [8:0] A3;
+ input [8:0] B3;
+ input [53:0] C;
+ input CLK;
+ input CEA0A1;
+ input CEA2A3;
+ input RSTA0A1;
+ input RSTA2A3;
+ input CEB0B1;
+ input CEB2B3;
+ input RSTB0B1;
+ input RSTB2B3;
+ input CEC;
+ input RSTC;
+ input RSTCTRL;
+ input CECTRL;
+ input SIGNED;
+ input RSTPIPE;
+ input CEPIPE;
+ input RSTOUT;
+ input CEOUT;
+ input LOADC;
+ input [3:0] ADDSUB;
+ output [53:0] Z;
+endmodule
+
+(* keep *)
+module MULTIBOOT (...);
+ parameter MSPIADDR = "0b00000000000000000000000000000000";
+ parameter SOURCESEL = "DIS";
+ input AUTOREBOOT;
+ input [31:0] MSPIMADDR;
+endmodule
+
+module ODDR71 (...);
+ parameter GSR = "ENABLED";
+ input D0;
+ input D1;
+ input D2;
+ input D3;
+ input D4;
+ input D5;
+ input D6;
+ input SCLK;
+ input RST;
+ input ECLK;
+ output Q;
+endmodule
+
+module ODDRX1 (...);
+ parameter GSR = "ENABLED";
+ input D0;
+ input D1;
+ input SCLK;
+ input RST;
+ output Q;
+endmodule
+
+module ODDRX2DQS (...);
+ parameter GSR = "ENABLED";
+ input D0;
+ input D1;
+ input D2;
+ input D3;
+ input DQSW;
+ input ECLK;
+ input SCLK;
+ input RST;
+ output Q;
+endmodule
+
+module ODDRX2DQ (...);
+ parameter GSR = "ENABLED";
+ input D0;
+ input D1;
+ input D2;
+ input D3;
+ input DQSW270;
+ input ECLK;
+ input SCLK;
+ input RST;
+ output Q;
+endmodule
+
+module ODDRX2 (...);
+ parameter GSR = "ENABLED";
+ input D0;
+ input D1;
+ input D2;
+ input D3;
+ input SCLK;
+ input RST;
+ input ECLK;
+ output Q;
+endmodule
+
+module ODDRX4DQS (...);
+ parameter GSR = "ENABLED";
+ input D0;
+ input D1;
+ input D2;
+ input D3;
+ input D4;
+ input D5;
+ input D6;
+ input D7;
+ input DQSW;
+ input ECLK;
+ input SCLK;
+ input RST;
+ output Q;
+endmodule
+
+module ODDRX4DQ (...);
+ parameter GSR = "ENABLED";
+ input D0;
+ input D1;
+ input D2;
+ input D3;
+ input D4;
+ input D5;
+ input D6;
+ input D7;
+ input DQSW270;
+ input ECLK;
+ input SCLK;
+ input RST;
+ output Q;
+endmodule
+
+module ODDRX4 (...);
+ parameter GSR = "ENABLED";
+ input D0;
+ input D1;
+ input D2;
+ input D3;
+ input D4;
+ input D5;
+ input D6;
+ input D7;
+ input SCLK;
+ input RST;
+ input ECLK;
+ output Q;
+endmodule
+
+module ODDRX5 (...);
+ parameter GSR = "ENABLED";
+ input D0;
+ input D1;
+ input D2;
+ input D3;
+ input D4;
+ input D5;
+ input D6;
+ input D7;
+ input D8;
+ input D9;
+ input SCLK;
+ input RST;
+ input ECLK;
+ output Q;
+endmodule
+
+module OFD1P3BX (...);
+ parameter GSR = "ENABLED";
+ input D;
+ input SP;
+ input CK;
+ input PD;
+ output Q;
+endmodule
+
+module OFD1P3DX (...);
+ parameter GSR = "ENABLED";
+ input D;
+ input SP;
+ input CK;
+ input CD;
+ output Q;
+endmodule
+
+module OFD1P3IX (...);
+ parameter GSR = "ENABLED";
+ input D;
+ input SP;
+ input CK;
+ input CD;
+ output Q;
+endmodule
+
+module OFD1P3JX (...);
+ parameter GSR = "ENABLED";
+ input D;
+ input SP;
+ input CK;
+ input PD;
+ output Q;
+endmodule
+
+module OSHX2 (...);
+ parameter GSR = "ENABLED";
+ input D0;
+ input D1;
+ input ECLK;
+ input SCLK;
+ input RST;
+ output Q;
+endmodule
+
+module OSHX4 (...);
+ parameter GSR = "ENABLED";
+ input D0;
+ input D1;
+ input D2;
+ input D3;
+ input ECLK;
+ input SCLK;
+ input RST;
+ output Q;
+endmodule
+
+module PCIE (...);
+ parameter ENABLE_USER_CFG = "DISABLED";
+ parameter PWDN_N = "DISABLED";
+ parameter GSR = "ENABLED";
+ parameter IDDQ_PCS = "DISABLED";
+ parameter PHY_MODE = "0b0000";
+ parameter ALT_CLK_SEL_VCC = "PAD";
+ parameter L0S_ADJ = "0b00000110000000";
+ parameter L0S_EXIT_LATENCY = "MORE_4_US";
+ parameter L1_EXIT_LATENCY = "MORE_64_US";
+ parameter CALIB_3DB = "ENABLED";
+ parameter DB_UPSTREAM = "6DB";
+ parameter ERR_REC_ENTRY_SEL = "RCVRY_AFTER";
+ parameter A_CHNGD_MAX = "0b100";
+ parameter A0_FORCE = "DISABLED";
+ parameter A0_FREEZE = "DISABLED";
+ parameter A0_INIT = "0b000000";
+ parameter A0DIR_VAL = "DISABLED";
+ parameter A1_FORCE = "DISABLED";
+ parameter A1_FREEZE = "DISABLED";
+ parameter A1_INIT = "0b000000";
+ parameter A1DIR_VAL = "DISABLED";
+ parameter A2_FORCE = "DISABLED";
+ parameter A2_FREEZE = "DISABLED";
+ parameter A2_INIT = "0b000000";
+ parameter A2GAIN_CALIB = "0b100110";
+ parameter ACJTAG_REG = "0b00";
+ parameter ADDR_LIMIT_PRE_MTHD_CTRL = "0b0100";
+ parameter ADDR_LIMIT_TABLE_MTHD_CTRL = "0b00101";
+ parameter ADIR_OVR = "DISABLED";
+ parameter ADV_CH_CD_SEL = "IMPLEMENT_CH";
+ parameter ADV_TARGET_LINK_SPEED_USPORT_A = "DISABLED";
+ parameter ADV_TARGET_LINK_SPEED_USPORT_B = "DISABLED";
+ parameter ADV_TARGET_LINK_SPEED_USPORT_C = "DISABLED";
+ parameter ADV_TARGET_LINK_SPEED_USPORT_D = "DISABLED";
+ parameter ADVANCE = "DISABLED";
+ parameter ALERT_ENABLE = "0b000";
+ parameter ALMOST_EMPTY_10B = "0b001110";
+ parameter MID_VALUE_10B = "0b011110";
+ parameter ALMOST_EMPTY_20B = "0b001111";
+ parameter ALMOST_EMPTY_GEN3 = "0b001100";
+ parameter ALMOST_FULL_10B = "0b110000";
+ parameter ALMOST_FULL_20B = "0b011000";
+ parameter ALMOST_FULL_GEN3 = "0b010110";
+ parameter ARRAY_DA = "0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter ARRAY_MT = "0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000011100000000000010000000000000001001000000000000011000000000000001010000000000000100";
+ parameter ARXCDRICP_RATE0 = "0b011";
+ parameter ARXCDRICP_RATE1 = "0b011";
+ parameter ARXCDRICP_RATE2 = "0b011";
+ parameter ARXDMPWRDWN = "DISABLED";
+ parameter ARXDPPWRDN = "DISABLED";
+ parameter ARXEOM_PWRDN = "POWERED_DOWN";
+ parameter ARXICP_RATE0 = "0b011";
+ parameter ARXICP_RATE1 = "0b011";
+ parameter ARXICP_RATE2 = "0b011";
+ parameter ARXOVR_OUT = "DISABLED";
+ parameter ARXRSACTAT = "0b0001";
+ parameter ARXRSAPTAT = "0b1000";
+ parameter ARXRSVCTL = "0b00000000";
+ parameter ARXSEL_OUT = "DISABLED";
+ parameter ASPM_L1_1_SUPPORTED = "SUPPORTED";
+ parameter ASPM_L1_2_SUPPORTED = "SUPPORTED";
+ parameter ASPM_SUPPORT = "L0S_AND_L1_SUPPORTED";
+ parameter ATTENTION_BUTTON_PRESENT = "NOT_SUPPORTED";
+ parameter ATTENTION_INDICATOR_PRESENT = "NOT_SUPPORTED";
+ parameter ATXICP_RATE0 = "0b101";
+ parameter ATXICP_RATE1 = "0b101";
+ parameter AUTO_SHIFT = "ENABLED";
+ parameter AUX_CURRENT = "SELF_POWERED";
+ parameter AUXCLK1US_MAX = "0b00001001";
+ parameter AUXIDL_MAX = "0b00000100";
+ parameter BAR_INDEX_CFG0_A = "0b000";
+ parameter BAR_INDEX_CFG0_B = "0b000";
+ parameter BAR_INDEX_CFG0_C = "0b000";
+ parameter BAR_INDEX_CFG0_D = "0b000";
+ parameter BAR_INDEX_CFG1_A = "0b001";
+ parameter BAR_INDEX_CFG1_B = "0b001";
+ parameter BAR_INDEX_CFG1_C = "0b001";
+ parameter BAR_INDEX_CFG1_D = "0b001";
+ parameter BAR_INDEX_CFG2_A = "0b010";
+ parameter BAR_INDEX_CFG2_B = "0b010";
+ parameter BAR_INDEX_CFG2_C = "0b010";
+ parameter BAR_INDEX_CFG2_D = "0b010";
+ parameter BAR_INDEX_CFG3_A = "0b011";
+ parameter BAR_INDEX_CFG3_B = "0b011";
+ parameter BAR_INDEX_CFG3_C = "0b011";
+ parameter BAR_INDEX_CFG3_D = "0b011";
+ parameter BAR_INDEX_CFG4_A = "0b100";
+ parameter BAR_INDEX_CFG4_B = "0b100";
+ parameter BAR_INDEX_CFG4_C = "0b100";
+ parameter BAR_INDEX_CFG4_D = "0b100";
+ parameter BAR_INDEX_CFG5_A = "0b101";
+ parameter BAR_INDEX_CFG5_B = "0b101";
+ parameter BAR_INDEX_CFG5_C = "0b101";
+ parameter BAR_INDEX_CFG5_D = "0b101";
+ parameter BIR_MSIX_PBA_A = "BAR0";
+ parameter BIR_MSIX_PBA_B = "BAR0";
+ parameter BIR_MSIX_PBA_C = "BAR0";
+ parameter BIR_MSIX_PBA_D = "BAR0";
+ parameter BIR_MSIX_TABLE_A = "BAR0";
+ parameter BIR_MSIX_TABLE_B = "BAR0";
+ parameter BIR_MSIX_TABLE_C = "BAR0";
+ parameter BIR_MSIX_TABLE_D = "BAR0";
+ parameter BYP_AVG = "USED";
+ parameter BYPASS = "PERFORM_RECEIVER_DETECTION";
+ parameter BYPASS_ADDR_DEC = "NORMAL";
+ parameter CALIB_SETTLE_MAX = "0b001";
+ parameter CALIB_STABLE_MAX = "0b11000";
+ parameter CAPABILITY_VERSION = "0b0010";
+ parameter CDR_ERR = "DISABLED";
+ parameter CDR_P1 = "CDR_PLL_RESET";
+ parameter CDR_PLL_DELTA = "0P4_PERCENT";
+ parameter CDR_REFERENCE = "0b00";
+ parameter CDRPLL_CMP_MAX = "0b00010100";
+ parameter CDRPLL_CNT_MAX = "0b00000100";
+ parameter CDRPLL_PRE_RXEQ_COARSE_TIMER = "0b01010000";
+ parameter CDRPLL_PRE_RXEQ_FINE_TIMER = "0b10110100";
+ parameter CDRPLL_PST_RXEQ_COARSE_TIMER = "0b01000000";
+ parameter CDRPLL_PST_RXEQ_FINE_TIMER = "0b01000010";
+ parameter CFG_A_BAR0 = "0b11111111111111110000000000001100";
+ parameter CFG_A_BAR1 = "0b11111111111111111111111111111111";
+ parameter CFG_A_BAR2 = "0b11111111111111111110000000001100";
+ parameter CFG_A_BAR3 = "0b11111111111111111111111111111111";
+ parameter CFG_A_BAR4 = "0b11111111111111111110000000001100";
+ parameter CFG_A_BAR5 = "0b11111111111111111111111111111111";
+ parameter CFG_B_BAR0 = "0b11111111111111110000000000001100";
+ parameter CFG_B_BAR1 = "0b11111111111111111111111111111111";
+ parameter CFG_B_BAR2 = "0b11111111111111111110000000001100";
+ parameter CFG_B_BAR3 = "0b11111111111111111111111111111111";
+ parameter CFG_B_BAR4 = "0b11111111111111111110000000001100";
+ parameter CFG_B_BAR5 = "0b11111111111111111111111111111111";
+ parameter CFG_C_BAR0 = "0b11111111111111110000000000001100";
+ parameter CFG_C_BAR1 = "0b11111111111111111111111111111111";
+ parameter CFG_C_BAR2 = "0b11111111111111111110000000001100";
+ parameter CFG_C_BAR3 = "0b11111111111111111111111111111111";
+ parameter CFG_C_BAR4 = "0b11111111111111111110000000001100";
+ parameter CFG_C_BAR5 = "0b11111111111111111111111111111111";
+ parameter CFG_D_BAR0 = "0b11111111111111110000000000001100";
+ parameter CFG_D_BAR1 = "0b11111111111111111111111111111111";
+ parameter CFG_D_BAR2 = "0b11111111111111111110000000001100";
+ parameter CFG_D_BAR3 = "0b11111111111111111111111111111111";
+ parameter CFG_D_BAR4 = "0b11111111111111111110000000001100";
+ parameter CFG_D_BAR5 = "0b11111111111111111111111111111111";
+ parameter CFG_EXP_ROM_A = "0b00000000000000000000000000000000";
+ parameter CFG_EXP_ROM_B = "0b00000000000000000000000000000000";
+ parameter CFG_EXP_ROM_C = "0b00000000000000000000000000000000";
+ parameter CFG_EXP_ROM_D = "0b00000000000000000000000000000000";
+ parameter CIS_POINTER_CARDBUS_A = "0b00000000000000000000000000000000";
+ parameter CIS_POINTER_CARDBUS_B = "0b00000000000000000000000000000000";
+ parameter CIS_POINTER_CARDBUS_C = "0b00000000000000000000000000000000";
+ parameter CIS_POINTER_CARDBUS_D = "0b00000000000000000000000000000000";
+ parameter CLASS_CODE_ID3A = "0b000100011000000000000000";
+ parameter CLASS_CODE_ID3B = "0b000100011000000000000000";
+ parameter CLASS_CODE_ID3C = "0b000100011000000000000000";
+ parameter CLASS_CODE_ID3D = "0b000100011000000000000000";
+ parameter CM_RESTORE_TIME = "0b00000000";
+ parameter CNT250NS_MAX = "0b001111100";
+ parameter COARSE_GAIN = "DISABLED";
+ parameter COEF_EN_LPBK_MASTER = "OTHERWISE";
+ parameter COEF_EN_LPBK_SLAVE = "OTHERWISE";
+ parameter COEF_ENABLE = "DETERMINE_LOCAL_PHY";
+ parameter COEF_EQTX_FORCE = "0b000000000000000000";
+ parameter COEF_LPBK_MASTER = "0b000000000000000000";
+ parameter COEF_LPBK_SLAVE = "0b000000000000000000";
+ parameter COEF0_POST = "0b000101";
+ parameter COEF0_POST_CURSOR = "0b000000";
+ parameter COEF0_PRE = "0b000000";
+ parameter COEF0_PRE_CURSOR = "0b000000";
+ parameter COEF1_POST = "0b000011";
+ parameter COEF1_POST_CURSOR = "0b000000";
+ parameter COEF1_PRE = "0b000000";
+ parameter COEF1_PRE_CURSOR = "0b000000";
+ parameter COEF10_POST = "0b000111";
+ parameter COEF10_PRE = "0b000000";
+ parameter COEF2_POST = "0b000100";
+ parameter COEF2_POST_CURSOR = "0b000000";
+ parameter COEF2_PRE = "0b000000";
+ parameter COEF2_PRE_CURSOR = "0b000000";
+ parameter COEF3_POST = "0b000010";
+ parameter COEF3_POST_CURSOR = "0b000000";
+ parameter COEF3_PRE = "0b000000";
+ parameter COEF3_PRE_CURSOR = "0b000000";
+ parameter COEF4_POST = "0b000000";
+ parameter COEF4_PRE = "0b000000";
+ parameter COEF5_POST = "0b000000";
+ parameter COEF5_PRE = "0b000001";
+ parameter COEF6_POST = "0b000000";
+ parameter COEF6_PRE = "0b000010";
+ parameter COEF7_POST = "0b000100";
+ parameter COEF7_PRE = "0b000011";
+ parameter COEF8_POST = "0b000011";
+ parameter COEF8_PRE = "0b000010";
+ parameter COEF9_POST = "0b000000";
+ parameter COEF9_PRE = "0b000011";
+ parameter COMP_128_SUPPORTED = "ENABLED";
+ parameter COMP_32_SUPPORTED = "ENABLED";
+ parameter COMP_64_SUPPORTED = "ENABLED";
+ parameter COMPLETE = "DISABLED";
+ parameter CONV_METHOD = "COMPUTE_PCIE_SPEC";
+ parameter CORE_BYPASS = "NORMAL";
+ parameter CORE_EN = "ENABLED";
+ parameter COUNT_ACK_TO_NAK = "0b00000000";
+ parameter CPL_TIMEOUT_DISABLE_SUPPORTED = "SUPPORTED";
+ parameter CPL_TIMEOUT_RANGES_SUPPORTED = "NOT_SUPPORTED";
+ parameter CRS_ENABLE = "DISABLED";
+ parameter CSTAT_DATA_SCALE = "UNKNOWN_SCALE";
+ parameter CSTAT_DATA_SELECT = "D0_POWER_CONSUMED";
+ parameter CTLE_SETTLE = "0b100";
+ parameter CTLEBIAS_1 = "0b1000";
+ parameter ATXICP_RATE2 = "0b100";
+ parameter CTLEBYPASS = "DISABLED";
+ parameter CUR_FOM = "NUMBER_OF_CLOCK";
+ parameter CUR_FOM_AVG = "0b101";
+ parameter CUST_AUTO = "DISABLED";
+ parameter CUST_CHK = "SET";
+ parameter CUST_SEL = "DISABLED";
+ parameter CUST_SKIP = "DISABLED";
+ parameter CUST_TYP = "0b000";
+ parameter CUSTOM_PATTERN = "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter D1_SUPPORT = "SUPPORTED";
+ parameter D2_SUPPORT = "SUPPORTED";
+ parameter DATA_INJECT = "0b00000000000000000000000000000000";
+ parameter DATA_PM = "0b00000000";
+ parameter DEEMPH_5G_3_5DB_6DB_N = "6DB";
+ parameter DEEMPH_5G_ENABLE = "DISABLED";
+ parameter DEEMPH_LPBK_MASTER = "6P0DB";
+ parameter DEEMPH_LPBK_SLAVE = "6P0DB";
+ parameter DEVICE_ID_ID1A = "0b1110000000000100";
+ parameter DEVICE_ID_ID1B = "0b1110000000000100";
+ parameter DEVICE_ID_ID1C = "0b1110000000000100";
+ parameter DEVICE_ID_ID1D = "0b1110000000000100";
+ parameter DEVICE_PORT_TYPE = "PCIE_ENDPOINT";
+ parameter DFE_BIAS = "0b0001";
+ parameter DFE_PWDN = "DISABLED";
+ parameter DIR_PRE_GAIN = "0b00";
+ parameter DIR_PST_GAIN = "0b01";
+ parameter DIS_ARI_CAP = "ENABLED";
+ parameter DIS_CSR_RST = "DISABLED";
+ parameter DIS_INTERRUPT = "ENABLED";
+ parameter DIS_INTERRUPT_B = "ENABLED";
+ parameter DIS_INTERRUPT_C = "ENABLED";
+ parameter DIS_INTERRUPT_D = "ENABLED";
+ parameter DIS_MSI_CAP = "ENABLED";
+ parameter DIS_MSI_CAP_B = "ENABLED";
+ parameter DIS_MSI_CAP_C = "ENABLED";
+ parameter DIS_MSI_CAP_D = "ENABLED";
+ parameter DIS_MSIX_CAP = "ENABLED";
+ parameter DIS_MSIX_CAP_B = "ENABLED";
+ parameter DIS_MSIX_CAP_C = "ENABLED";
+ parameter DIS_MSIX_CAP_D = "ENABLED";
+ parameter DISABLE_FLR_CAPABILITY = "ENABLED";
+ parameter DLLP_CRC_ERR_ENABLE = "DISABLED";
+ parameter DLLP_CRC_ERR_RATE = "0b000000000000";
+ parameter DLLP_INJECT_ENABLE = "DISABLED";
+ parameter DOUBLE_TX_DATA_VALID = "ONE_CLK_EVERY_64_CLKS";
+ parameter DOWNSTREAM_EQ_SKIP_PHASE_2_3 = "NORMAL_OPERATION";
+ parameter DS_DRIVE_CLKREQ = "ENABLED";
+ parameter DS_PORT_RX_PRESET_HINT = "0b001";
+ parameter DS_PORT_TX_PRESET = "0b0011";
+ parameter DS_US_N_PORTTYPE = "UPSTREAM";
+ parameter DSI = "NO_DSI_NECESSARY";
+ parameter DSP_DIR = "ANALYSIS_OF_DATA_BY_DSP";
+ parameter DSPDIR_PRESGN = "0b11110000";
+ parameter DSPDIR_PREVAL = "0b00011000";
+ parameter DSPDIR_PSTSGN0 = "0b11111111";
+ parameter DSPDIR_PSTSGN1 = "0b00000000";
+ parameter DSPDIR_PSTVAL0 = "0b00000010";
+ parameter DSPDIR_PSTVAL1 = "0b01000000";
+ parameter EARLY_RX_EVAL = "RX_SIGNAL_AFTER_TS1";
+ parameter ECRC_GEN_CHK_CAPABLE = "SUPPORTED";
+ parameter EFF_LPBK = "PASSED";
+ parameter EI4 = "EI_IV";
+ parameter EM_INTERLOCK_PRESENT = "NOT_SUPPORTED";
+ parameter EN = "DISABLED";
+ parameter EN_ACK_TO_DIV = "ACK_SPEC";
+ parameter EN_ACK_TO_NAK = "DO_NOTHING";
+ parameter EN_ACS_VIOLATION = "DISABLED";
+ parameter EN_ASPM_L0S = "ENABLED";
+ parameter EN_ASPM_L1 = "ENABLED";
+ parameter EN_ATOMIC_OP_CAP = "ENABLED";
+ parameter EN_ATOMICOP_EGRESS_BLOCKED = "DISABLED";
+ parameter EN_ATS_CAP = "ENABLED";
+ parameter EN_BDGT_CAP = "DISABLED";
+ parameter EN_CAP = "ENABLED";
+ parameter EN_CAP_B = "ENABLED";
+ parameter EN_CAP_C = "ENABLED";
+ parameter EN_CAP_D = "ENABLED";
+ parameter EN_COMPLETER_ABORT = "DISABLED";
+ parameter EN_COMPLETION_TIMEOUT = "ENABLED";
+ parameter EN_CORR_INTERNAL_ERROR = "DISABLED";
+ parameter EN_DPA_CAP = "DISABLED";
+ parameter EN_DRCT_SCR_OFF = "OTHERWISE";
+ parameter EN_DRCT_TO_LPBK = "OTHERWISE";
+ parameter EN_EQTX_OVERRIDE = "PIPE_LOCAL_FS_AND_PIPE_LOCAL_LF";
+ parameter EN_FORCE_SCR_OFF_FAST = "OTHERWISE";
+ parameter EN_L1 = "ENABLED";
+ parameter EN_L1PMSS_CAP = "ENABLED";
+ parameter EN_L2 = "ENABLED";
+ parameter EN_LPBK_ERR_RST = "MASTER_LPBK_INCREMENT";
+ parameter EN_LTR_CAP = "ENABLED";
+ parameter EN_MC_BLOCKED_TLP = "DISABLED";
+ parameter EN_NWL_VSEC_CAP = "ENABLED";
+ parameter EN_PORT_DIS = "DISABLED";
+ parameter EN_PORT_INTLEG = "ENABLED";
+ parameter EN_RBAR_CAP_A = "ENABLED";
+ parameter EN_RBAR_CAP_B = "ENABLED";
+ parameter EN_RBAR_CAP_C = "ENABLED";
+ parameter EN_RBAR_CAP_D = "ENABLED";
+ parameter EN_RECEIVER_OVERFLOW = "DISABLED";
+ parameter EN_SELF_XLINK = "OTHERWISE";
+ parameter EN_SURPRISE_DOWN_ERROR = "DISABLED";
+ parameter EN_TLP_PREFIX_BLOCKED = "DISABLED";
+ parameter EN_UCORR_INTERNAL_ERROR = "DISABLED";
+ parameter EN_USER_WRITE = "READ_WRITE_ACCESS";
+ parameter END_END_PREFIXES_SUPPORTED = "NOT_SUPPORTED";
+ parameter END_ON_HOLD = "YES_EXIT_ON_HOLD";
+ parameter ENDCALIB_MAX = "0b10000100";
+ parameter ENDPOINT_L0S_ACCEPTABLE_LATENCY = "MAX_64_NS";
+ parameter ENDPOINT_L1_ACCEPTABLE_LATENCY = "MAX_1_US";
+ parameter ENTRY_TIME_ASPM_L0S = "0b0000000000000000";
+ parameter ENTRY_TIME_ASPM_L1 = "0b0000000000000000";
+ parameter EOM_TIME = "0b0000000000000000";
+ parameter EOM0DIR = "SELECT_DIR_1";
+ parameter EOM1DIR = "SELECT_DIR_0";
+ parameter EOMCTRL0_LOW = "DISABLED";
+ parameter EOMDIVDIS = "DISABLED";
+ parameter EOMMODE = "0b00";
+ parameter EOMRDSEL = "DISABLED";
+ parameter EOMSTART = "DISABLED";
+ parameter EOMX = "0b000000";
+ parameter EOMX_UPDATE_CNT_VALUE = "0b0011111";
+ parameter EOMY = "0b00000000";
+ parameter ERRCNT_DEC = "0b00100000";
+ parameter ERRCNT_THR = "0b1000";
+ parameter ES_PWDN = "DISABLED";
+ parameter EVAL_RST = "DISABLED";
+ parameter EXCLUDE_L0 = "INCLUDE";
+ parameter EXCLUDE_CFG_COMPLETE = "INCLUDE";
+ parameter EXCLUDE_CFG_IDLE = "INCLUDE";
+ parameter EXCLUDE_LOOPBACK_MASTER = "INCLUDE";
+ parameter EXCLUDE_REC_IDLE = "INCLUDE";
+ parameter EXCLUDE_REC_RCVR_CFG = "INCLUDE";
+ parameter EXIT_DIRECT_TO_DETECT = "DO_NOT_EXIT_TO_DETECT";
+ parameter EXT_CONTROL = "DISABLED";
+ parameter EXTENDED_TAG_FIELD_EN_DEFAULT = "EIGHT_BIT";
+ parameter EXTENDED_TAG_FIELD_SUPPORTED = "EIGHT_BIT";
+ parameter F_ARXCTLEDIR = "IGNORED";
+ parameter F_ARXCTLENULL = "0b0000";
+ parameter F_ARXDMDIR = "DISABLED";
+ parameter F_ARXDMNULL = "0b00000";
+ parameter F_ARXEOMDIR = "IGNORED";
+ parameter F_ARXEOMNULL = "0b00000";
+ parameter F_ARXESDIR = "IGNORED";
+ parameter F_ARXESNULL = "0b00000";
+ parameter F_ARXTDIR = "IGNORED";
+ parameter F_ARXTNULL = "0b00000";
+ parameter F_ASCHCAL = "IGNORED";
+ parameter F_ASCHDIR = "IGNORED";
+ parameter F_ASCHNULL = "0b0000";
+ parameter FAIL_LIMIT_ERR = "RXEQ_NOT_FAIL";
+ parameter FAST = "L0";
+ parameter FC_UPDATE_TIMER_DISABLE = "ENABLED";
+ parameter FC_UPDATE_TIMER_DIV = "PCIE_REC_VALUES";
+ parameter FILTER = "0b1001";
+ parameter FINE_GAIN = "DISABLED";
+ parameter FOM_COMPARE = "0b00000000";
+ parameter FOM_HIRES = "DISABLED";
+ parameter FOM_ITERCNT = "0b101";
+ parameter FOM_THR = "0b0100";
+ parameter FORCE_ATXDRA = "0b000000000000000000000";
+ parameter FORCE_ATXDRP = "0b000000000000000000000";
+ parameter FORCE_ATXDRR = "0b000000000000000000000";
+ parameter FORCE_ATXDRT = "0b000000000000000000000";
+ parameter FORCE_DIR_RSLT = "0b000000";
+ parameter FORCE_FOM_RSLT = "0b00000000";
+ parameter FORCE_IDLE = "DISABLED";
+ parameter FORCE_RX_DETECT = "DISABLED";
+ parameter FORCE_SIGNAL = "DISABLED";
+ parameter FREQ_LOCK = "DISABLED";
+ parameter FS = "0b110000";
+ parameter GAIN_TIMER1 = "0b0101";
+ parameter GEN12_ENA_POST_A0 = "DISABLED";
+ parameter GEN12_ENA_POST_A1A2 = "DISABLED";
+ parameter GEN12_ENA_PREA0 = "DISABLED";
+ parameter GEN3_ENA_POST_A0 = "ENABLED";
+ parameter GEN3_ENA_POST_A1A2 = "ENABLED";
+ parameter GEN3_ENA_PREA0 = "ENABLED";
+ parameter GLOBAL_INVAL_SUPPORT = "ENABLED";
+ parameter HINT = "0b000";
+ parameter HINT0_3DB = "ENABLED";
+ parameter HINT0_A0GAIN = "0b111";
+ parameter HINT0_A2GAIN = "0b111";
+ parameter HINT1_3DB = "ENABLED";
+ parameter HINT1_A0GAIN = "0b011";
+ parameter HINT1_A2GAIN = "0b101";
+ parameter HINT2_3DB = "ENABLED";
+ parameter HINT2_A0GAIN = "0b011";
+ parameter HINT2_A2GAIN = "0b111";
+ parameter HINT3_3DB = "ENABLED";
+ parameter HINT3_A0GAIN = "0b000";
+ parameter HINT3_A2GAIN = "0b111";
+ parameter HINT4_3DB = "DISABLED";
+ parameter HINT4_A0GAIN = "0b111";
+ parameter HINT4_A2GAIN = "0b111";
+ parameter HINT5_3DB = "DISABLED";
+ parameter HINT5_A0GAIN = "0b011";
+ parameter HINT5_A2GAIN = "0b101";
+ parameter HINT6_3DB = "DISABLED";
+ parameter HINT6_A0GAIN = "0b011";
+ parameter HINT6_A2GAIN = "0b111";
+ parameter HINT7_3DB = "DISABLED";
+ parameter HINT7_A0GAIN = "0b000";
+ parameter HINT7_A2GAIN = "0b111";
+ parameter HINT7_OVR = "DISABLED";
+ parameter HLD_RST = "WRITE_1";
+ parameter HOT_PLUG_CAPABLE = "NOT_SUPPORTED";
+ parameter HOT_PLUG_SURPRISE = "NOT_POSSIBLE";
+ parameter ID_DS_PORT = "0b0000000000000000";
+ parameter ID_NWL_VSEC_CAP = "0b0000000000000001";
+ parameter IGNORE_ECRC = "DISABLED";
+ parameter IGNORE_POISON = "ENABLED";
+ parameter INDICATOR = "0b00000000000000000000000000000000";
+ parameter INHIBIT = "PERFORM_RECEIVER_DETECTION";
+ parameter INJECT_DATA_ERROR_0 = "DISABLED";
+ parameter INJECT_DATA_ERROR_1 = "DISABLED";
+ parameter INJECT_DATA_ERROR_2 = "DISABLED";
+ parameter INJECT_DATA_ERROR_3 = "DISABLED";
+ parameter INJECT_DATA_ERROR_EN = "DISABLED";
+ parameter INJECT_ERR_LANE_SELECT_0 = "DISABLED";
+ parameter INJECT_ERR_LANE_SELECT_1 = "DISABLED";
+ parameter INJECT_ERR_LANE_SELECT_2 = "DISABLED";
+ parameter INJECT_ERR_LANE_SELECT_3 = "DISABLED";
+ parameter INJECT_RX_1BIT_DATA_ERR = "DISABLED";
+ parameter INJECT_RX_2BIT_DATA_ERR = "DISABLED";
+ parameter INJECT_RX_SKP_ERR = "DISABLED";
+ parameter INJECT_RX_VALID_ERR = "DISABLED";
+ parameter INT_CLR = "DISABLED";
+ parameter INT_EN = "DISABLED";
+ parameter INTERRUPT_MESSAGE_NUMBER = "0b00000";
+ parameter INVAL_Q_DEPTH = "0b00000";
+ parameter ITERATION_MAX = "0b000000";
+ parameter L1_ENTER_PLL_RESET_TIME = "0b100";
+ parameter L1_EXIT_PLL_LOCK_TIME = "0b01110";
+ parameter L1PM_SUPPORTED = "SUPPORTED";
+ parameter L2_D3HOT_ENABLE = "DISABLED";
+ parameter LANE_SELECT = "0b0000";
+ parameter LF = "0b001000";
+ parameter LF_PHY = "0b001010";
+ parameter LINK_LANE = "ENABLED";
+ parameter LPBK_EN = "DISABLED";
+ parameter LW_START_UPDN_ACK_EN = "DISABLED";
+ parameter LW_START_UPDN_COUNT = "0b000011111010";
+ parameter LW_START_UPDN_EIE_EN = "DISABLED";
+ parameter LW_START_UPDN_EN_DIR_DS = "DO_NOT_ASSERT";
+ parameter LW_START_UPDN_END_DELAY = "0b1001";
+ parameter LW_START_UPDN_RATE_EN_16G = "DISABLED";
+ parameter LW_START_UPDN_RATE_EN_2P5G = "ENABLED";
+ parameter LW_START_UPDN_RATE_EN_5G = "ENABLED";
+ parameter LW_START_UPDN_RATE_EN_8G = "ENABLED";
+ parameter LW_START_UPDN_START_DELAY = "0b1000";
+ parameter LW_START_UPDN_TIMER_EN = "DISABLED";
+ parameter MARGIN_ENABLE = "PCIE_SPEC";
+ parameter MARGIN_VALUE = "0b000";
+ parameter MASK_0 = "SKIP_RCVR_DETECTION";
+ parameter MASK_1 = "SKIP_RCVR_DETECTION";
+ parameter MASK_2 = "SKIP_RCVR_DETECTION";
+ parameter MASK_3 = "SKIP_RCVR_DETECTION";
+ parameter MAX_LINK_WIDTH = "1_LANE";
+ parameter MAX_SPEED = "8G";
+ parameter MAX_VAR = "0b00100";
+ parameter MERGE_LMMI_RDATA = "DISABLED";
+ parameter METHOD_FMERIT_CTRL = "STEP_PCIE_TX_PRESETS";
+ parameter METHOD_TX_CRED_CLEANUP = "HEADER";
+ parameter MGMT_INTLEG = "0b0000";
+ parameter MGMT_LTSSM_DIS = "DISABLED";
+ parameter MID_VALUE_20B = "0b010100";
+ parameter MID_VALUE_GEN3 = "0b001110";
+ parameter MIN_SPEED = "2P5G";
+ parameter MIN_TIME = "0_MS";
+ parameter MIN_TIME_CFG = "4US";
+ parameter MIX_DIR = "DISABLED";
+ parameter MODE_BFF = "RESTART";
+ parameter MRL_SENSOR_PRESENT = "NOT_SUPPORTED";
+ parameter MULT_ENABLE = "RECOMMENDED_VALUES";
+ parameter MULT_MESSAGE_CAPABLE_MSICAP_A = "EIGHT";
+ parameter MULT_MESSAGE_CAPABLE_MSICAP_B = "EIGHT";
+ parameter MULT_MESSAGE_CAPABLE_MSICAP_C = "EIGHT";
+ parameter MULT_MESSAGE_CAPABLE_MSICAP_D = "EIGHT";
+ parameter NFTS = "0b11111111";
+ parameter NO_COMMAND_COMPLETED_SUPPORT = "SW_NOTIF_PROVIDED";
+ parameter NO_FCMP = "DISABLED";
+ parameter NO_REMOTE_CHANGE = "DISABLED";
+ parameter NO_TX_IDLE_DELAY = "DATA_VALID_GAP";
+ parameter NUM_LANES = "1_LANE";
+ parameter NUMBER_DSLINK = "0b00000";
+ parameter NUMHI_A = "0b00000000000000000000000000000000";
+ parameter NUMHI_B = "0b00000000000000000000000000000000";
+ parameter NUMHI_C = "0b00000000000000000000000000000000";
+ parameter NUMHI_D = "0b00000000000000000000000000000000";
+ parameter NUMHOLD = "SINGLE_HOLD_RESPONSE";
+ parameter NUMLO_A = "0b00000000000000000000000000000000";
+ parameter NUMLO_B = "0b00000000000000000000000000000000";
+ parameter NUMLO_C = "0b00000000000000000000000000000000";
+ parameter NUMLO_D = "0b00000000000000000000000000000000";
+ parameter OBFF_SUPPORTED = "NOT_SUPPORTED";
+ parameter OFFSET_MSIX_PBA_A = "0b00000000000000000111000000000";
+ parameter OFFSET_MSIX_PBA_B = "0b00000000000000000111000000000";
+ parameter OFFSET_MSIX_PBA_C = "0b00000000000000000111000000000";
+ parameter OFFSET_MSIX_PBA_D = "0b00000000000000000111000000000";
+ parameter OFFSET_MSIX_TABLE_A = "0b00000000000000000110000000000";
+ parameter OFFSET_MSIX_TABLE_B = "0b00000000000000000110000000000";
+ parameter OFFSET_MSIX_TABLE_C = "0b00000000000000000110000000000";
+ parameter OFFSET_MSIX_TABLE_D = "0b00000000000000000110000000000";
+ parameter OVER_CTLE = "DISABLED";
+ parameter OVER_RX = "DISABLED";
+ parameter OVER_RXDM = "DISABLED";
+ parameter OVER_RXDP = "DISABLED";
+ parameter OVER_RXES = "DISABLED";
+ parameter OVER_RXT = "DISABLED";
+ parameter OVER_SCH = "DISABLED";
+ parameter OVER_TX = "DISABLED";
+ parameter OVERRIDE = "DISABLED";
+ parameter OVR_CDR = "DISABLED";
+ parameter OVR_DIR = "DISABLED";
+ parameter OVR_FOM = "DISABLED";
+ parameter OVR_GAIN3DB = "ENABLED";
+ parameter OVR_HINT3DB = "ENABLED";
+ parameter P_CLK_PERIOD = "0b0000111110100000";
+ parameter PAR_LPBK = "DISABLED";
+ parameter PAS = "10X";
+ parameter PATTERN_0 = "UNSCRAMBLED";
+ parameter PATTERN_1 = "UNSCRAMBLED";
+ parameter PATTERN_2 = "UNSCRAMBLED";
+ parameter PCIPM_L1_1_SUPPORTED = "SUPPORTED";
+ parameter PCIPM_L1_2_SUPPORTED = "SUPPORTED";
+ parameter PERIOD_SRIS_128B130B = "0b000000";
+ parameter PERIOD_SRIS_8B10B = "0b00000000";
+ parameter PERIOD_SRNS_128B130B = "0b00000000";
+ parameter PERIOD_SRNS_8B10B = "0b00000000";
+ parameter PHANTOM_FUNCTIONS_SUPPORTED = "NO_FUNCTION_BITS";
+ parameter PHYSICAL_SLOT_NUMBER = "0b0000000000001";
+ parameter PIN_INTERRUPT_A = "INTA";
+ parameter PIN_INTERRUPT_B = "INTA";
+ parameter PIN_INTERRUPT_C = "INTA";
+ parameter PIN_INTERRUPT_D = "INTA";
+ parameter PIPE_TX_SWING = "FULL_SWING";
+ parameter PLESIO_LPBK = "DISABLED";
+ parameter PM_REDUCE_TIMEOUTS = "DISABLED";
+ parameter PMA_DRIVEN_MODE = "PCS_DRIVEN";
+ parameter PMCSR_B2_B3_SUPPORT = "DISABLED";
+ parameter PMCSR_BUS_P_C_EN = "DISABLED";
+ parameter PME_CLOCK = "DISABLED";
+ parameter PME_SUPPORT = "0b11111";
+ parameter PMFF_ALL = "DISABLED";
+ parameter PORT_CM_RESTORE_TIME = "0b00000000";
+ parameter PORT_NUMBER = "0b00000000";
+ parameter PORT_TPOWER_ON_SCALE = "2_US";
+ parameter PORT_TPOWER_ON_VALUE = "0b00000";
+ parameter POST = "0b000000";
+ parameter POST_A0COEF = "0b001";
+ parameter POST_A1COEF = "0b001";
+ parameter POST_A2COEF = "0b001";
+ parameter POST_CURSOR_LIMIT = "0b100000";
+ parameter POST_CURSOR_STEP_SIZE = "0b001000";
+ parameter POST_ITERCNT = "0b100";
+ parameter POST_STEP = "STEP_SIZE_4";
+ parameter POWER_CONTROLLER_PRESENT = "NOT_SUPPORTED";
+ parameter POWER_INDICATOR_PRESENT = "NOT_SUPPORTED";
+ parameter POWER_REQUIRED = "AUX_POWER_NOT_REQUIRED";
+ parameter PRBS_CHK = "DISABLED";
+ parameter PRBS_GEN = "DISABLED";
+ parameter PRBS_TYP = "PRBS7";
+ parameter PRE = "0b000000";
+ parameter PRE_A0COEF = "0b101";
+ parameter PRE_A1COEF = "0b101";
+ parameter PRE_A2COEF = "0b101";
+ parameter PRE_CURSOR_LIMIT = "0b010000";
+ parameter PRE_CURSOR_STEP_SIZE = "0b000100";
+ parameter PRE_FOM = "ENABLED";
+ parameter PRE_FOM_AVG = "0b100";
+ parameter PRE_ITERCNT = "0b100";
+ parameter PRE_RXEQ_TIMER = "0b00010100";
+ parameter PRE_STEP = "STEP_SIZE_2";
+ parameter PRESET_COUNT_INI = "0b0000";
+ parameter PRESET_EN_LPBK_MASTER = "OTHERWISE";
+ parameter PRESET_EN_LPBK_SLAVE = "OTHERWISE";
+ parameter PRESET_ENABLE = "NORMAL_OP";
+ parameter PRESET_EQTX_FORCE = "0b0000";
+ parameter PRESET_LPBK_MASTER = "0b0000";
+ parameter PRESET_LPBK_SLAVE_0 = "OTHERWISE";
+ parameter PRESET_LPBK_SLAVE_1 = "OTHERWISE";
+ parameter PRESET_LPBK_SLAVE_2 = "OTHERWISE";
+ parameter PRESET_LPBK_SLAVE_3 = "OTHERWISE";
+ parameter PRESET_REJECT = "0b00000000000";
+ parameter PRESET0_POSTCURSOR = "0b1000";
+ parameter PRESET0_PRECURSOR = "0b0000";
+ parameter PRESET1_POSTCURSOR = "0b0101";
+ parameter PRESET1_PRECURSOR = "0b0000";
+ parameter PRESET10_POSTCURSOR = "0b1010";
+ parameter PRESET10_PRECURSOR = "0b0000";
+ parameter PRESET2_POSTCURSOR = "0b0110";
+ parameter PRESET2_PRECURSOR = "0b0000";
+ parameter PRESET3_POSTCURSOR = "0b0100";
+ parameter PRESET3_PRECURSOR = "0b0000";
+ parameter PRESET4_POSTCURSOR = "0b0000";
+ parameter PRESET4_PRECURSOR = "0b0000";
+ parameter PRESET5_POSTCURSOR = "0b0000";
+ parameter PRESET5_PRECURSOR = "0b0011";
+ parameter PRESET6_POSTCURSOR = "0b0000";
+ parameter PRESET6_PRECURSOR = "0b0100";
+ parameter PRESET7_POSTCURSOR = "0b0110";
+ parameter PRESET7_PRECURSOR = "0b0011";
+ parameter PRESET8_POSTCURSOR = "0b0100";
+ parameter PRESET8_PRECURSOR = "0b0100";
+ parameter PRESET9_POSTCURSOR = "0b0000";
+ parameter PRESET9_PRECURSOR = "0b0101";
+ parameter PS_REENTRY_TIME = "0b00000000";
+ parameter RATE = "2P5G";
+ parameter RATE_ENABLE = "INITIAL_SPEED_CHANGES";
+ parameter RCB = "DISABLED";
+ parameter REC_SPD_INFER_EQ_PH0123 = "EXCLUDE_TIME_SPENT";
+ parameter REC_SPD_INFER_RCVR_CFG = "EXCLUDE_TIME_SPENT";
+ parameter REC_SPD_INFER_RCVR_LOCK = "EXCLUDE_TIME_SPENT";
+ parameter DIS_FUNC_B = "ENABLED";
+ parameter DIS_FUNC_C = "ENABLED";
+ parameter DIS_FUNC_D = "ENABLED";
+ parameter REDUCE_TIMEOUTS_LTSSMSIM = "DISABLED";
+ parameter REDUCE_TIMEOUTS_SIM = "DISABLED";
+ parameter REDUCE_TS1 = "DISABLED";
+ parameter REENTRY_DISABLE = "ENABLED";
+ parameter REENTRY_TIME = "0b00000000000000";
+ parameter REQ_FEEDBACK = "0b00000000";
+ parameter RESET_EIEOS_INTERVAL_COUNT = "DISABLED";
+ parameter REVISION_ID_ID3A = "0b00000100";
+ parameter REVISION_ID_ID3B = "0b00000100";
+ parameter REVISION_ID_ID3C = "0b00000100";
+ parameter REVISION_ID_ID3D = "0b00000100";
+ parameter RL1 = "0b0011";
+ parameter RL2 = "0b0101";
+ parameter RL3 = "0b0011";
+ parameter ROUTING_SUPPORTED = "DISABLED";
+ parameter RP_COMPLETER_EN = "DISABLED";
+ parameter RSTCDR_ERR = "ENABLED";
+ parameter RSTCDR_FRQ = "ENABLED";
+ parameter RSTCDR_IDL = "DISABLED";
+ parameter RX_BYPASS_DECODE_EN = "ENABLED";
+ parameter RX_BYPASS_MSG_DEC = "NORMAL_OPERATION";
+ parameter RX_CONVERT_UR_TO_CA = "NORMAL_OPERATION";
+ parameter RX_D_ALLOC_C = "0b0000000001100000";
+ parameter RX_D_ALLOC_N = "0b0000000000000110";
+ parameter RX_D_ALLOC_P = "0b0000000001101100";
+ parameter RX_DIV_MODE1 = "0b10";
+ parameter RX_DIV_MODE0 = "DIV_2";
+ parameter RX_DIV_MODE2 = "0b00";
+ parameter RX_DL_ACTIVE_DISABLE = "BLOCK_RECEPTION_TLP";
+ parameter RX_EARLY_FORWARD_DISABLE = "FWD_RX_DATA_LL";
+ parameter RX_ERR_COR = "DISABLED";
+ parameter RX_ERR_UCOR = "DISABLED";
+ parameter RX_FORCE_RO = "DISABLED";
+ parameter RX_H_ALLOC_C = "0b000000100000";
+ parameter RX_H_ALLOC_N = "0b000000001000";
+ parameter RX_H_ALLOC_P = "0b000000010000";
+ parameter RX_HIZ = "IGNORED";
+ parameter RX_IMPED_RATIO = "0b10000000";
+ parameter RX_INHIBIT_ACK_NAK = "PROCESS_RCVD_ACK";
+ parameter RX_INHIBIT_TLP = "PROCESS_RCVD_TLP";
+ parameter RX_LCRC_INJECT_EN = "DO_NOT_INJECT_ERROR";
+ parameter RX_MALF_INJECT_EN = "DO_NOT_INJECT_ERROR";
+ parameter RX_POLINV = "NORMAL";
+ parameter RX_PRIORITY = "DISABLED";
+ parameter RX_PRIORITY_N_STARVE_THRESH = "0b00010000";
+ parameter RX_PRIORITY_P_STARVE_THRESH = "0b00010000";
+ parameter RX_PWRDN = "IGNORED";
+ parameter RX_TLP_VALID = "DISABLED";
+ parameter RXEQ_ALGO = "0b111";
+ parameter RXEQ_ENABLE = "0b100";
+ parameter RXEQ_EVAL_MAX = "0b11111111";
+ parameter RXEQ_MANUAL = "DISABLED";
+ parameter RXEQ_STATE = "0b0000";
+ parameter RXF_A = "0b0100";
+ parameter RXF_B = "0b0100";
+ parameter RXF_C = "0b0100";
+ parameter RXHF_CLKDN = "ENABLED";
+ parameter RXIDLE_MAX = "0b1111";
+ parameter RXIDLE_MAX2 = "0b0000010000000000";
+ parameter RXIDLE_MSB = "0b11";
+ parameter RXM_A = "0b10";
+ parameter RXM_B = "0b01";
+ parameter RXM_C = "0b00";
+ parameter RXN_A = "0b00100";
+ parameter RXN_B = "0b01001";
+ parameter RXN_C = "0b01111";
+ parameter RXOFF_SETTLE_MAX = "0b011";
+ parameter RXOFF_STABLE_MAX = "0b10000";
+ parameter RXPLLINIT = "DISABLED";
+ parameter RXPLLRST = "SET";
+ parameter SELECT_DIR_FOM_N = "FME_METHOD";
+ parameter SELECTABLE_DEEMPHASIS = "6P0DB";
+ parameter SEQ_NUM = "0b000000000000";
+ parameter SIGNAL_DETECT_THRESHOLD = "125_MV";
+ parameter SIZE_CFG0_A = "0b00000";
+ parameter SIZE_CFG0_B = "0b00000";
+ parameter SIZE_CFG0_C = "0b00000";
+ parameter SIZE_CFG0_D = "0b00000";
+ parameter SIZE_CFG1_A = "0b00000";
+ parameter SIZE_CFG1_B = "0b00000";
+ parameter SIZE_CFG1_C = "0b00000";
+ parameter SIZE_CFG1_D = "0b00000";
+ parameter SIZE_CFG2_A = "0b00000";
+ parameter SIZE_CFG2_B = "0b00000";
+ parameter SIZE_CFG2_C = "0b00000";
+ parameter SIZE_CFG2_D = "0b00000";
+ parameter SIZE_CFG3_A = "0b00000";
+ parameter SIZE_CFG3_B = "0b00000";
+ parameter SIZE_CFG3_C = "0b00000";
+ parameter SIZE_CFG3_D = "0b00000";
+ parameter SIZE_CFG4_A = "0b00000";
+ parameter SIZE_CFG4_B = "0b00000";
+ parameter SIZE_CFG4_C = "0b00000";
+ parameter SIZE_CFG4_D = "0b00000";
+ parameter SIZE_CFG5_A = "0b00000";
+ parameter SIZE_CFG5_B = "0b00000";
+ parameter SIZE_CFG5_C = "0b00000";
+ parameter SIZE_CFG5_D = "0b00000";
+ parameter SKIP_FINAL_COEF_CHECK = "DISABLED";
+ parameter SLOT_CLOCK_CONFIGURATION = "REFCLK_BY_SLOT";
+ parameter SLOT_IMPLEMENTED = "UNCONNECTED";
+ parameter SLOT_POWER_LIMIT_SCALE = "0b00";
+ parameter SLOT_POWER_LIMIT_VALUE = "0b00001010";
+ parameter SPEED_LPBK_CTRL = "2P5G";
+ parameter START_PRESET = "PRESET_VALUE";
+ parameter START_REMOTE_ADV = "OTHERWISE";
+ parameter STATE_DATA_N = "USE_RX_DATA_OBSERVATION";
+ parameter STEP_SELECT = "0b00000";
+ parameter STP_OVERRIDE_EN = "DISABLED";
+ parameter STP_OVERRIDE_LEN = "0b00000000000";
+ parameter STP_OVERRIDE_NEW_LEN = "0b00000000000";
+ parameter SUBSTATE_MAX = "0b00000";
+ parameter SUBSYSTEM_ID_ID2A = "0b1110000000000100";
+ parameter SUBSYSTEM_ID_ID2B = "0b1110000000000100";
+ parameter SUBSYSTEM_ID_ID2C = "0b1110000000000100";
+ parameter SUBSYSTEM_ID_ID2D = "0b1110000000000100";
+ parameter SUBSYSTEM_VENDOR_ID_ID2A = "0b0001100110101010";
+ parameter SUBSYSTEM_VENDOR_ID_ID2B = "0b0001100110101010";
+ parameter SUBSYSTEM_VENDOR_ID_ID2C = "0b0001100110101010";
+ parameter SUBSYSTEM_VENDOR_ID_ID2D = "0b0001100110101010";
+ parameter SUPP_SIZE_CFG0_A = "0b00000000000000001111";
+ parameter SUPP_SIZE_CFG0_B = "0b00000000000000001111";
+ parameter SUPP_SIZE_CFG0_C = "0b00000000000000001111";
+ parameter SUPP_SIZE_CFG0_D = "0b00000000000000001111";
+ parameter SUPP_SIZE_CFG1_A = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG1_B = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG1_C = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG1_D = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG2_A = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG2_B = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG2_C = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG2_D = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG3_A = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG3_B = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG3_C = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG3_D = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG4_A = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG4_B = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG4_C = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG4_D = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG5_A = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG5_B = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG5_C = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG5_D = "0b00000000000000000000";
+ parameter SYS_ALLOC = "PWR_BUDGET_CAP_VALUES";
+ parameter T0_RX_BYPASS_MSG_DEC = "NORMAL_OPERATION";
+ parameter TABLE_SIZE_MSIXCAP_A = "0b00000000111";
+ parameter TABLE_SIZE_MSIXCAP_B = "0b00000000111";
+ parameter TABLE_SIZE_MSIXCAP_C = "0b00000000111";
+ parameter TABLE_SIZE_MSIXCAP_D = "0b00000000111";
+ parameter TARGET_LINK_SPEED = "8G";
+ parameter TARGET_ONLY = "DISABLED";
+ parameter TD1_MEANS_ADD_HAS_N = "ECRC_CONTAINED";
+ parameter TIMEOUT_THRESHOLD_PME = "0b000000000000";
+ parameter TIMEOUT_THRESHOLD_PME_TO_ACK_DS = "0b00000000";
+ parameter TIMER = "0b00000000";
+ parameter TLP_LCRC_ERR_ENABLE = "DISABLED";
+ parameter TLP_LCRC_ERR_RATE = "0b000";
+ parameter TLP_SEQ_ERR_ENABLE = "DISABLED";
+ parameter TLUNIT = "1_MS";
+ parameter TO_EXTEND = "0b01111111";
+ parameter TRNG_A0COEF = "0b101";
+ parameter TRNG_A1COEF = "0b101";
+ parameter TRNG_A2COEF = "0b101";
+ parameter TRNG_FAST = "DISABLED";
+ parameter TRNG_ITERCNT = "0b100";
+ parameter TRNG_RXEQ_TIMER = "0b00100000";
+ parameter TS1_ACK_BLOCK_USE_PRESET = "FORCED_TO_ZERO";
+ parameter TS1_ACK_DELAY = "0b00011111";
+ parameter TS1_ACK_MASK_USE_PRESET = "IGNORES_USE_PRESET";
+ parameter TX_AMP_RATIO_MARGIN0_FULL = "0b10000000";
+ parameter TX_AMP_RATIO_MARGIN0_HALF = "0b01010000";
+ parameter TX_AMP_RATIO_MARGIN1_FULL = "0b01111000";
+ parameter TX_AMP_RATIO_MARGIN1_HALF = "0b01011000";
+ parameter TX_AMP_RATIO_MARGIN2_FULL = "0b01101000";
+ parameter TX_AMP_RATIO_MARGIN2_HALF = "0b01001000";
+ parameter TX_AMP_RATIO_MARGIN3_FULL = "0b01100000";
+ parameter TX_AMP_RATIO_MARGIN3_HALF = "0b01000000";
+ parameter TX_AMP_RATIO_MARGIN4_FULL = "0b01011000";
+ parameter TX_AMP_RATIO_MARGIN4_HALF = "0b00111000";
+ parameter TX_AMP_RATIO_MARGIN5_FULL = "0b01010000";
+ parameter TX_AMP_RATIO_MARGIN5_HALF = "0b00110000";
+ parameter TX_AMP_RATIO_MARGIN6_FULL = "0b01001000";
+ parameter TX_AMP_RATIO_MARGIN6_HALF = "0b00101000";
+ parameter TX_AMP_RATIO_MARGIN7_FULL = "0b01000000";
+ parameter TX_AMP_RATIO_MARGIN7_HALF = "0b00100000";
+ parameter TX_BYPASS_DECODE_EN = "ENABLED";
+ parameter TX_BYPASS_MSG_DEC = "NORMAL_OPERATION";
+ parameter TX_COMP_RECEIVE = "DOES_NOT_ASSERT";
+ parameter TX_CONVERT_UR_TO_CA = "NORMAL_OPERATION";
+ parameter TX_D_ALLOC_C = "0b0000000001100000";
+ parameter TX_D_ALLOC_N = "0b0000000000000110";
+ parameter TX_D_ALLOC_P = "0b0000000001101100";
+ parameter TX_DIV_MODE0 = "0b10";
+ parameter TX_DIV_MODE1 = "0b10";
+ parameter TX_DIV_MODE2 = "0b10";
+ parameter TX_EQ_EVAL_CNT_SEL = "WAIT_8_CLKS";
+ parameter TX_ERR_COR = "DISABLED";
+ parameter TX_ERR_UCOR = "DISABLED";
+ parameter TX_FORCE_RO = "DISABLED";
+ parameter TX_GAP_INJECT_EN = "DO_NOT_INJECT_GAP";
+ parameter TX_H_ALLOC_C = "0b000000100000";
+ parameter TX_H_ALLOC_N = "0b000000001000";
+ parameter TX_H_ALLOC_P = "0b000000010000";
+ parameter TX_HIZ = "IGNORED";
+ parameter TX_IMPED_RATIO = "0b10000000";
+ parameter TX_PAR1_INJECT_EN = "DO_NOT_INJECT_ERR";
+ parameter TX_PAR2_HANDLE_DISABLE = "ENABLE_HANDLING";
+ parameter TX_PAR2_INJECT_EN = "DO_NOT_INJECT_ERR";
+ parameter TX_PAR2_REPORT_DISABLE = "ENABLE_REPORTING";
+ parameter TX_POLINV = "NORMAL";
+ parameter TX_PRE_RATIO = "0b00000000";
+ parameter TX_PRE_RATIO_DEEMP0_FULL = "0b00000000";
+ parameter TX_PRE_RATIO_DEEMP0_HALF = "0b00000000";
+ parameter TX_PRE_RATIO_DEEMP1_FULL = "0b00000000";
+ parameter TX_PRE_RATIO_DEEMP1_HALF = "0b00000000";
+ parameter TX_PRIORITY = "DISABLED";
+ parameter TX_PRIORITY_N_STARVE_THRESH = "0b00010000";
+ parameter TX_PRIORITY_P_STARVE_THRESH = "0b00010000";
+ parameter TX_PST_RATIO = "0b00010101";
+ parameter TX_PST_RATIO_DEEMP0_FULL = "0b00100000";
+ parameter TX_PST_RATIO_DEEMP0_HALF = "0b00100000";
+ parameter TX_PST_RATIO_DEEMP1_FULL = "0b00010101";
+ parameter TX_PST_RATIO_DEEMP1_HALF = "0b00010101";
+ parameter TX_QUIESCE = "DISABLED";
+ parameter TX_REPLAY_ECC1_HANDLE_DISABLE = "ENABLE_CORRECTION";
+ parameter TX_REPLAY_ECC1_INJECT_EN = "DO_NOT_INJECT_ERR";
+ parameter TX_REPLAY_ECC1_REPORT_DISABLE = "ENABLE_REPORTING";
+ parameter TX_REPLAY_ECC2_HANDLE_DISABLE = "ENABLE_HANDLING";
+ parameter TX_REPLAY_ECC2_INJECT_EN = "DO_NOT_INJECT_ERR";
+ parameter TX_REPLAY_ECC2_REPORT_DISABLE = "ENABLE_REPORTING";
+ parameter TX_REQ_EQ = "DISABLED";
+ parameter TX_SELECT_RX_FEEDBACK = "REFCLK";
+ parameter TX_TLP_VALID = "DISABLED";
+ parameter TXF_A = "0b0100";
+ parameter TXF_B = "0b0100";
+ parameter TXF_C = "0b0100";
+ parameter TXHF_CLKDN = "ENABLED";
+ parameter TXM_A = "0b10";
+ parameter TXM_B = "0b01";
+ parameter TXM_C = "0b00";
+ parameter TXN_A = "0b00100";
+ parameter TXN_B = "0b01001";
+ parameter TXN_C = "0b01111";
+ parameter TXPLL_INIT = "DISABLED";
+ parameter TXPLLRST = "DISABLED";
+ parameter TYPE1_TYPE0_N = "ENDPOINT";
+ parameter U_CLK_PERIOD = "0b0001111101000000";
+ parameter US_PORT_PS_ENTRY_TIME = "0b0000000000000000";
+ parameter US_PORT_RX_PRESET_HINT = "0b010";
+ parameter US_PORT_TX_PRESET = "0b0100";
+ parameter USE_COEF_PRE_MTHD_CTRL = "PRESET_VALUE";
+ parameter USE_COEF_UPDN_CTRL = "PRESET_VALUE";
+ parameter USER_AUTO_N = "AUTOMATIC_ON_RECEPTION";
+ parameter VEC_MASK_CAPABLE_MSICAP_A = "ENABLED";
+ parameter VEC_MASK_CAPABLE_MSICAP_B = "ENABLED";
+ parameter VEC_MASK_CAPABLE_MSICAP_C = "ENABLED";
+ parameter VEC_MASK_CAPABLE_MSICAP_D = "ENABLED";
+ parameter VENDOR_ID_ID1A = "0b0001100110101010";
+ parameter VENDOR_ID_ID1B = "0b0001100110101010";
+ parameter VENDOR_ID_ID1C = "0b0001100110101010";
+ parameter VENDOR_ID_ID1D = "0b0001100110101010";
+ parameter VENDOR0_UR = "REPORT";
+ parameter VERSION_AER_CAP = "VER_0X2";
+ parameter VERSION_PM_CAP = "0b011";
+ parameter XLCY0 = "0b00000000";
+ parameter XLCY1 = "0b00000000";
+ parameter RX_ESP_RESP_WAIT = "0b01000000";
+ parameter SEL_PCLK_DIV2 = "PCLK_DIV2";
+ parameter COMPLIANCE = "ENABLED";
+ parameter LOOPBACK = "ENABLED";
+ parameter HOT_RESET = "ENABLED";
+ parameter DIS_PREVENT = "ENABLED";
+ parameter MPS_VIOLATION_RX = "DISABLED";
+ parameter MPS_VIOLATION_TX = "DISABLED";
+ parameter EN_RX_ALLOC_SEL = "HW";
+ parameter EN_TX_ALLOC_SEL = "HW";
+ parameter AUX_CLK_PERIOD = "0b1111010000100100";
+ parameter EN_PIPE_IF_CTRL = "DISABLED";
+ parameter PIPE_PWRDN = "P1";
+ parameter TX_CM_DIS = "DEASSERTED";
+ parameter RX_EI_DIS = "DEASSERTED";
+ parameter PCLKREQ_N = "DEASSERTED";
+ parameter STS_PHY_STATUS = "DEASSERTED";
+ parameter STS_PIPE_RSTN = "DEASSERTED";
+ parameter LEGACY_MODE = "MATCH_TS";
+ parameter OVERFLOW = "DISABLED";
+ parameter DIR = "RECEIVE";
+ parameter SPEED = "8G";
+ parameter LANE = "0";
+ parameter COEF_ENABLE_8G = "DISABLED";
+ parameter PRESET_ENABLE_8G = "DISABLED";
+ parameter VALUE_8G_PRE = "0b000000";
+ parameter VALUE_8G_POST = "0b000000";
+ parameter REQ_EQ_MAX_COUNT = "0b10";
+ parameter MESO_LPBK = "DISABLED";
+ parameter TX_REPLAY_ECC2_INJECT_M_1_N = "INJECT_1_ERR";
+ parameter TX_REPLAY_ECC1_INJECT_M_1_N = "INJECT_1_ERR";
+ parameter REDO = "DISABLED";
+ parameter RX_PAR_REPORT_DISABLE = "ENABLE_REPORTING";
+ parameter RX_PAR_INJECT_EN = "DO_NOT_INJECT_ERR";
+ parameter RX_ECC2_REPORT_DISABLE = "ENABLE_REPORTING";
+ parameter RX_ECC2_HANDLE_DISABLE = "ENABLE_HANDLING";
+ parameter RX_ECC2_INJECT_M_1_N = "INJECT_1_ERR";
+ parameter RX_ECC2_INJECT_TYPE = "POSTED_DATA_RAM";
+ parameter RX_ECC2_INJECT_EN = "DO_NOT_INJECT_ERR";
+ parameter RX_ECC1_REPORT_DISABLE = "ENABLE_REPORTING";
+ parameter RX_ECC1_HANDLE_DISABLE = "ENABLE_HANDLING";
+ parameter RX_ECC1_INJECT_M_1_N = "INJECT_1_ERR";
+ parameter RX_ECC1_INJECT_TYPE = "POSTED_DATA_RAM";
+ parameter RX_ECC1_INJECT_EN = "DO_NOT_INJECT_ERR";
+ parameter RX_ERR_PAR = "OTHERWISE";
+ parameter RX_ERR_ECC2 = "OTHERWISE";
+ parameter RX_ERR_ECC1 = "OTHERWISE";
+ parameter TX_PAR_REPORT_DISABLE = "ENABLE_REPORTING";
+ parameter TX_PAR_INJECT_EN = "DO_NOT_INJECT_ERR";
+ parameter TX_ECC2_REPORT_DISABLE = "ENABLE_REPORTING";
+ parameter TX_ECC2_HANDLE_DISABLE = "ENABLE_HANDLING";
+ parameter TX_ECC2_INJECT_M_1_N = "INJECT_1_ERR";
+ parameter TX_ECC2_INJECT_TYPE = "POSTED_DATA_RAM";
+ parameter TX_ECC2_INJECT_EN = "DO_NOT_INJECT_ERR";
+ parameter TX_ECC1_REPORT_DISABLE = "ENABLE_REPORTING";
+ parameter TX_ECC1_HANDLE_DISABLE = "ENABLE_HANDLING";
+ parameter TX_ECC1_INJECT_M_1_N = "INJECT_1_ERR";
+ parameter TX_ECC1_INJECT_TYPE = "POSTED_DATA_RAM";
+ parameter TX_ECC1_INJECT_EN = "DO_NOT_INJECT_ERR";
+ parameter TX_ERR_PAR = "OTHERWISE";
+ parameter TX_ERR_ECC2 = "OTHERWISE";
+ parameter TX_ERR_ECC1 = "OTHERWISE";
+ parameter MAX_PAYLOAD_SIZE_SUPPORTED = "256_BYTES";
+ parameter ARXCAL_OUT = "DISABLED";
+ parameter F_ARXDPDIR = "IGNORED";
+ parameter IDLE_INFER_REC_RCVR_CFG = "OTHERWISE";
+ parameter IDLE_INFER_LPBK_SLAVE = "OTHERWISE";
+ parameter IDLE_INFER_REC_SPEED2_SUCCESS = "OTHERWISE";
+ parameter IDLE_INFER_REC_SPEED2_UNSUCCESS = "OTHERWISE";
+ parameter IDLE_INFER_L0_TO_REC_RCVR_LOCK = "OTHERWISE";
+ parameter SPEED_CHANGE_FAIL = "OTHERWISE";
+ parameter DIRECT_TO_DETECT_FAST = "OTHERWISE";
+ parameter DIRECT_TO_RCVRY_CH_BOND = "OTHERWISE";
+ parameter DIRECT_TO_LPBK_ENTRY = "OTHERWISE";
+ parameter DIRECT_SPEED_CHANGE = "OTHERWISE";
+ parameter L0_TO_REC_RCVR_LOCK_RX_TS12 = "OTHERWISE";
+ parameter L0_TO_REC_RCVR_LOCK_RX_8G_EIE = "OTHERWISE";
+ parameter L0_TO_REC_RCVR_LOCK_RX_INFER = "OTHERWISE";
+ parameter DIRECT_TO_RCVRY_PHY = "OTHERWISE";
+ parameter DIRECT_TO_RCVRY_FRAME = "OTHERWISE";
+ parameter DIRECT_TO_RCVRY_REPLAY = "OTHERWISE";
+ parameter DIRECT_TO_HOT_RESET = "OTHERWISE";
+ parameter DIRECT_TO_DISABLE = "OTHERWISE";
+ parameter RX_L0S_DIRECT_TO_RCVRY = "OTHERWISE";
+ parameter AUTONOMOUS_WIDTH_CHANGE = "OTHERWISE";
+ parameter DIRECTED_RETRAIN_LINK = "OTHERWISE";
+ parameter ERR_TX_PIPE_UNDERFLOW = "OTHERWISE";
+ parameter TS2_DETECT3 = "OTHERWISE";
+ parameter TS2_DETECT2 = "OTHERWISE";
+ parameter TS2_DETECT1 = "OTHERWISE";
+ parameter TS2_DETECT0 = "OTHERWISE";
+ parameter TS1_DETECT3 = "OTHERWISE";
+ parameter TS1_DETECT2 = "OTHERWISE";
+ parameter TS1_DETECT1 = "OTHERWISE";
+ parameter TS1_DETECT0 = "OTHERWISE";
+ parameter TS2I_DETECT3 = "OTHERWISE";
+ parameter TS2I_DETECT2 = "OTHERWISE";
+ parameter TS2I_DETECT1 = "OTHERWISE";
+ parameter TS2I_DETECT0 = "OTHERWISE";
+ parameter TS1I_DETECT3 = "OTHERWISE";
+ parameter TS1I_DETECT2 = "OTHERWISE";
+ parameter TS1I_DETECT1 = "OTHERWISE";
+ parameter TS1I_DETECT0 = "OTHERWISE";
+ parameter FTS_DETECT3 = "OTHERWISE";
+ parameter FTS_DETECT2 = "OTHERWISE";
+ parameter FTS_DETECT1 = "OTHERWISE";
+ parameter FTS_DETECT0 = "OTHERWISE";
+ parameter SKP_DETECT3 = "OTHERWISE";
+ parameter SKP_DETECT2 = "OTHERWISE";
+ parameter SKP_DETECT1 = "OTHERWISE";
+ parameter SKP_DETECT0 = "OTHERWISE";
+ parameter EIE_DETECT3 = "OTHERWISE";
+ parameter EIE_DETECT2 = "OTHERWISE";
+ parameter EIE_DETECT1 = "OTHERWISE";
+ parameter EIE_DETECT0 = "OTHERWISE";
+ parameter EIOS_DETECT3 = "OTHERWISE";
+ parameter EIOS_DETECT2 = "OTHERWISE";
+ parameter EIOS_DETECT1 = "OTHERWISE";
+ parameter EIOS_DETECT0 = "OTHERWISE";
+ parameter DATA_DETECT3 = "OTHERWISE";
+ parameter DATA_DETECT2 = "OTHERWISE";
+ parameter DATA_DETECT1 = "OTHERWISE";
+ parameter DATA_DETECT0 = "OTHERWISE";
+ parameter SDS_DETECT3 = "OTHERWISE";
+ parameter SDS_DETECT2 = "OTHERWISE";
+ parameter SDS_DETECT1 = "OTHERWISE";
+ parameter SDS_DETECT0 = "OTHERWISE";
+ parameter INFO_BAD_TLP_NULL_ERR = "OTHERWISE";
+ parameter INFO_BAD_TLP_PHY_ERR = "OTHERWISE";
+ parameter INFO_BAD_TLP_MALF_ERR = "OTHERWISE";
+ parameter INFO_BAD_TLP_ECRC_ERR = "OTHERWISE";
+ parameter INFO_SCHEDULE_DUPL_ACK = "OTHERWISE";
+ parameter INFO_BAD_TLP_SEQ_ERR = "OTHERWISE";
+ parameter INFO_BAD_TLP_CRC_ERR = "OTHERWISE";
+ parameter INFO_NAK_RECEIVED = "OTHERWISE";
+ parameter INFO_DESKEW_OVERFLOW_ERROR = "OTHERWISE";
+ parameter INFO_TX_DATA_UNDERFLOW = "OTHERWISE";
+ parameter INFO_REPLAY_STARTED = "OTHERWISE";
+ parameter ERR_AER_TX_PAR2 = "OTHERWISE";
+ parameter ERR_AER_TX_REPLAY_ECC2 = "OTHERWISE";
+ parameter ERR_AER_TX_REPLAY_ECC1 = "OTHERWISE";
+ parameter ERR_AER_SURPRISE_DOWN = "OTHERWISE";
+ parameter ERR_AER_DL_PROTOCOL_ERROR = "OTHERWISE";
+ parameter ERR_AER_REPLAY_TIMER_TIMEOUT = "OTHERWISE";
+ parameter ERR_AER_REPLAY_NUM_ROLLOVER = "OTHERWISE";
+ parameter ERR_AER_BAD_DLLP = "OTHERWISE";
+ parameter ERR_AER_BAD_TLP = "OTHERWISE";
+ parameter ERR_AER_RECEIVER_ERROR = "OTHERWISE";
+ parameter P_RX_LIM_H = "DISABLED";
+ parameter P_RX_LIM_D = "DISABLED";
+ parameter N_RX_LIM_H = "DISABLED";
+ parameter N_RX_LIM_D = "DISABLED";
+ parameter C_RX_LIM_H = "DISABLED";
+ parameter C_RX_LIM_D = "DISABLED";
+ parameter P_TX_LIM_H = "DISABLED";
+ parameter P_TX_LIM_D = "DISABLED";
+ parameter N_TX_LIM_H = "DISABLED";
+ parameter N_TX_LIM_D = "DISABLED";
+ parameter C_TX_LIM_H = "DISABLED";
+ parameter C_TX_LIM_D = "DISABLED";
+ parameter MAX_RSA_WAIT = "0b00101000";
+ parameter F_ARXDPNULL = "0b00000";
+ input LMMICLK;
+ input LMMIRESET_N;
+ input LMMIREQUEST;
+ input LMMIWRRD_N;
+ input [14:0] LMMIOFFSET;
+ input [31:0] LMMIWDATA;
+ output [31:0] LMMIRDATA;
+ output LMMIRDATAVALID;
+ output LMMIREADY;
+ output ACJNOUT;
+ output ACJPOUT;
+ input AUXCK;
+ input CKUSRI;
+ output CKUSRO;
+ input ECKIN;
+ input ECKIND2;
+ output ECKINDO;
+ input ERSTN;
+ input ERSTND2;
+ input ERXCKD2;
+ output ERXCKDO;
+ input ERXRSND2;
+ input ETXCKD2;
+ output ETXCKDO;
+ input ETXRSND2;
+ output [3:0] FLR;
+ input [3:0] FLRACK;
+ input [3:0] MINTLEG;
+ output MINTO;
+ input PERSTN;
+ output [4:0] PMCTRL;
+ output PMCTRLEN;
+ input [4:0] PMDPAST;
+ input PRMSGSD;
+ input [12:0] PRNOSNP;
+ input PRNSNPRE;
+ input [12:0] PRSNOOP;
+ input PRSNPRE;
+ input [31:0] PPBDREG;
+ output [7:0] PPBDSEL;
+ input REXTCK;
+ input REXTRST;
+ input RSTUSRN;
+ output UDLLKUP;
+ input ULTSDIS;
+ output UPLLKUP;
+ output UTLLKUP;
+ input [9:0] UCFGADDR;
+ input [2:0] UCFGF;
+ output [31:0] UCFGRDD;
+ output UCFGRDE;
+ output UCFGRDY;
+ input UCFGSERD;
+ input UCFGVD;
+ input [3:0] UCFGWRBE;
+ input [31:0] UCFGWRD;
+ input UCFGWRDN;
+ input USERAUPD;
+ input [3:0] USERTRS;
+ output [12:0] VRXCMDD;
+ input VRXCINIT;
+ input [11:0] VRXCNH;
+ input VRXCNINF;
+ input VRXCRRE;
+ output [31:0] VRXD;
+ output [3:0] VRXDP;
+ output VRXEOP;
+ output VRXERR;
+ output [1:0] VRXF;
+ input VRXRDY;
+ output [1:0] VRXSEL;
+ output VRXSOP;
+ output VRXVD;
+ output VXCDINIT;
+ output [11:0] VXCDNH;
+ output VTXCRRE;
+ input [31:0] VXD;
+ input [3:0] VXDP;
+ input VXEOP;
+ input VXEOPN;
+ output VXRDY;
+ input VXSOP;
+ input VXVD;
+ output [7:0] TESTOUT;
+ (* iopad_external_pin *)
+ input S0REFCKN;
+ (* iopad_external_pin *)
+ input S0REFCKP;
+ (* iopad_external_pin *)
+ input S0REFRET;
+ (* iopad_external_pin *)
+ input S0REXT;
+ (* iopad_external_pin *)
+ input S0RXN;
+ (* iopad_external_pin *)
+ input S0RXP;
+ (* iopad_external_pin *)
+ output S0TXN;
+ (* iopad_external_pin *)
+ output S0TXP;
+ input CLKREQI;
+ output CLKREQO;
+ output CLKREQOE;
+endmodule
+
+module PDP16K_MODE (...);
+ parameter DATA_WIDTH_W = "X36";
+ parameter DATA_WIDTH_R = "X36";
+ parameter OUTREG = "BYPASSED";
+ parameter RESETMODE = "SYNC";
+ parameter GSR = "ENABLED";
+ parameter ECC = "DISABLED";
+ parameter INITVAL_00 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_01 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_02 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_03 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_04 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_05 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_06 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_07 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_08 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_09 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_10 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_11 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_12 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_13 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_14 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_15 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_16 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_17 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_18 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_19 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_20 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_21 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_22 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_23 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_24 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_25 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_26 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_27 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_28 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_29 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_30 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_31 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_32 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_33 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_34 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_35 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_36 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_37 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_38 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_39 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter CSDECODE_W = "000";
+ parameter CSDECODE_R = "000";
+ parameter ASYNC_RST_RELEASE = "SYNC";
+ parameter INIT_DATA = "STATIC";
+ input DI0;
+ input DI1;
+ input DI2;
+ input DI3;
+ input DI4;
+ input DI5;
+ input DI6;
+ input DI7;
+ input DI8;
+ input DI9;
+ input DI10;
+ input DI11;
+ input DI12;
+ input DI13;
+ input DI14;
+ input DI15;
+ input DI16;
+ input DI17;
+ input DI18;
+ input DI19;
+ input DI20;
+ input DI21;
+ input DI22;
+ input DI23;
+ input DI24;
+ input DI25;
+ input DI26;
+ input DI27;
+ input DI28;
+ input DI29;
+ input DI30;
+ input DI31;
+ input DI32;
+ input DI33;
+ input DI34;
+ input DI35;
+ input ADW0;
+ input ADW1;
+ input ADW2;
+ input ADW3;
+ input ADW4;
+ input ADW5;
+ input ADW6;
+ input ADW7;
+ input ADW8;
+ input ADW9;
+ input ADW10;
+ input ADW11;
+ input ADW12;
+ input ADW13;
+ input ADR0;
+ input ADR1;
+ input ADR2;
+ input ADR3;
+ input ADR4;
+ input ADR5;
+ input ADR6;
+ input ADR7;
+ input ADR8;
+ input ADR9;
+ input ADR10;
+ input ADR11;
+ input ADR12;
+ input ADR13;
+ input CLKW;
+ input CLKR;
+ input CEW;
+ input CER;
+ input CSW0;
+ input CSW1;
+ input CSW2;
+ input CSR0;
+ input CSR1;
+ input CSR2;
+ input RST;
+ output DO0;
+ output DO1;
+ output DO2;
+ output DO3;
+ output DO4;
+ output DO5;
+ output DO6;
+ output DO7;
+ output DO8;
+ output DO9;
+ output DO10;
+ output DO11;
+ output DO12;
+ output DO13;
+ output DO14;
+ output DO15;
+ output DO16;
+ output DO17;
+ output DO18;
+ output DO19;
+ output DO20;
+ output DO21;
+ output DO22;
+ output DO23;
+ output DO24;
+ output DO25;
+ output DO26;
+ output DO27;
+ output DO28;
+ output DO29;
+ output DO30;
+ output DO31;
+ output DO32;
+ output DO33;
+ output DO34;
+ output DO35;
+ output ONEBITERR;
+ output TWOBITERR;
+endmodule
+
+module PDP16K (...);
+ parameter DATA_WIDTH_W = "X36";
+ parameter DATA_WIDTH_R = "X36";
+ parameter OUTREG = "BYPASSED";
+ parameter RESETMODE = "SYNC";
+ parameter GSR = "ENABLED";
+ parameter ECC = "DISABLED";
+ parameter INITVAL_00 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_01 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_02 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_03 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_04 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_05 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_06 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_07 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_08 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_09 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_10 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_11 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_12 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_13 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_14 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_15 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_16 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_17 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_18 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_19 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_20 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_21 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_22 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_23 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_24 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_25 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_26 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_27 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_28 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_29 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_30 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_31 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_32 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_33 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_34 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_35 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_36 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_37 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_38 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_39 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter CSDECODE_W = "000";
+ parameter CSDECODE_R = "000";
+ parameter ASYNC_RST_RELEASE = "SYNC";
+ parameter INIT_DATA = "STATIC";
+ input [35:0] DI;
+ input [13:0] ADW;
+ input [13:0] ADR;
+ input CLKW;
+ input CLKR;
+ input CEW;
+ input CER;
+ input [2:0] CSW;
+ input [2:0] CSR;
+ input RST;
+ output [35:0] DO;
+ output ONEBITERR;
+ output TWOBITERR;
+endmodule
+
+module PDPSC16K_MODE (...);
+ parameter DATA_WIDTH_W = "X36";
+ parameter DATA_WIDTH_R = "X36";
+ parameter OUTREG = "BYPASSED";
+ parameter RESETMODE = "SYNC";
+ parameter GSR = "ENABLED";
+ parameter ECC = "DISABLED";
+ parameter INITVAL_00 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_01 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_02 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_03 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_04 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_05 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_06 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_07 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_08 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_09 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_10 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_11 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_12 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_13 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_14 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_15 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_16 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_17 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_18 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_19 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_20 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_21 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_22 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_23 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_24 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_25 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_26 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_27 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_28 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_29 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_30 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_31 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_32 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_33 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_34 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_35 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_36 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_37 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_38 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_39 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter CSDECODE_W = "000";
+ parameter CSDECODE_R = "000";
+ parameter ASYNC_RST_RELEASE = "SYNC";
+ parameter INIT_DATA = "STATIC";
+ input DI0;
+ input DI1;
+ input DI2;
+ input DI3;
+ input DI4;
+ input DI5;
+ input DI6;
+ input DI7;
+ input DI8;
+ input DI9;
+ input DI10;
+ input DI11;
+ input DI12;
+ input DI13;
+ input DI14;
+ input DI15;
+ input DI16;
+ input DI17;
+ input DI18;
+ input DI19;
+ input DI20;
+ input DI21;
+ input DI22;
+ input DI23;
+ input DI24;
+ input DI25;
+ input DI26;
+ input DI27;
+ input DI28;
+ input DI29;
+ input DI30;
+ input DI31;
+ input DI32;
+ input DI33;
+ input DI34;
+ input DI35;
+ input ADW0;
+ input ADW1;
+ input ADW2;
+ input ADW3;
+ input ADW4;
+ input ADW5;
+ input ADW6;
+ input ADW7;
+ input ADW8;
+ input ADW9;
+ input ADW10;
+ input ADW11;
+ input ADW12;
+ input ADW13;
+ input ADR0;
+ input ADR1;
+ input ADR2;
+ input ADR3;
+ input ADR4;
+ input ADR5;
+ input ADR6;
+ input ADR7;
+ input ADR8;
+ input ADR9;
+ input ADR10;
+ input ADR11;
+ input ADR12;
+ input ADR13;
+ input CLK;
+ input CER;
+ input CEW;
+ input CSW0;
+ input CSW1;
+ input CSW2;
+ input CSR0;
+ input CSR1;
+ input CSR2;
+ input RST;
+ output DO0;
+ output DO1;
+ output DO2;
+ output DO3;
+ output DO4;
+ output DO5;
+ output DO6;
+ output DO7;
+ output DO8;
+ output DO9;
+ output DO10;
+ output DO11;
+ output DO12;
+ output DO13;
+ output DO14;
+ output DO15;
+ output DO16;
+ output DO17;
+ output DO18;
+ output DO19;
+ output DO20;
+ output DO21;
+ output DO22;
+ output DO23;
+ output DO24;
+ output DO25;
+ output DO26;
+ output DO27;
+ output DO28;
+ output DO29;
+ output DO30;
+ output DO31;
+ output DO32;
+ output DO33;
+ output DO34;
+ output DO35;
+ output ONEBITERR;
+ output TWOBITERR;
+endmodule
+
+module PDPSC16K (...);
+ parameter DATA_WIDTH_W = "X36";
+ parameter DATA_WIDTH_R = "X36";
+ parameter OUTREG = "BYPASSED";
+ parameter RESETMODE = "SYNC";
+ parameter GSR = "ENABLED";
+ parameter ECC = "DISABLED";
+ parameter INITVAL_00 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_01 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_02 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_03 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_04 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_05 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_06 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_07 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_08 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_09 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_10 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_11 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_12 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_13 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_14 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_15 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_16 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_17 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_18 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_19 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_20 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_21 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_22 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_23 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_24 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_25 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_26 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_27 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_28 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_29 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_30 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_31 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_32 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_33 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_34 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_35 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_36 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_37 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_38 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_39 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter CSDECODE_W = "000";
+ parameter CSDECODE_R = "000";
+ parameter ASYNC_RST_RELEASE = "SYNC";
+ parameter INIT_DATA = "STATIC";
+ input [35:0] DI;
+ input [13:0] ADW;
+ input [13:0] ADR;
+ input CLK;
+ input CER;
+ input CEW;
+ input [2:0] CSW;
+ input [2:0] CSR;
+ input RST;
+ output [35:0] DO;
+ output ONEBITERR;
+ output TWOBITERR;
+endmodule
+
+module PDPSC512K (...);
+ parameter OUTREG = "NO_REG";
+ parameter GSR = "ENABLED";
+ parameter RESETMODE = "SYNC";
+ parameter INITVAL_00 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_01 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_02 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_03 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_04 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_05 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_06 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_07 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_08 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_09 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_10 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_11 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_12 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_13 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_14 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_15 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_16 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_17 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_18 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_19 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_20 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_21 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_22 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_23 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_24 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_25 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_26 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_27 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_28 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_29 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_30 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_31 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_32 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_33 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_34 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_35 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_36 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_37 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_38 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_39 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_40 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_41 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_42 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_43 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_44 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_45 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_46 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_47 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_48 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_49 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_50 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_51 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_52 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_53 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_54 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_55 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_56 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_57 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_58 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_59 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_60 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_61 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_62 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_63 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_64 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_65 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_66 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_67 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_68 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_69 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_70 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_71 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_72 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_73 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_74 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_75 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_76 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_77 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_78 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_79 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter ASYNC_RESET_RELEASE = "SYNC";
+ parameter ECC_BYTE_SEL = "ECC_EN";
+ input [31:0] DI;
+ input [13:0] ADW;
+ input [13:0] ADR;
+ input CLK;
+ input CEW;
+ input CER;
+ input WE;
+ input CSW;
+ input CSR;
+ input RSTR;
+ input [3:0] BYTEEN_N;
+ output [31:0] DO;
+ output [1:0] ERRDECA;
+ output [1:0] ERRDECB;
+endmodule
+
+module PLL (...);
+ parameter BW_CTL_BIAS = "0b0101";
+ parameter CLKOP_TRIM = "0b0000";
+ parameter CLKOS_TRIM = "0b0000";
+ parameter CLKOS2_TRIM = "0b0000";
+ parameter CLKOS3_TRIM = "0b0000";
+ parameter CLKOS4_TRIM = "0b0000";
+ parameter CLKOS5_TRIM = "0b0000";
+ parameter CRIPPLE = "5P";
+ parameter CSET = "40P";
+ parameter DELAY_CTRL = "200PS";
+ parameter DELA = "0";
+ parameter DELB = "0";
+ parameter DELC = "0";
+ parameter DELD = "0";
+ parameter DELE = "0";
+ parameter DELF = "0";
+ parameter DIRECTION = "DISABLED";
+ parameter DIVA = "0";
+ parameter DIVB = "0";
+ parameter DIVC = "0";
+ parameter DIVD = "0";
+ parameter DIVE = "0";
+ parameter DIVF = "0";
+ parameter DYN_SEL = "0b000";
+ parameter DYN_SOURCE = "STATIC";
+ parameter ENCLK_CLKOP = "DISABLED";
+ parameter ENCLK_CLKOS = "DISABLED";
+ parameter ENCLK_CLKOS2 = "DISABLED";
+ parameter ENCLK_CLKOS3 = "DISABLED";
+ parameter ENCLK_CLKOS4 = "DISABLED";
+ parameter ENCLK_CLKOS5 = "DISABLED";
+ parameter ENABLE_SYNC = "DISABLED";
+ parameter FAST_LOCK_EN = "ENABLED";
+ parameter V2I_1V_EN = "DISABLED";
+ parameter FBK_CUR_BLE = "0b00000000";
+ parameter FBK_EDGE_SEL = "POSITIVE";
+ parameter FBK_IF_TIMING_CTL = "0b00";
+ parameter FBK_INTEGER_MODE = "DISABLED";
+ parameter FBK_MASK = "0b00001000";
+ parameter FBK_MMD_DIG = "8";
+ parameter FBK_MMD_PULS_CTL = "0b0000";
+ parameter FBK_MODE = "0b00";
+ parameter FBK_PI_BYPASS = "NOT_BYPASSED";
+ parameter FBK_PI_RC = "0b1100";
+ parameter FBK_PR_CC = "0b0000";
+ parameter FBK_PR_IC = "0b1000";
+ parameter FLOAT_CP = "DISABLED";
+ parameter FLOCK_CTRL = "2X";
+ parameter FLOCK_EN = "ENABLED";
+ parameter FLOCK_SRC_SEL = "REFCLK";
+ parameter FORCE_FILTER = "DISABLED";
+ parameter I_CTRL = "10UA";
+ parameter IPI_CMP = "0b1000";
+ parameter IPI_CMPN = "0b0011";
+ parameter IPI_COMP_EN = "DISABLED";
+ parameter IPP_CTRL = "0b1000";
+ parameter IPP_SEL = "0b1111";
+ parameter KP_VCO = "0b11001";
+ parameter LDT_INT_LOCK_STICKY = "DISABLED";
+ parameter LDT_LOCK = "1536CYC";
+ parameter LDT_LOCK_SEL = "U_FREQ";
+ parameter LEGACY_ATT = "DISABLED";
+ parameter LOAD_REG = "DISABLED";
+ parameter OPENLOOP_EN = "DISABLED";
+ parameter PHIA = "0";
+ parameter PHIB = "0";
+ parameter PHIC = "0";
+ parameter PHID = "0";
+ parameter PHIE = "0";
+ parameter PHIF = "0";
+ parameter PLLPDN_EN = "DISABLED";
+ parameter PLLPD_N = "UNUSED";
+ parameter PLLRESET_ENA = "DISABLED";
+ parameter REF_INTEGER_MODE = "DISABLED";
+ parameter REF_MASK = "0b00000000";
+ parameter REF_MMD_DIG = "8";
+ parameter REF_MMD_IN = "0b00001000";
+ parameter REF_MMD_PULS_CTL = "0b0000";
+ parameter REF_TIMING_CTL = "0b00";
+ parameter REFIN_RESET = "SET";
+ parameter RESET_LF = "DISABLED";
+ parameter ROTATE = "DISABLED";
+ parameter SEL_OUTA = "DISABLED";
+ parameter SEL_OUTB = "DISABLED";
+ parameter SEL_OUTC = "DISABLED";
+ parameter SEL_OUTD = "DISABLED";
+ parameter SEL_OUTE = "DISABLED";
+ parameter SEL_OUTF = "DISABLED";
+ parameter SLEEP = "DISABLED";
+ parameter SSC_DITHER = "DISABLED";
+ parameter SSC_EN_CENTER_IN = "DOWN_TRIANGLE";
+ parameter SSC_EN_SDM = "DISABLED";
+ parameter SSC_EN_SSC = "DISABLED";
+ parameter SSC_F_CODE = "0b000000000000000";
+ parameter SSC_N_CODE = "0b000010100";
+ parameter SSC_ORDER = "SDM_ORDER2";
+ parameter SSC_PI_BYPASS = "NOT_BYPASSED";
+ parameter SSC_REG_WEIGHTING_SEL = "0b000";
+ parameter SSC_SQUARE_MODE = "DISABLED";
+ parameter SSC_STEP_IN = "0b0000000";
+ parameter SSC_TBASE = "0b000000000000";
+ parameter STDBY_ATT = "DISABLED";
+ parameter TRIMOP_BYPASS_N = "BYPASSED";
+ parameter TRIMOS_BYPASS_N = "BYPASSED";
+ parameter TRIMOS2_BYPASS_N = "BYPASSED";
+ parameter TRIMOS3_BYPASS_N = "BYPASSED";
+ parameter TRIMOS4_BYPASS_N = "BYPASSED";
+ parameter TRIMOS5_BYPASS_N = "BYPASSED";
+ parameter V2I_KVCO_SEL = "85";
+ parameter V2I_PP_ICTRL = "0b00110";
+ parameter V2I_PP_RES = "10K";
+ parameter CLKMUX_FB = "CMUX_CLKOP";
+ parameter SEL_FBK = "DIVA";
+ parameter DIV_DEL = "0b0000001";
+ parameter PHASE_SEL_DEL = "0b000";
+ parameter PHASE_SEL_DEL_P1 = "0b000";
+ parameter EXTERNAL_DIVIDE_FACTOR = "0";
+ output INTFBKOP;
+ output INTFBKOS;
+ output INTFBKOS2;
+ output INTFBKOS3;
+ output INTFBKOS4;
+ output INTFBKOS5;
+ input DIR;
+ input [2:0] DIRSEL;
+ input LOADREG;
+ input DYNROTATE;
+ input LMMICLK;
+ input LMMIRESET_N;
+ input LMMIREQUEST;
+ input LMMIWRRD_N;
+ input [6:0] LMMIOFFSET;
+ input [7:0] LMMIWDATA;
+ output [7:0] LMMIRDATA;
+ output LMMIRDATAVALID;
+ output LMMIREADY;
+ input PLLPOWERDOWN_N;
+ input REFCK;
+ output CLKOP;
+ output CLKOS;
+ output CLKOS2;
+ output CLKOS3;
+ output CLKOS4;
+ output CLKOS5;
+ input ENCLKOP;
+ input ENCLKOS;
+ input ENCLKOS2;
+ input ENCLKOS3;
+ input ENCLKOS4;
+ input ENCLKOS5;
+ input FBKCK;
+ output INTLOCK;
+ input LEGACY;
+ output LEGRDYN;
+ output LOCK;
+ output PFDDN;
+ output PFDUP;
+ input PLLRESET;
+ input STDBY;
+ output REFMUXCK;
+ output REGQA;
+ output REGQB;
+ output REGQB1;
+ output CLKOUTDL;
+ input ROTDEL;
+ input DIRDEL;
+ input ROTDELP1;
+ input [4:0] GRAYTEST;
+ input [1:0] BINTEST;
+ input DIRDELP1;
+ input [4:0] GRAYACT;
+ input [1:0] BINACT;
+endmodule
+
+module PREADD9 (...);
+ parameter SIGNEDSTATIC_EN = "DISABLED";
+ parameter SUBSTRACT_EN = "SUBTRACTION";
+ parameter CSIGNED = "DISABLED";
+ parameter BSIGNED_OPERAND_EN = "DISABLED";
+ parameter BYPASS_PREADD9 = "USED";
+ parameter REGBYPSBR0 = "REGISTER";
+ parameter REGBYPSBR1 = "BYPASS";
+ parameter REGBYPSBL = "REGISTER";
+ parameter SHIFTBR = "REGISTER";
+ parameter SHIFTBL = "REGISTER";
+ parameter GSR = "ENABLED";
+ parameter PREADDCAS_EN = "DISABLED";
+ parameter SR_18BITSHIFT_EN = "DISABLED";
+ parameter OPC = "INPUT_B_AS_PREADDER_OPERAND";
+ parameter RESET = "SYNC";
+ input [8:0] B;
+ input BSIGNED;
+ input [9:0] C;
+ input [8:0] BRS1;
+ input [8:0] BRS2;
+ input [8:0] BLS1;
+ input [8:0] BLS2;
+ input BRSS1;
+ input BRSS2;
+ input BLSS1;
+ input BLSS2;
+ input PRCASIN;
+ input CLK;
+ input RSTB;
+ input CEB;
+ input RSTCL;
+ input CECL;
+ output [8:0] BRSO;
+ output [8:0] BLSO;
+ output BRSOSGND;
+ output BLSOSGND;
+ output PRCASOUT;
+ output [8:0] BR;
+ output BRSIGNED;
+endmodule
+
+module REFMUX (...);
+ parameter REFSEL_ATT = "MC1";
+ parameter SEL1 = "SELECT_REFCLK1";
+ parameter SEL_REF2 = "REFCLK2_0";
+ parameter SEL_REF1 = "REFCLK1_0";
+ output REFCK;
+ output ZRSEL3;
+ input REFSEL;
+ input [7:0] REFCLK1;
+ input [7:0] REFCLK2;
+endmodule
+
+module REG18 (...);
+ parameter REGBYPS = "REGISTER";
+ parameter GSR = "ENABLED";
+ parameter RESET = "SYNC";
+ input [17:0] PM;
+ output [17:0] PP;
+ input CEP;
+ input RSTP;
+ input CLK;
+endmodule
+
+(* keep *)
+module SEDC (...);
+ parameter SEDCEN = "DIS";
+ input SEDENABLE;
+ input SEDCCOF;
+ input SEDCENABLE;
+ input SEDCMODE;
+ input SEDCSTART;
+ output SEDCBUSY;
+ output SEDCERR;
+ output SEDCERRC;
+ output SEDCERRCRC;
+ output SEDCERRM;
+ output [15:0] SEDCFRMERRLOC;
+ input OSCCLKSEDC;
+ input RSTSEDC;
+ output [12:0] SEDCDSRERRLOCCIB;
+endmodule
+
+module SEIO18 (...);
+ parameter PULLMODE = "DOWN";
+ parameter MIPI = "DISABLED";
+ parameter ENADC_IN = "DISABLED";
+ input PADDO;
+ input DOLP;
+ (* iopad_external_pin *)
+ inout IOPAD;
+ output PADDI;
+ output INLP;
+ input PADDT;
+ output INADC;
+endmodule
+
+module SEIO33 (...);
+ parameter PULLMODE = "DOWN";
+ (* iopad_external_pin *)
+ inout IOPAD;
+ output PADDI;
+ input PADDO;
+ input PADDT;
+ input I3CRESEN;
+ input I3CWKPU;
+endmodule
+
+module SGMIICDR (...);
+ parameter GSR = "ENABLED";
+ parameter DCOITUNE4LSB = "0_PERCENT";
+ parameter DCOCTLGI = "0_PERCENT";
+ parameter DCOSTEP = "100_PERCENT";
+ parameter DCOCALDIV = "100_PERCENT";
+ parameter DCOIOSTUNE = "0_PERCENT";
+ parameter DCOFLTDAC = "80MHZ";
+ parameter DCOSTARTVAL = "NOMINAL";
+ parameter DCONUOFLSB = "NEG_60_PERCENT";
+ parameter RPWDNB = "POWER_UP";
+ parameter CDR_CNT4SEL = "BYPASSED";
+ parameter DCOITUNE = "100_PERCENT";
+ parameter BAND_THRESHOLD = "0b000000";
+ parameter AUTO_FACQ_EN = "ENABLED";
+ parameter AUTO_CALIB_EN = "ENABLED";
+ parameter CDR_LOL_SET = "1000_PPM";
+ parameter FC2DCO_FLOOP = "DISABLED";
+ parameter FC2DCO_DLOOP = "DISABLED";
+ parameter CALIB_TIME_SEL = "24_CYC";
+ parameter CALIB_CK_MODE = "BY_2";
+ parameter BAND_CALIB_MODE = "256_FDBK_CLK_CYC";
+ parameter REG_BAND_SEL = "0b00000";
+ parameter REG_BAND_OFFSET = "0b0000";
+ parameter REG_IDAC_SEL = "0b00000000";
+ parameter LB_CTL = "DISABLED";
+ parameter REG_IDAC_EN = "DISABLED";
+ parameter ATDCFG = "0_PS";
+ parameter ATDDLY = "0_PS";
+ parameter BDAVOID_ENB = "ENABLED";
+ parameter BYPASSATD = "NOT_BYPASS";
+ parameter DCOIUPDNX2 = "1X";
+ parameter IDAC_EN = "DISABLED";
+ parameter FB_CLK_DIV = "0b010";
+ parameter EN_RECALIB = "ENABLED";
+ input LMMICLK;
+ input LMMIRESET_N;
+ input LMMIREQUEST;
+ input LMMIWRRD_N;
+ input [3:0] LMMIOFFSET;
+ input [7:0] LMMIWDATA;
+ output [7:0] LMMIRDATA;
+ output LMMIRDATAVALID;
+ output LMMIREADY;
+ input DCALIRST;
+ input DFACQRST;
+ input RRST;
+ input SPCLK;
+ output SRCLK;
+ output [9:0] SRXD;
+ input RSTBFBW;
+ input RSTBRXF;
+ input SGMIIIN;
+ input SREFCLK;
+ output CDRLOL;
+endmodule
+
+module SP16K_MODE (...);
+ parameter DATA_WIDTH = "X18";
+ parameter OUTREG = "BYPASSED";
+ parameter RESETMODE = "SYNC";
+ parameter GSR = "ENABLED";
+ parameter INITVAL_00 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_01 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_02 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_03 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_04 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_05 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_06 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_07 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_08 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_09 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_10 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_11 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_12 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_13 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_14 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_15 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_16 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_17 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_18 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_19 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_20 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_21 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_22 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_23 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_24 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_25 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_26 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_27 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_28 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_29 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_30 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_31 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_32 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_33 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_34 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_35 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_36 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_37 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_38 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_39 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter CSDECODE = "000";
+ parameter ASYNC_RST_RELEASE = "SYNC";
+ parameter INIT_DATA = "STATIC";
+ input DI0;
+ input DI1;
+ input DI2;
+ input DI3;
+ input DI4;
+ input DI5;
+ input DI6;
+ input DI7;
+ input DI8;
+ input DI9;
+ input DI10;
+ input DI11;
+ input DI12;
+ input DI13;
+ input DI14;
+ input DI15;
+ input DI16;
+ input DI17;
+ input AD0;
+ input AD1;
+ input AD2;
+ input AD3;
+ input AD4;
+ input AD5;
+ input AD6;
+ input AD7;
+ input AD8;
+ input AD9;
+ input AD10;
+ input AD11;
+ input AD12;
+ input AD13;
+ input CLK;
+ input CE;
+ input WE;
+ input CS0;
+ input CS1;
+ input CS2;
+ input RST;
+ output DO0;
+ output DO1;
+ output DO2;
+ output DO3;
+ output DO4;
+ output DO5;
+ output DO6;
+ output DO7;
+ output DO8;
+ output DO9;
+ output DO10;
+ output DO11;
+ output DO12;
+ output DO13;
+ output DO14;
+ output DO15;
+ output DO16;
+ output DO17;
+endmodule
+
+module SP16K (...);
+ parameter DATA_WIDTH = "X18";
+ parameter OUTREG = "BYPASSED";
+ parameter RESETMODE = "SYNC";
+ parameter GSR = "ENABLED";
+ parameter INITVAL_00 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_01 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_02 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_03 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_04 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_05 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_06 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_07 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_08 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_09 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_10 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_11 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_12 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_13 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_14 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_15 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_16 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_17 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_18 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_19 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_20 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_21 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_22 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_23 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_24 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_25 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_26 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_27 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_28 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_29 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_30 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_31 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_32 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_33 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_34 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_35 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_36 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_37 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_38 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_39 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter CSDECODE = "000";
+ parameter ASYNC_RST_RELEASE = "SYNC";
+ parameter INIT_DATA = "STATIC";
+ input [17:0] DI;
+ input [13:0] AD;
+ input CLK;
+ input CE;
+ input WE;
+ input [2:0] CS;
+ input RST;
+ output [17:0] DO;
+endmodule
+
+module SP512K (...);
+ parameter OUTREG = "NO_REG";
+ parameter GSR = "ENABLED";
+ parameter RESETMODE = "SYNC";
+ parameter INITVAL_00 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_01 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_02 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_03 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_04 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_05 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_06 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_07 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_08 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_09 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_10 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_11 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_12 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_13 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_14 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_15 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_16 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_17 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_18 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_19 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_20 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_21 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_22 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_23 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_24 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_25 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_26 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_27 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_28 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_29 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_30 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_31 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_32 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_33 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_34 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_35 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_36 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_37 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_38 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_39 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_40 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_41 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_42 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_43 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_44 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_45 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_46 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_47 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_48 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_49 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_50 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_51 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_52 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_53 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_54 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_55 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_56 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_57 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_58 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_59 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_60 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_61 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_62 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_63 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_64 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_65 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_66 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_67 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_68 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_69 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_70 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_71 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_72 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_73 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_74 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_75 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_76 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_77 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_78 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_79 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter ASYNC_RESET_RELEASE = "SYNC";
+ parameter ECC_BYTE_SEL = "ECC_EN";
+ input [31:0] DI;
+ input [13:0] AD;
+ input CLK;
+ input CE;
+ input WE;
+ input CS;
+ input RSTOUT;
+ input CEOUT;
+ input [3:0] BYTEEN_N;
+ output [31:0] DO;
+ output [1:0] ERRDECA;
+ output [1:0] ERRDECB;
+endmodule
+
+module TSHX2DQS (...);
+ parameter GSR = "ENABLED";
+ input T0;
+ input T1;
+ input DQSW;
+ input ECLK;
+ input SCLK;
+ input RST;
+ output Q;
+endmodule
+
+module TSHX2DQ (...);
+ parameter GSR = "ENABLED";
+ input T0;
+ input T1;
+ input DQSW270;
+ input ECLK;
+ input SCLK;
+ input RST;
+ output Q;
+endmodule
+
+module TSHX4DQS (...);
+ parameter GSR = "ENABLED";
+ input T0;
+ input T1;
+ input T2;
+ input T3;
+ input DQSW;
+ input ECLK;
+ input SCLK;
+ input RST;
+ output Q;
+endmodule
+
+module TSHX4DQ (...);
+ parameter GSR = "ENABLED";
+ input T0;
+ input T1;
+ input T2;
+ input T3;
+ input DQSW270;
+ input ECLK;
+ input SCLK;
+ input RST;
+ output Q;
+endmodule
+
+(* keep *)
+module WDT (...);
+ parameter WDTEN = "DIS";
+ parameter WDTMODE = "SINGLE";
+ parameter WDTVALUE = "0b000000000000000000";
+ input WDTRELOAD;
+ input WDT_CLK;
+ input WDT_RST;
+endmodule
+
+module MIPI (...);
+ parameter MIPI_ID = "0";
+ (* iopad_external_pin *)
+ inout BP;
+ (* iopad_external_pin *)
+ inout BN;
+ input AP;
+ input AN;
+ input TP;
+ input TN;
+ input IHS;
+ input HSRXEN;
+ input HSTXEN;
+ output OHS;
+ output OLSP;
+ output OLSN;
+endmodule
+
+(* keep *)
+module CONFIG_IP_CORE (...);
+ parameter DONEPHASE = "DIS";
+ parameter DSRFCTRL = "0b00";
+ parameter ENTSALL = "DIS";
+ parameter MCCFGUSEREN = "DIS";
+ parameter MCCIBINT = "DIS";
+ parameter MCHSEUSEREN = "DIS";
+ parameter MCJTAGDISABLE = "EN";
+ parameter MCPERSISTUI2C = "DIS";
+ parameter MCSPARE = "0b00000";
+ parameter MCUCLKSEL = "DIS";
+ parameter MCUI2CAFWKUP = "DIS";
+ parameter PERSISTI2C = "DIS";
+ parameter PERSISTI3C = "DIS";
+ parameter PERSISTMQUAD = "DIS";
+ parameter PERSISTMSPI = "DIS";
+ parameter PERSISTSHEXA = "DIS";
+ parameter PERSISTSOCTA = "DIS";
+ parameter PERSISTSQUAD = "DIS";
+ parameter PERSISTSSPI = "DIS";
+ parameter PERSISTWKUP = "DIS";
+ parameter PPTQOUT = "0b0000";
+ parameter SCANEN = "DIS";
+ parameter SYNCEXTDONE = "DIS";
+ parameter TRANECI = "DIS";
+ parameter TRANHSE = "DIS";
+ parameter TRANSBI = "DIS";
+ parameter TSALLINV = "NINV";
+ parameter WLSLEW = "DIS";
+ output CFGDONECIB;
+ input CIBTSALL;
+ output FREEZEIOCIB;
+ output LASTADDRCIB15;
+ output LASTADDRCIB14;
+ output LASTADDRCIB13;
+ output LASTADDRCIB12;
+ output LASTADDRCIB11;
+ output LASTADDRCIB10;
+ output LASTADDRCIB9;
+ output LASTADDRCIB8;
+ output LASTADDRCIB7;
+ output LASTADDRCIB6;
+ output LASTADDRCIB5;
+ output LASTADDRCIB4;
+ output LASTADDRCIB3;
+ output LASTADDRCIB2;
+ output LASTADDRCIB1;
+ output LASTADDRCIB0;
+ input MBISTENABLEN;
+ output MBISTRRMATCH;
+ input MBISTTRRAEN;
+endmodule
+
+module TSALLA (...);
+ input TSALL;
+endmodule
+
+module OSCA (...);
+ parameter HF_CLK_DIV = "1";
+ parameter HF_SED_SEC_DIV = "1";
+ parameter HF_OSC_EN = "ENABLED";
+ parameter LF_OUTPUT_EN = "DISABLED";
+ input HFOUTEN;
+ input HFSDSCEN;
+ output HFCLKOUT;
+ output LFCLKOUT;
+ output HFCLKCFG;
+ output HFSDCOUT;
+endmodule
+
+module OSC (...);
+ parameter DTR_EN = "ENABLED";
+ parameter HF_CLK_DIV = "1";
+ parameter HF_SED_SEC_DIV = "1";
+ parameter HF_FABRIC_EN = "DISABLED";
+ parameter HF_OSC_EN = "ENABLED";
+ parameter HFDIV_FABRIC_EN = "ENABLED";
+ parameter LF_FABRIC_EN = "DISABLED";
+ parameter LF_OUTPUT_EN = "DISABLED";
+ parameter DEBUG_N = "DISABLED";
+ parameter MCJTAGGSRNDIS = "EN";
+ parameter MCLMMIGSRNDIS = "EN";
+ parameter MCSEDCGSRNDIS = "EN";
+ parameter MCWDTGSRNDIS = "EN";
+ parameter SMCLK_DIV = "3";
+ output HFCLKOUT;
+ input HFSDSCEN;
+ output LFCLKOUT;
+ output HFSDCOUT;
+ output HSE_CLK;
+ input JTAG_LRST_N;
+ input LMMI_CLK;
+ output LMMI_CLK_O;
+ input LMMI_LRST_N;
+ output LMMI_RST;
+ input SEDC_CLK;
+ input SEDC_LRST_N;
+ output SEDC_RST;
+ output CFG_CLK;
+ output SMCLK_RST;
+ output WDT_CLK;
+ input WDT_LRST_N;
+ output WDT_RST;
+endmodule
+
+module ACC54_CORE (...);
+ parameter SIGN = "DISABLED";
+ parameter M9ADDSUB_CTRL = "ADDITION";
+ parameter ADDSUB_CTRL = "ADD_ADD_CTRL_54_BIT_ADDER";
+ parameter STATICOPCODE_EN = "DISABLED";
+ parameter OUTREGBYPS = "REGISTER";
+ parameter GSR = "ENABLED";
+ parameter PROGCONST = "0b000000000000000000000000000000000000000000000000000000";
+ parameter CONSTSEL = "BYPASS";
+ parameter DSPCASCADE = "DISABLED";
+ parameter ACC108CASCADE = "BYPASSCASCADE";
+ parameter ACCUMODE = "MODE0";
+ parameter ACCUBYPS = "USED";
+ parameter CREGBYPS1 = "REGISTER";
+ parameter CREGBYPS2 = "REGISTER";
+ parameter CREGBYPS3 = "REGISTER";
+ parameter CINREGBYPS1 = "REGISTER";
+ parameter CINREGBYPS2 = "REGISTER";
+ parameter CINREGBYPS3 = "REGISTER";
+ parameter LOADREGBYPS1 = "REGISTER";
+ parameter LOADREGBYPS2 = "REGISTER";
+ parameter LOADREGBYPS3 = "REGISTER";
+ parameter M9ADDSUBREGBYPS1 = "REGISTER";
+ parameter M9ADDSUBREGBYPS2 = "REGISTER";
+ parameter M9ADDSUBREGBYPS3 = "REGISTER";
+ parameter ADDSUBSIGNREGBYPS1 = "REGISTER";
+ parameter ADDSUBSIGNREGBYPS2 = "REGISTER";
+ parameter ADDSUBSIGNREGBYPS3 = "REGISTER";
+ parameter ROUNDHALFUP = "DISABLED";
+ parameter ROUNDRTZI = "ROUND_TO_ZERO";
+ parameter ROUNDBIT = "ROUND_TO_BIT0";
+ parameter CASCOUTREGBYPS = "REGISTER";
+ parameter SFTEN = "DISABLED";
+ parameter RESET = "SYNC";
+ input SFTCTRL3;
+ input SFTCTRL2;
+ input SFTCTRL1;
+ input SFTCTRL0;
+ input DSPIN53;
+ input DSPIN52;
+ input DSPIN51;
+ input DSPIN50;
+ input DSPIN49;
+ input DSPIN48;
+ input DSPIN47;
+ input DSPIN46;
+ input DSPIN45;
+ input DSPIN44;
+ input DSPIN43;
+ input DSPIN42;
+ input DSPIN41;
+ input DSPIN40;
+ input DSPIN39;
+ input DSPIN38;
+ input DSPIN37;
+ input DSPIN36;
+ input DSPIN35;
+ input DSPIN34;
+ input DSPIN33;
+ input DSPIN32;
+ input DSPIN31;
+ input DSPIN30;
+ input DSPIN29;
+ input DSPIN28;
+ input DSPIN27;
+ input DSPIN26;
+ input DSPIN25;
+ input DSPIN24;
+ input DSPIN23;
+ input DSPIN22;
+ input DSPIN21;
+ input DSPIN20;
+ input DSPIN19;
+ input DSPIN18;
+ input DSPIN17;
+ input DSPIN16;
+ input DSPIN15;
+ input DSPIN14;
+ input DSPIN13;
+ input DSPIN12;
+ input DSPIN11;
+ input DSPIN10;
+ input DSPIN9;
+ input DSPIN8;
+ input DSPIN7;
+ input DSPIN6;
+ input DSPIN5;
+ input DSPIN4;
+ input DSPIN3;
+ input DSPIN2;
+ input DSPIN1;
+ input DSPIN0;
+ input PP71;
+ input PP70;
+ input PP69;
+ input PP68;
+ input PP67;
+ input PP66;
+ input PP65;
+ input PP64;
+ input PP63;
+ input PP62;
+ input PP61;
+ input PP60;
+ input PP59;
+ input PP58;
+ input PP57;
+ input PP56;
+ input PP55;
+ input PP54;
+ input PP53;
+ input PP52;
+ input PP51;
+ input PP50;
+ input PP49;
+ input PP48;
+ input PP47;
+ input PP46;
+ input PP45;
+ input PP44;
+ input PP43;
+ input PP42;
+ input PP41;
+ input PP40;
+ input PP39;
+ input PP38;
+ input PP37;
+ input PP36;
+ input PP35;
+ input PP34;
+ input PP33;
+ input PP32;
+ input PP31;
+ input PP30;
+ input PP29;
+ input PP28;
+ input PP27;
+ input PP26;
+ input PP25;
+ input PP24;
+ input PP23;
+ input PP22;
+ input PP21;
+ input PP20;
+ input PP19;
+ input PP18;
+ input PP17;
+ input PP16;
+ input PP15;
+ input PP14;
+ input PP13;
+ input PP12;
+ input PP11;
+ input PP10;
+ input PP9;
+ input PP8;
+ input PP7;
+ input PP6;
+ input PP5;
+ input PP4;
+ input PP3;
+ input PP2;
+ input PP1;
+ input PP0;
+ input CINPUT53;
+ input CINPUT52;
+ input CINPUT51;
+ input CINPUT50;
+ input CINPUT49;
+ input CINPUT48;
+ input CINPUT47;
+ input CINPUT46;
+ input CINPUT45;
+ input CINPUT44;
+ input CINPUT43;
+ input CINPUT42;
+ input CINPUT41;
+ input CINPUT40;
+ input CINPUT39;
+ input CINPUT38;
+ input CINPUT37;
+ input CINPUT36;
+ input CINPUT35;
+ input CINPUT34;
+ input CINPUT33;
+ input CINPUT32;
+ input CINPUT31;
+ input CINPUT30;
+ input CINPUT29;
+ input CINPUT28;
+ input CINPUT27;
+ input CINPUT26;
+ input CINPUT25;
+ input CINPUT24;
+ input CINPUT23;
+ input CINPUT22;
+ input CINPUT21;
+ input CINPUT20;
+ input CINPUT19;
+ input CINPUT18;
+ input CINPUT17;
+ input CINPUT16;
+ input CINPUT15;
+ input CINPUT14;
+ input CINPUT13;
+ input CINPUT12;
+ input CINPUT11;
+ input CINPUT10;
+ input CINPUT9;
+ input CINPUT8;
+ input CINPUT7;
+ input CINPUT6;
+ input CINPUT5;
+ input CINPUT4;
+ input CINPUT3;
+ input CINPUT2;
+ input CINPUT1;
+ input CINPUT0;
+ input LOAD;
+ input M9ADDSUB1;
+ input M9ADDSUB0;
+ input ADDSUB1;
+ input ADDSUB0;
+ input CIN;
+ input CASIN1;
+ input CASIN0;
+ input CEO;
+ input RSTO;
+ input CEC;
+ input RSTC;
+ input CLK;
+ input SIGNEDI;
+ output SUM135;
+ output SUM134;
+ output SUM133;
+ output SUM132;
+ output SUM131;
+ output SUM130;
+ output SUM129;
+ output SUM128;
+ output SUM127;
+ output SUM126;
+ output SUM125;
+ output SUM124;
+ output SUM123;
+ output SUM122;
+ output SUM121;
+ output SUM120;
+ output SUM119;
+ output SUM118;
+ output SUM117;
+ output SUM116;
+ output SUM115;
+ output SUM114;
+ output SUM113;
+ output SUM112;
+ output SUM111;
+ output SUM110;
+ output SUM19;
+ output SUM18;
+ output SUM17;
+ output SUM16;
+ output SUM15;
+ output SUM14;
+ output SUM13;
+ output SUM12;
+ output SUM11;
+ output SUM10;
+ output SUM035;
+ output SUM034;
+ output SUM033;
+ output SUM032;
+ output SUM031;
+ output SUM030;
+ output SUM029;
+ output SUM028;
+ output SUM027;
+ output SUM026;
+ output SUM025;
+ output SUM024;
+ output SUM023;
+ output SUM022;
+ output SUM021;
+ output SUM020;
+ output SUM019;
+ output SUM018;
+ output SUM017;
+ output SUM016;
+ output SUM015;
+ output SUM014;
+ output SUM013;
+ output SUM012;
+ output SUM011;
+ output SUM010;
+ output SUM09;
+ output SUM08;
+ output SUM07;
+ output SUM06;
+ output SUM05;
+ output SUM04;
+ output SUM03;
+ output SUM02;
+ output SUM01;
+ output SUM00;
+ output DSPOUT53;
+ output DSPOUT52;
+ output DSPOUT51;
+ output DSPOUT50;
+ output DSPOUT49;
+ output DSPOUT48;
+ output DSPOUT47;
+ output DSPOUT46;
+ output DSPOUT45;
+ output DSPOUT44;
+ output DSPOUT43;
+ output DSPOUT42;
+ output DSPOUT41;
+ output DSPOUT40;
+ output DSPOUT39;
+ output DSPOUT38;
+ output DSPOUT37;
+ output DSPOUT36;
+ output DSPOUT35;
+ output DSPOUT34;
+ output DSPOUT33;
+ output DSPOUT32;
+ output DSPOUT31;
+ output DSPOUT30;
+ output DSPOUT29;
+ output DSPOUT28;
+ output DSPOUT27;
+ output DSPOUT26;
+ output DSPOUT25;
+ output DSPOUT24;
+ output DSPOUT23;
+ output DSPOUT22;
+ output DSPOUT21;
+ output DSPOUT20;
+ output DSPOUT19;
+ output DSPOUT18;
+ output DSPOUT17;
+ output DSPOUT16;
+ output DSPOUT15;
+ output DSPOUT14;
+ output DSPOUT13;
+ output DSPOUT12;
+ output DSPOUT11;
+ output DSPOUT10;
+ output DSPOUT9;
+ output DSPOUT8;
+ output DSPOUT7;
+ output DSPOUT6;
+ output DSPOUT5;
+ output DSPOUT4;
+ output DSPOUT3;
+ output DSPOUT2;
+ output DSPOUT1;
+ output DSPOUT0;
+ output CASCOUT1;
+ output CASCOUT0;
+ input ROUNDEN;
+ input CECIN;
+ input CECTRL;
+ input RSTCIN;
+ input RSTCTRL;
+endmodule
+
+module ADC_CORE (...);
+ parameter ADC_ENP = "ENABLED";
+ parameter CLK_DIV = "2";
+ parameter CTLCOMPSW1 = "DISABLED";
+ parameter CTLCOMPSW2 = "DISABLED";
+ parameter CTLCOMPSW3 = "DISABLED";
+ parameter DF = "STRAIGHT_BINARY";
+ parameter EN_COMP1 = "ENABLED";
+ parameter EN_COMP2 = "ENABLED";
+ parameter EN_COMP3 = "ENABLED";
+ parameter OMA = "BIPOLAR";
+ parameter OMB = "BIPOLAR";
+ parameter REFBUFAEN = "ENABLED";
+ parameter REFBUFBEN = "ENABLED";
+ parameter SLEEP = "DISABLED";
+ parameter VREFACFG = "1P0_TO_1P2";
+ parameter VREFASEL = "INTERNAL";
+ parameter VREFBCFG = "1P0_TO_1P2";
+ parameter VREFBSEL = "INTERNAL";
+ input ADCEN;
+ input CAL;
+ output CALRDY;
+ input CHAEN;
+ input CHASEL3;
+ input CHASEL2;
+ input CHASEL1;
+ input CHASEL0;
+ input CHBEN;
+ input CHBSEL3;
+ input CHBSEL2;
+ input CHBSEL1;
+ input CHBSEL0;
+ input CLKDCLK;
+ input CLKFAB;
+ output COG;
+ input COMP1IN;
+ input COMP1IP;
+ output COMP1OL;
+ input COMP2IN;
+ input COMP2IP;
+ output COMP2OL;
+ input COMP3IN;
+ input COMP3IP;
+ output COMP3OL;
+ input CONVSTOP;
+ output DA11;
+ output DA10;
+ output DA9;
+ output DA8;
+ output DA7;
+ output DA6;
+ output DA5;
+ output DA4;
+ output DA3;
+ output DA2;
+ output DA1;
+ output DA0;
+ output DB11;
+ output DB10;
+ output DB9;
+ output DB8;
+ output DB7;
+ output DB6;
+ output DB5;
+ output DB4;
+ output DB3;
+ output DB2;
+ output DB1;
+ output DB0;
+ (* iopad_external_pin *)
+ input DN1;
+ (* iopad_external_pin *)
+ input DN0;
+ (* iopad_external_pin *)
+ input DP1;
+ (* iopad_external_pin *)
+ input DP0;
+ output EOC;
+ input GPION15;
+ input GPION14;
+ input GPION13;
+ input GPION12;
+ input GPION11;
+ input GPION10;
+ input GPION9;
+ input GPION8;
+ input GPION7;
+ input GPION6;
+ input GPION5;
+ input GPION4;
+ input GPION3;
+ input GPION2;
+ input GPION1;
+ input GPION0;
+ input GPIOP15;
+ input GPIOP14;
+ input GPIOP13;
+ input GPIOP12;
+ input GPIOP11;
+ input GPIOP10;
+ input GPIOP9;
+ input GPIOP8;
+ input GPIOP7;
+ input GPIOP6;
+ input GPIOP5;
+ input GPIOP4;
+ input GPIOP3;
+ input GPIOP2;
+ input GPIOP1;
+ input GPIOP0;
+ input RESETN;
+ input RSTN;
+ input RSVDH;
+ input RSVDL;
+ input SOC;
+ output COMP1O;
+ output COMP2O;
+ output COMP3O;
+endmodule
+
+module ALUREG_CORE (...);
+ parameter ALURST_ACTIVELOW = "DISABLE";
+ parameter GSR = "ENABLED";
+ parameter INREG = "DISABLE";
+ parameter MULFXP_ROUND = "ENABLE";
+ parameter OUTREG = "DISABLE";
+ parameter REGRST_ACTIVELOW = "DISABLE";
+ parameter RETAIN = "ENABLE";
+ parameter RFASYNC_RD = "SYNC_RD";
+ parameter RFR0_RO = "R0READONLY";
+ parameter RFUNALIA_WR = "DISABLE";
+ parameter RFWCLK_INV = "SIG";
+ input OPCGLOADCLK;
+ input ALUCLK;
+ output ALUFLAGC;
+ output ALUFLAGV;
+ output ALUFLAGZ;
+ input ALUFORWARDA;
+ input ALUFORWARDB;
+ input ALUIREGEN;
+ input ALUOREGEN;
+ input ALURST;
+ input DATAA31;
+ input DATAA30;
+ input DATAA29;
+ input DATAA28;
+ input DATAA27;
+ input DATAA26;
+ input DATAA25;
+ input DATAA24;
+ input DATAA23;
+ input DATAA22;
+ input DATAA21;
+ input DATAA20;
+ input DATAA19;
+ input DATAA18;
+ input DATAA17;
+ input DATAA16;
+ input DATAA15;
+ input DATAA14;
+ input DATAA13;
+ input DATAA12;
+ input DATAA11;
+ input DATAA10;
+ input DATAA9;
+ input DATAA8;
+ input DATAA7;
+ input DATAA6;
+ input DATAA5;
+ input DATAA4;
+ input DATAA3;
+ input DATAA2;
+ input DATAA1;
+ input DATAA0;
+ input DATAB31;
+ input DATAB30;
+ input DATAB29;
+ input DATAB28;
+ input DATAB27;
+ input DATAB26;
+ input DATAB25;
+ input DATAB24;
+ input DATAB23;
+ input DATAB22;
+ input DATAB21;
+ input DATAB20;
+ input DATAB19;
+ input DATAB18;
+ input DATAB17;
+ input DATAB16;
+ input DATAB15;
+ input DATAB14;
+ input DATAB13;
+ input DATAB12;
+ input DATAB11;
+ input DATAB10;
+ input DATAB9;
+ input DATAB8;
+ input DATAB7;
+ input DATAB6;
+ input DATAB5;
+ input DATAB4;
+ input DATAB3;
+ input DATAB2;
+ input DATAB1;
+ input DATAB0;
+ input DATAC4;
+ input DATAC3;
+ input DATAC2;
+ input DATAC1;
+ input DATAC0;
+ input OPC6;
+ input OPC5;
+ input OPC4;
+ input OPC3;
+ input OPC2;
+ input OPC1;
+ input OPC0;
+ input OPCCUSTOM;
+ input RADDRA4;
+ input RADDRA3;
+ input RADDRA2;
+ input RADDRA1;
+ input RADDRA0;
+ input RADDRB4;
+ input RADDRB3;
+ input RADDRB2;
+ input RADDRB1;
+ input RADDRB0;
+ output RDATAA31;
+ output RDATAA30;
+ output RDATAA29;
+ output RDATAA28;
+ output RDATAA27;
+ output RDATAA26;
+ output RDATAA25;
+ output RDATAA24;
+ output RDATAA23;
+ output RDATAA22;
+ output RDATAA21;
+ output RDATAA20;
+ output RDATAA19;
+ output RDATAA18;
+ output RDATAA17;
+ output RDATAA16;
+ output RDATAA15;
+ output RDATAA14;
+ output RDATAA13;
+ output RDATAA12;
+ output RDATAA11;
+ output RDATAA10;
+ output RDATAA9;
+ output RDATAA8;
+ output RDATAA7;
+ output RDATAA6;
+ output RDATAA5;
+ output RDATAA4;
+ output RDATAA3;
+ output RDATAA2;
+ output RDATAA1;
+ output RDATAA0;
+ output RDATAB31;
+ output RDATAB30;
+ output RDATAB29;
+ output RDATAB28;
+ output RDATAB27;
+ output RDATAB26;
+ output RDATAB25;
+ output RDATAB24;
+ output RDATAB23;
+ output RDATAB22;
+ output RDATAB21;
+ output RDATAB20;
+ output RDATAB19;
+ output RDATAB18;
+ output RDATAB17;
+ output RDATAB16;
+ output RDATAB15;
+ output RDATAB14;
+ output RDATAB13;
+ output RDATAB12;
+ output RDATAB11;
+ output RDATAB10;
+ output RDATAB9;
+ output RDATAB8;
+ output RDATAB7;
+ output RDATAB6;
+ output RDATAB5;
+ output RDATAB4;
+ output RDATAB3;
+ output RDATAB2;
+ output RDATAB1;
+ output RDATAB0;
+ input REGCLK;
+ input REGCLKEN;
+ input REGRST;
+ output RESULT31;
+ output RESULT30;
+ output RESULT29;
+ output RESULT28;
+ output RESULT27;
+ output RESULT26;
+ output RESULT25;
+ output RESULT24;
+ output RESULT23;
+ output RESULT22;
+ output RESULT21;
+ output RESULT20;
+ output RESULT19;
+ output RESULT18;
+ output RESULT17;
+ output RESULT16;
+ output RESULT15;
+ output RESULT14;
+ output RESULT13;
+ output RESULT12;
+ output RESULT11;
+ output RESULT10;
+ output RESULT9;
+ output RESULT8;
+ output RESULT7;
+ output RESULT6;
+ output RESULT5;
+ output RESULT4;
+ output RESULT3;
+ output RESULT2;
+ output RESULT1;
+ output RESULT0;
+ input SCANCLK;
+ input SCANRST;
+ input WADDR4;
+ input WADDR3;
+ input WADDR2;
+ input WADDR1;
+ input WADDR0;
+ input WDROTATE1;
+ input WDROTATE0;
+ input WDSIGNEXT;
+ input WDSIZE1;
+ input WDSIZE0;
+ input WDATA31;
+ input WDATA30;
+ input WDATA29;
+ input WDATA28;
+ input WDATA27;
+ input WDATA26;
+ input WDATA25;
+ input WDATA24;
+ input WDATA23;
+ input WDATA22;
+ input WDATA21;
+ input WDATA20;
+ input WDATA19;
+ input WDATA18;
+ input WDATA17;
+ input WDATA16;
+ input WDATA15;
+ input WDATA14;
+ input WDATA13;
+ input WDATA12;
+ input WDATA11;
+ input WDATA10;
+ input WDATA9;
+ input WDATA8;
+ input WDATA7;
+ input WDATA6;
+ input WDATA5;
+ input WDATA4;
+ input WDATA3;
+ input WDATA2;
+ input WDATA1;
+ input WDATA0;
+ input WREN;
+endmodule
+
+module BNKREF18_CORE (...);
+ parameter BANK = "0b0000";
+ parameter STANDBY_DIFFIO = "DISABLED";
+ parameter STANDBY_INR = "DISABLED";
+ input STDBYINR;
+ input STDBYDIF;
+ input PVTSNKI6;
+ input PVTSNKI5;
+ input PVTSNKI4;
+ input PVTSNKI3;
+ input PVTSNKI2;
+ input PVTSNKI1;
+ input PVTSNKI0;
+ input PVTSRCI6;
+ input PVTSRCI5;
+ input PVTSRCI4;
+ input PVTSRCI3;
+ input PVTSRCI2;
+ input PVTSRCI1;
+ input PVTSRCI0;
+ output PVTCODE6;
+ output PVTCODE5;
+ output PVTCODE4;
+ output PVTCODE3;
+ output PVTCODE2;
+ output PVTCODE1;
+ output PVTCODE0;
+ input PVTSEL;
+endmodule
+
+module BNKREF33_CORE (...);
+ parameter BANK = "0b0000";
+ input PVTSEL;
+ input PVTSNKI6;
+ input PVTSNKI5;
+ input PVTSNKI4;
+ input PVTSNKI3;
+ input PVTSNKI2;
+ input PVTSNKI1;
+ input PVTSNKI0;
+ input PVTSRCI6;
+ input PVTSRCI5;
+ input PVTSRCI4;
+ input PVTSRCI3;
+ input PVTSRCI2;
+ input PVTSRCI1;
+ input PVTSRCI0;
+ output PVTCODE6;
+ output PVTCODE5;
+ output PVTCODE4;
+ output PVTCODE3;
+ output PVTCODE2;
+ output PVTCODE1;
+ output PVTCODE0;
+endmodule
+
+module DIFFIO18_CORE (...);
+ parameter MIPI_ID = "0";
+ parameter PULLMODE = "DOWN";
+ parameter ENADC_IN = "DISABLED";
+ parameter MIPI = "DISABLED";
+ input I;
+ input DOLP;
+ (* iopad_external_pin *)
+ inout B;
+ output O;
+ output INLP;
+ input T;
+ output INADC;
+ input HSRXEN;
+ input HSTXEN;
+endmodule
+
+(* keep *)
+module CONFIG_CLKRST_CORE (...);
+ parameter MCJTAGGSRNDIS = "EN";
+ parameter MCLMMIGSRNDIS = "EN";
+ parameter MCSEDCGSRNDIS = "EN";
+ parameter MCWDTGSRNDIS = "EN";
+ parameter SMCLK_DIV = "3";
+ output HSE_CLK;
+ input JTAG_LRST_N;
+ input LMMI_CLK;
+ output LMMI_CLK_O;
+ input LMMI_LRST_N;
+ output LMMI_RST;
+ input OSCCLK;
+ input SEDC_CLK;
+ input SEDC_LRST_N;
+ output SEDC_RST;
+ output CFG_CLK;
+ output SMCLK_RST;
+ output WDT_CLK;
+ input WDT_LRST_N;
+ output WDT_RST;
+endmodule
+
+(* keep *)
+module CONFIG_HSE_CORE (...);
+ parameter MCGLBGSRNDIS = "EN";
+ parameter MCHSEDISABLE = "EN";
+ parameter MCHSEOTPEN = "DIS";
+ input ASFCLKI;
+ output ASFEMPTYO;
+ output ASFFULLO;
+ input ASFRDI;
+ input ASFRESETI;
+ input ASFWRI;
+ input CFG_CLK;
+ input HSE_CLK;
+ input HSELRSTN;
+ input LMMICLK;
+ input LMMIOFFSET17;
+ input LMMIOFFSET16;
+ input LMMIOFFSET15;
+ input LMMIOFFSET14;
+ input LMMIOFFSET13;
+ input LMMIOFFSET12;
+ input LMMIOFFSET11;
+ input LMMIOFFSET10;
+ input LMMIOFFSET9;
+ input LMMIOFFSET8;
+ input LMMIOFFSET7;
+ input LMMIOFFSET6;
+ input LMMIOFFSET5;
+ input LMMIOFFSET4;
+ input LMMIOFFSET3;
+ input LMMIOFFSET2;
+ input LMMIOFFSET1;
+ input LMMIOFFSET0;
+ output LMMIRDATA31;
+ output LMMIRDATA30;
+ output LMMIRDATA29;
+ output LMMIRDATA28;
+ output LMMIRDATA27;
+ output LMMIRDATA26;
+ output LMMIRDATA25;
+ output LMMIRDATA24;
+ output LMMIRDATA23;
+ output LMMIRDATA22;
+ output LMMIRDATA21;
+ output LMMIRDATA20;
+ output LMMIRDATA19;
+ output LMMIRDATA18;
+ output LMMIRDATA17;
+ output LMMIRDATA16;
+ output LMMIRDATA15;
+ output LMMIRDATA14;
+ output LMMIRDATA13;
+ output LMMIRDATA12;
+ output LMMIRDATA11;
+ output LMMIRDATA10;
+ output LMMIRDATA9;
+ output LMMIRDATA8;
+ output LMMIRDATA7;
+ output LMMIRDATA6;
+ output LMMIRDATA5;
+ output LMMIRDATA4;
+ output LMMIRDATA3;
+ output LMMIRDATA2;
+ output LMMIRDATA1;
+ output LMMIRDATA0;
+ output LMMIRDATAVALID;
+ output LMMIREADY;
+ input LMMIREQUEST;
+ input LMMIRESETN;
+ input LMMIWDATA31;
+ input LMMIWDATA30;
+ input LMMIWDATA29;
+ input LMMIWDATA28;
+ input LMMIWDATA27;
+ input LMMIWDATA26;
+ input LMMIWDATA25;
+ input LMMIWDATA24;
+ input LMMIWDATA23;
+ input LMMIWDATA22;
+ input LMMIWDATA21;
+ input LMMIWDATA20;
+ input LMMIWDATA19;
+ input LMMIWDATA18;
+ input LMMIWDATA17;
+ input LMMIWDATA16;
+ input LMMIWDATA15;
+ input LMMIWDATA14;
+ input LMMIWDATA13;
+ input LMMIWDATA12;
+ input LMMIWDATA11;
+ input LMMIWDATA10;
+ input LMMIWDATA9;
+ input LMMIWDATA8;
+ input LMMIWDATA7;
+ input LMMIWDATA6;
+ input LMMIWDATA5;
+ input LMMIWDATA4;
+ input LMMIWDATA3;
+ input LMMIWDATA2;
+ input LMMIWDATA1;
+ input LMMIWDATA0;
+ input LMMIWRRDN;
+ input OTM;
+endmodule
+
+(* keep *)
+module CONFIG_JTAG_CORE (...);
+ parameter MCER1EXIST = "NEXIST";
+ parameter MCER2EXIST = "NEXIST";
+ output JCE1;
+ output JCE2;
+ output JRSTN;
+ output JRTI1;
+ output JRTI2;
+ output JSHIFT;
+ output JTDI;
+ output JUPDATE;
+ input JTDO1;
+ input JTDO2;
+ input SMCLK;
+ input TCK;
+ output JTCK;
+ input TDI;
+ output TDO_OEN;
+ output TDO;
+ input TMS;
+endmodule
+
+(* keep *)
+module CONFIG_LMMI_CORE (...);
+ parameter LMMI_EN = "DIS";
+ input LMMIOFFSET7;
+ input LMMIOFFSET6;
+ input LMMIOFFSET5;
+ input LMMIOFFSET4;
+ input LMMIOFFSET3;
+ input LMMIOFFSET2;
+ input LMMIOFFSET1;
+ input LMMIOFFSET0;
+ input LMMICLK;
+ output LMMIRDATA7;
+ output LMMIRDATA6;
+ output LMMIRDATA5;
+ output LMMIRDATA4;
+ output LMMIRDATA3;
+ output LMMIRDATA2;
+ output LMMIRDATA1;
+ output LMMIRDATA0;
+ output LMMIRDATAVALID;
+ output LMMIREADY;
+ input LMMIRESETN;
+ input LMMIREQUEST;
+ input LMMIWDATA7;
+ input LMMIWDATA6;
+ input LMMIWDATA5;
+ input LMMIWDATA4;
+ input LMMIWDATA3;
+ input LMMIWDATA2;
+ input LMMIWDATA1;
+ input LMMIWDATA0;
+ input LMMIWRRDN;
+ input RSTSMCLK;
+ input SMCLK;
+endmodule
+
+(* keep *)
+module CONFIG_MULTIBOOT_CORE (...);
+ parameter MSPIADDR = "0b00000000000000000000000000000000";
+ parameter SOURCESEL = "DIS";
+ input CIBAUTOREBOOT;
+ input CIBMSPIMADDR31;
+ input CIBMSPIMADDR30;
+ input CIBMSPIMADDR29;
+ input CIBMSPIMADDR28;
+ input CIBMSPIMADDR27;
+ input CIBMSPIMADDR26;
+ input CIBMSPIMADDR25;
+ input CIBMSPIMADDR24;
+ input CIBMSPIMADDR23;
+ input CIBMSPIMADDR22;
+ input CIBMSPIMADDR21;
+ input CIBMSPIMADDR20;
+ input CIBMSPIMADDR19;
+ input CIBMSPIMADDR18;
+ input CIBMSPIMADDR17;
+ input CIBMSPIMADDR16;
+ input CIBMSPIMADDR15;
+ input CIBMSPIMADDR14;
+ input CIBMSPIMADDR13;
+ input CIBMSPIMADDR12;
+ input CIBMSPIMADDR11;
+ input CIBMSPIMADDR10;
+ input CIBMSPIMADDR9;
+ input CIBMSPIMADDR8;
+ input CIBMSPIMADDR7;
+ input CIBMSPIMADDR6;
+ input CIBMSPIMADDR5;
+ input CIBMSPIMADDR4;
+ input CIBMSPIMADDR3;
+ input CIBMSPIMADDR2;
+ input CIBMSPIMADDR1;
+ input CIBMSPIMADDR0;
+endmodule
+
+(* keep *)
+module CONFIG_SEDC_CORE (...);
+ parameter SEDCEN = "DIS";
+ input CIBSED1ENABLE;
+ input CIBSEDCCOF;
+ input CIBSEDCENABLE;
+ input CIBSEDCMODE;
+ input CIBSEDCSTART;
+ input OSCCLKSEDC;
+ input RSTSEDC;
+ output SEDCBUSYCIB;
+ output SEDCDSRERRLOCCIB12;
+ output SEDCDSRERRLOCCIB11;
+ output SEDCDSRERRLOCCIB10;
+ output SEDCDSRERRLOCCIB9;
+ output SEDCDSRERRLOCCIB8;
+ output SEDCDSRERRLOCCIB7;
+ output SEDCDSRERRLOCCIB6;
+ output SEDCDSRERRLOCCIB5;
+ output SEDCDSRERRLOCCIB4;
+ output SEDCDSRERRLOCCIB3;
+ output SEDCDSRERRLOCCIB2;
+ output SEDCDSRERRLOCCIB1;
+ output SEDCDSRERRLOCCIB0;
+ output SEDCERR1CIB;
+ output SEDCERRCCIB;
+ output SEDCERRCRCCIB;
+ output SEDCERRMCIB;
+ output SEDCFRMERRLOCCIB15;
+ output SEDCFRMERRLOCCIB14;
+ output SEDCFRMERRLOCCIB13;
+ output SEDCFRMERRLOCCIB12;
+ output SEDCFRMERRLOCCIB11;
+ output SEDCFRMERRLOCCIB10;
+ output SEDCFRMERRLOCCIB9;
+ output SEDCFRMERRLOCCIB8;
+ output SEDCFRMERRLOCCIB7;
+ output SEDCFRMERRLOCCIB6;
+ output SEDCFRMERRLOCCIB5;
+ output SEDCFRMERRLOCCIB4;
+ output SEDCFRMERRLOCCIB3;
+ output SEDCFRMERRLOCCIB2;
+ output SEDCFRMERRLOCCIB1;
+ output SEDCFRMERRLOCCIB0;
+endmodule
+
+(* keep *)
+module CONFIG_WDT_CORE (...);
+ parameter WDTEN = "DIS";
+ parameter WDTMODE = "SINGLE";
+ parameter WDTVALUE = "0b000000000000000000";
+ input CIBWDTRELOAD;
+ input WDT_CLK;
+ input WDT_RST;
+endmodule
+
+module DDRDLL_CORE (...);
+ parameter GSR = "ENABLED";
+ parameter ENA_ROUNDOFF = "ENABLED";
+ parameter FORCE_MAX_DELAY = "CODE_OR_LOCK_FROM_DLL_LOOP";
+ output CODE8;
+ output CODE7;
+ output CODE6;
+ output CODE5;
+ output CODE4;
+ output CODE3;
+ output CODE2;
+ output CODE1;
+ output CODE0;
+ input FREEZE;
+ output LOCK;
+ input CLKIN;
+ input RST;
+ output DCNTL8;
+ output DCNTL7;
+ output DCNTL6;
+ output DCNTL5;
+ output DCNTL4;
+ output DCNTL3;
+ output DCNTL2;
+ output DCNTL1;
+ output DCNTL0;
+ input UDDCNTL_N;
+endmodule
+
+module DLLDEL_CORE (...);
+ parameter ADJUST = "0";
+ parameter DEL_ADJUST = "PLUS";
+ parameter ENABLE = "DISABLED";
+ input CLKIN;
+ output CLKOUT;
+ input CODE8;
+ input CODE7;
+ input CODE6;
+ input CODE5;
+ input CODE4;
+ input CODE3;
+ input CODE2;
+ input CODE1;
+ input CODE0;
+ output COUT;
+ input DIR;
+ input LOAD_N;
+ input MOVE;
+endmodule
+
+module DPHY_CORE (...);
+ parameter GSR = "ENABLED";
+ parameter AUTO_PD_EN = "POWERED_UP";
+ parameter CFG_NUM_LANES = "ONE_LANE";
+ parameter CM = "0b00000000";
+ parameter CN = "0b00000";
+ parameter CO = "0b000";
+ parameter CONT_CLK_MODE = "DISABLED";
+ parameter DESKEW_EN = "DISABLED";
+ parameter DSI_CSI = "CSI2_APP";
+ parameter EN_CIL = "CIL_ENABLED";
+ parameter HSEL = "DISABLED";
+ parameter LANE0_SEL = "LANE_0";
+ parameter LOCK_BYP = "GATE_TXBYTECLKHS";
+ parameter MASTER_SLAVE = "SLAVE";
+ parameter PLLCLKBYPASS = "REGISTERED";
+ parameter RSEL = "0b00";
+ parameter RXCDRP = "0b00";
+ parameter RXDATAWIDTHHS = "0b00";
+ parameter RXLPRP = "0b000";
+ parameter TEST_ENBL = "0b000000";
+ parameter TEST_PATTERN = "0b00000000000000000000000000000000";
+ parameter TST = "0b1001";
+ parameter TXDATAWIDTHHS = "0b00";
+ parameter U_PRG_HS_PREPARE = "0b00";
+ parameter U_PRG_HS_TRAIL = "0b000000";
+ parameter U_PRG_HS_ZERO = "0b000000";
+ parameter U_PRG_RXHS_SETTLE = "0b000000";
+ parameter UC_PRG_HS_PREPARE = "1P0_TXCLKESC";
+ parameter UC_PRG_HS_TRAIL = "0b00000";
+ parameter UC_PRG_HS_ZERO = "0b0000000";
+ parameter UC_PRG_RXHS_SETTLE = "0b000000";
+ input BITCKEXT;
+ (* iopad_external_pin *)
+ inout CKN;
+ (* iopad_external_pin *)
+ inout CKP;
+ input CLKREF;
+ output D0ACTIVE1;
+ output D0ACTIVE0;
+ output D0BYTCNT9;
+ output D0BYTCNT8;
+ output D0BYTCNT7;
+ output D0BYTCNT6;
+ output D0BYTCNT5;
+ output D0BYTCNT4;
+ output D0BYTCNT3;
+ output D0BYTCNT2;
+ output D0BYTCNT1;
+ output D0BYTCNT0;
+ output D0ERRCNT9;
+ output D0ERRCNT8;
+ output D0ERRCNT7;
+ output D0ERRCNT6;
+ output D0ERRCNT5;
+ output D0ERRCNT4;
+ output D0ERRCNT3;
+ output D0ERRCNT2;
+ output D0ERRCNT1;
+ output D0ERRCNT0;
+ output D0PASS1;
+ output D0PASS0;
+ output D0VALID1;
+ output D0VALID0;
+ output D1ACTIVE1;
+ output D1ACTIVE0;
+ output D1BYTCNT9;
+ output D1BYTCNT8;
+ output D1BYTCNT7;
+ output D1BYTCNT6;
+ output D1BYTCNT5;
+ output D1BYTCNT4;
+ output D1BYTCNT3;
+ output D1BYTCNT2;
+ output D1BYTCNT1;
+ output D1BYTCNT0;
+ output D1ERRCNT9;
+ output D1ERRCNT8;
+ output D1ERRCNT7;
+ output D1ERRCNT6;
+ output D1ERRCNT5;
+ output D1ERRCNT4;
+ output D1ERRCNT3;
+ output D1ERRCNT2;
+ output D1ERRCNT1;
+ output D1ERRCNT0;
+ output D1PASS1;
+ output D1PASS0;
+ output D1VALID1;
+ output D1VALID0;
+ output D2ACTIVE1;
+ output D2ACTIVE0;
+ output D2BYTCNT9;
+ output D2BYTCNT8;
+ output D2BYTCNT7;
+ output D2BYTCNT6;
+ output D2BYTCNT5;
+ output D2BYTCNT4;
+ output D2BYTCNT3;
+ output D2BYTCNT2;
+ output D2BYTCNT1;
+ output D2BYTCNT0;
+ output D2ERRCNT9;
+ output D2ERRCNT8;
+ output D2ERRCNT7;
+ output D2ERRCNT6;
+ output D2ERRCNT5;
+ output D2ERRCNT4;
+ output D2ERRCNT3;
+ output D2ERRCNT2;
+ output D2ERRCNT1;
+ output D2ERRCNT0;
+ output D2PASS1;
+ output D2PASS0;
+ output D2VALID1;
+ output D2VALID0;
+ output D3ACTIVE1;
+ output D3ACTIVE0;
+ output D3BYTCNT9;
+ output D3BYTCNT8;
+ output D3BYTCNT7;
+ output D3BYTCNT6;
+ output D3BYTCNT5;
+ output D3BYTCNT4;
+ output D3BYTCNT3;
+ output D3BYTCNT2;
+ output D3BYTCNT1;
+ output D3BYTCNT0;
+ output D3ERRCNT9;
+ output D3ERRCNT8;
+ output D3ERRCNT7;
+ output D3ERRCNT6;
+ output D3ERRCNT5;
+ output D3ERRCNT4;
+ output D3ERRCNT3;
+ output D3ERRCNT2;
+ output D3ERRCNT1;
+ output D3ERRCNT0;
+ output D3PASS1;
+ output D3PASS0;
+ output D3VALID1;
+ output D3VALID0;
+ output DCTSTOUT9;
+ output DCTSTOUT8;
+ output DCTSTOUT7;
+ output DCTSTOUT6;
+ output DCTSTOUT5;
+ output DCTSTOUT4;
+ output DCTSTOUT3;
+ output DCTSTOUT2;
+ output DCTSTOUT1;
+ output DCTSTOUT0;
+ (* iopad_external_pin *)
+ inout DN0;
+ (* iopad_external_pin *)
+ inout DN1;
+ (* iopad_external_pin *)
+ inout DN2;
+ (* iopad_external_pin *)
+ inout DN3;
+ (* iopad_external_pin *)
+ inout DP0;
+ (* iopad_external_pin *)
+ inout DP1;
+ (* iopad_external_pin *)
+ inout DP2;
+ (* iopad_external_pin *)
+ inout DP3;
+ output LOCK;
+ input PDDPHY;
+ input PDPLL;
+ input SCCLKIN;
+ input SCRSTNIN;
+ output UDIR;
+ input UED0THEN;
+ output UERCLP0;
+ output UERCLP1;
+ output UERCTRL;
+ output UERE;
+ output UERSTHS;
+ output UERSSHS;
+ output UERSE;
+ input UFRXMODE;
+ input UTXMDTX;
+ output URXACTHS;
+ output URXCKE;
+ input URXCKINE;
+ output URXDE7;
+ output URXDE6;
+ output URXDE5;
+ output URXDE4;
+ output URXDE3;
+ output URXDE2;
+ output URXDE1;
+ output URXDE0;
+ output URXDHS15;
+ output URXDHS14;
+ output URXDHS13;
+ output URXDHS12;
+ output URXDHS11;
+ output URXDHS10;
+ output URXDHS9;
+ output URXDHS8;
+ output URXDHS7;
+ output URXDHS6;
+ output URXDHS5;
+ output URXDHS4;
+ output URXDHS3;
+ output URXDHS2;
+ output URXDHS1;
+ output URXDHS0;
+ output URXLPDTE;
+ output URXSKCHS;
+ output URXDRX;
+ output URXSHS3;
+ output URXSHS2;
+ output URXSHS1;
+ output URXSHS0;
+ output URE0D3DP;
+ output URE1D3DN;
+ output URE2CKDP;
+ output URE3CKDN;
+ output URXULPSE;
+ output URXVDE;
+ output URXVDHS3;
+ output URXVDHS2;
+ output URXVDHS1;
+ output URXVDHS0;
+ output USSTT;
+ input UTDIS;
+ input UTXCKE;
+ input UDE0D0TN;
+ input UDE1D1TN;
+ input UDE2D2TN;
+ input UDE3D3TN;
+ input UDE4CKTN;
+ input UDE5D0RN;
+ input UDE6D1RN;
+ input UDE7D2RN;
+ input UTXDHS31;
+ input UTXDHS30;
+ input UTXDHS29;
+ input UTXDHS28;
+ input UTXDHS27;
+ input UTXDHS26;
+ input UTXDHS25;
+ input UTXDHS24;
+ input UTXDHS23;
+ input UTXDHS22;
+ input UTXDHS21;
+ input UTXDHS20;
+ input UTXDHS19;
+ input UTXDHS18;
+ input UTXDHS17;
+ input UTXDHS16;
+ input UTXDHS15;
+ input UTXDHS14;
+ input UTXDHS13;
+ input UTXDHS12;
+ input UTXDHS11;
+ input UTXDHS10;
+ input UTXDHS9;
+ input UTXDHS8;
+ input UTXDHS7;
+ input UTXDHS6;
+ input UTXDHS5;
+ input UTXDHS4;
+ input UTXDHS3;
+ input UTXDHS2;
+ input UTXDHS1;
+ input UTXDHS0;
+ input UTXENER;
+ output UTXRRS;
+ output UTXRYP;
+ output UTXRYSK;
+ input UTXRD0EN;
+ input UTRD0SEN;
+ input UTXSKD0N;
+ input UTXTGE0;
+ input UTXTGE1;
+ input UTXTGE2;
+ input UTXTGE3;
+ input UTXULPSE;
+ input UTXUPSEX;
+ input UTXVDE;
+ input UTXWVDHS3;
+ input UTXWVDHS2;
+ input UTXWVDHS1;
+ input UTXWVDHS0;
+ output UUSAN;
+ output U1DIR;
+ input U1ENTHEN;
+ output U1ERCLP0;
+ output U1ERCLP1;
+ output U1ERCTRL;
+ output U1ERE;
+ output U1ERSTHS;
+ output U1ERSSHS;
+ output U1ERSE;
+ input U1FRXMD;
+ input U1FTXST;
+ output U1RXATHS;
+ output U1RXCKE;
+ output U1RXDE7;
+ output U1RXDE6;
+ output U1RXDE5;
+ output U1RXDE4;
+ output U1RXDE3;
+ output U1RXDE2;
+ output U1RXDE1;
+ output U1RXDE0;
+ output U1RXDHS15;
+ output U1RXDHS14;
+ output U1RXDHS13;
+ output U1RXDHS12;
+ output U1RXDHS11;
+ output U1RXDHS10;
+ output U1RXDHS9;
+ output U1RXDHS8;
+ output U1RXDHS7;
+ output U1RXDHS6;
+ output U1RXDHS5;
+ output U1RXDHS4;
+ output U1RXDHS3;
+ output U1RXDHS2;
+ output U1RXDHS1;
+ output U1RXDHS0;
+ output U1RXDTE;
+ output U1RXSKS;
+ output U1RXSK;
+ output U1RXSHS3;
+ output U1RXSHS2;
+ output U1RXSHS1;
+ output U1RXSHS0;
+ output U1RE0D;
+ output U1RE1CN;
+ output U1RE2D;
+ output U1RE3N;
+ output U1RXUPSE;
+ output U1RXVDE;
+ output U1RXVDHS3;
+ output U1RXVDHS2;
+ output U1RXVDHS1;
+ output U1RXVDHS0;
+ output U1SSTT;
+ input U1TDIS;
+ input U1TREQ;
+ input U1TDE0D3;
+ input U1TDE1CK;
+ input U1TDE2D0;
+ input U1TDE3D1;
+ input U1TDE4D2;
+ input U1TDE5D3;
+ input U1TDE6;
+ input U1TDE7;
+ input U1TXDHS31;
+ input U1TXDHS30;
+ input U1TXDHS29;
+ input U1TXDHS28;
+ input U1TXDHS27;
+ input U1TXDHS26;
+ input U1TXDHS25;
+ input U1TXDHS24;
+ input U1TXDHS23;
+ input U1TXDHS22;
+ input U1TXDHS21;
+ input U1TXDHS20;
+ input U1TXDHS19;
+ input U1TXDHS18;
+ input U1TXDHS17;
+ input U1TXDHS16;
+ input U1TXDHS15;
+ input U1TXDHS14;
+ input U1TXDHS13;
+ input U1TXDHS12;
+ input U1TXDHS11;
+ input U1TXDHS10;
+ input U1TXDHS9;
+ input U1TXDHS8;
+ input U1TXDHS7;
+ input U1TXDHS6;
+ input U1TXDHS5;
+ input U1TXDHS4;
+ input U1TXDHS3;
+ input U1TXDHS2;
+ input U1TXDHS1;
+ input U1TXDHS0;
+ input U1TXLPD;
+ output U1TXRYE;
+ output U1TXRY;
+ output U1TXRYSK;
+ input U1TXREQ;
+ input U1TXREQH;
+ input U1TXSK;
+ input U1TXTGE0;
+ input U1TXTGE1;
+ input U1TXTGE2;
+ input U1TXTGE3;
+ input U1TXUPSE;
+ input U1TXUPSX;
+ input U1TXVDE;
+ input U1TXWVHS3;
+ input U1TXWVHS2;
+ input U1TXWVHS1;
+ input U1TXWVHS0;
+ output U1USAN;
+ output U2DIR;
+ input U2END2;
+ output U2ERCLP0;
+ output U2ERCLP1;
+ output U2ERCTRL;
+ output U2ERE;
+ output U2ERSTHS;
+ output U2ERSSHS;
+ output U2ERSE;
+ input U2FRXMD;
+ input U2FTXST;
+ output U2RXACHS;
+ output U2RXCKE;
+ output U2RXDE7;
+ output U2RXDE6;
+ output U2RXDE5;
+ output U2RXDE4;
+ output U2RXDE3;
+ output U2RXDE2;
+ output U2RXDE1;
+ output U2RXDE0;
+ output U2RXDHS15;
+ output U2RXDHS14;
+ output U2RXDHS13;
+ output U2RXDHS12;
+ output U2RXDHS11;
+ output U2RXDHS10;
+ output U2RXDHS9;
+ output U2RXDHS8;
+ output U2RXDHS7;
+ output U2RXDHS6;
+ output U2RXDHS5;
+ output U2RXDHS4;
+ output U2RXDHS3;
+ output U2RXDHS2;
+ output U2RXDHS1;
+ output U2RXDHS0;
+ output U2RPDTE;
+ output U2RXSK;
+ output U2RXSKC;
+ output U2RXSHS3;
+ output U2RXSHS2;
+ output U2RXSHS1;
+ output U2RXSHS0;
+ output U2RE0D2;
+ output U2RE1D2;
+ output U2RE2D3;
+ output U2RE3D3;
+ output U2RXUPSE;
+ output U2RXVDE;
+ output U2RXVDHS3;
+ output U2RXVDHS2;
+ output U2RXVDHS1;
+ output U2RXVDHS0;
+ output U2SSTT;
+ input U2TDIS;
+ input U2TREQ;
+ input U2TDE0D0;
+ input U2TDE1D1;
+ input U2TDE2D2;
+ input U2TDE3D3;
+ input U2TDE4CK;
+ input U2TDE5D0;
+ input U2TDE6D1;
+ input U2TDE7D2;
+ input U2TXDHS31;
+ input U2TXDHS30;
+ input U2TXDHS29;
+ input U2TXDHS28;
+ input U2TXDHS27;
+ input U2TXDHS26;
+ input U2TXDHS25;
+ input U2TXDHS24;
+ input U2TXDHS23;
+ input U2TXDHS22;
+ input U2TXDHS21;
+ input U2TXDHS20;
+ input U2TXDHS19;
+ input U2TXDHS18;
+ input U2TXDHS17;
+ input U2TXDHS16;
+ input U2TXDHS15;
+ input U2TXDHS14;
+ input U2TXDHS13;
+ input U2TXDHS12;
+ input U2TXDHS11;
+ input U2TXDHS10;
+ input U2TXDHS9;
+ input U2TXDHS8;
+ input U2TXDHS7;
+ input U2TXDHS6;
+ input U2TXDHS5;
+ input U2TXDHS4;
+ input U2TXDHS3;
+ input U2TXDHS2;
+ input U2TXDHS1;
+ input U2TXDHS0;
+ input U2TPDTE;
+ output U2TXRYE;
+ output U2TXRYH;
+ output U2TXRYSK;
+ input U2TXREQ;
+ input U2TXREQH;
+ input U2TXSKC;
+ input U2TXTGE0;
+ input U2TXTGE1;
+ input U2TXTGE2;
+ input U2TXTGE3;
+ input U2TXUPSE;
+ input U2TXUPSX;
+ input U2TXVDE;
+ input U2TXWVHS3;
+ input U2TXWVHS2;
+ input U2TXWVHS1;
+ input U2TXWVHS0;
+ output U2USAN;
+ output U3DIR;
+ input U3END3;
+ output U3ERCLP0;
+ output U3ERCLP1;
+ output U3ERCTRL;
+ output U3ERE;
+ output U3ERSTHS;
+ output U3ERSSHS;
+ output U3ERSE;
+ input U3FRXMD;
+ input U3FTXST;
+ output U3RXATHS;
+ output U3RXCKE;
+ output U3RXDE7;
+ output U3RXDE6;
+ output U3RXDE5;
+ output U3RXDE4;
+ output U3RXDE3;
+ output U3RXDE2;
+ output U3RXDE1;
+ output U3RXDE0;
+ output U3RXDHS15;
+ output U3RXDHS14;
+ output U3RXDHS13;
+ output U3RXDHS12;
+ output U3RXDHS11;
+ output U3RXDHS10;
+ output U3RXDHS9;
+ output U3RXDHS8;
+ output U3RXDHS7;
+ output U3RXDHS6;
+ output U3RXDHS5;
+ output U3RXDHS4;
+ output U3RXDHS3;
+ output U3RXDHS2;
+ output U3RXDHS1;
+ output U3RXDHS0;
+ output U3RPDTE;
+ output U3RXSK;
+ output U3RXSKC;
+ output U3RXSHS3;
+ output U3RXSHS2;
+ output U3RXSHS1;
+ output U3RXSHS0;
+ output U3RE0CK;
+ output U3RE1CK;
+ output U3RE2;
+ output U3RE3;
+ output U3RXUPSE;
+ output U3RXVDE;
+ output U3RXVDHS3;
+ output U3RXVDHS2;
+ output U3RXVDHS1;
+ output U3RXVDHS0;
+ output U3SSTT;
+ input U3TDISD2;
+ input U3TREQD2;
+ input U3TDE0D3;
+ input U3TDE1D0;
+ input U3TDE2D1;
+ input U3TDE3D2;
+ input U3TDE4D3;
+ input U3TDE5CK;
+ input U3TDE6;
+ input U3TDE7;
+ input U3TXDHS31;
+ input U3TXDHS30;
+ input U3TXDHS29;
+ input U3TXDHS28;
+ input U3TXDHS27;
+ input U3TXDHS26;
+ input U3TXDHS25;
+ input U3TXDHS24;
+ input U3TXDHS23;
+ input U3TXDHS22;
+ input U3TXDHS21;
+ input U3TXDHS20;
+ input U3TXDHS19;
+ input U3TXDHS18;
+ input U3TXDHS17;
+ input U3TXDHS16;
+ input U3TXDHS15;
+ input U3TXDHS14;
+ input U3TXDHS13;
+ input U3TXDHS12;
+ input U3TXDHS11;
+ input U3TXDHS10;
+ input U3TXDHS9;
+ input U3TXDHS8;
+ input U3TXDHS7;
+ input U3TXDHS6;
+ input U3TXDHS5;
+ input U3TXDHS4;
+ input U3TXDHS3;
+ input U3TXDHS2;
+ input U3TXDHS1;
+ input U3TXDHS0;
+ input U3TXLPDT;
+ output U3TXRY;
+ output U3TXRYHS;
+ output U3TXRYSK;
+ input U3TXREQ;
+ input U3TXREQH;
+ input U3TXSKC;
+ input U3TXTGE0;
+ input U3TXTGE1;
+ input U3TXTGE2;
+ input U3TXTGE3;
+ input U3TXULPS;
+ input U3TXUPSX;
+ input U3TXVD3;
+ input U3TXWVHS3;
+ input U3TXWVHS2;
+ input U3TXWVHS1;
+ input U3TXWVHS0;
+ output U3USAN;
+ input UCENCK;
+ output UCRXCKAT;
+ output UCRXUCKN;
+ output UCSSTT;
+ input UCTXREQH;
+ input UCTXUPSC;
+ input UCTXUPSX;
+ output UCUSAN;
+ input SCANCLK;
+ input SCANRST;
+ input LMMICLK;
+ input LMMIOFFSET4;
+ input LMMIOFFSET3;
+ input LMMIOFFSET2;
+ input LMMIOFFSET1;
+ input LMMIOFFSET0;
+ output LMMIRDATA3;
+ output LMMIRDATA2;
+ output LMMIRDATA1;
+ output LMMIRDATA0;
+ output LMMIRDATAVALID;
+ output LMMIREADY;
+ input LMMIREQUEST;
+ input LMMIRESETN;
+ input LMMIWDATA3;
+ input LMMIWDATA2;
+ input LMMIWDATA1;
+ input LMMIWDATA0;
+ input LMMIWRRDN;
+ input LTSTEN;
+ input LTSTLANE1;
+ input LTSTLANE0;
+ output URWDCKHS;
+ input UTRNREQ;
+ output UTWDCKHS;
+ output UCRXWCHS;
+ input OPCGLDCK;
+ output CLKLBACT;
+endmodule
+
+module DQSBUF_CORE (...);
+ parameter GSR = "ENABLED";
+ parameter ENABLE_FIFO = "DISABLED";
+ parameter FORCE_READ = "DISABLED";
+ parameter FREE_WHEEL = "DDR";
+ parameter MODX = "NOT_USED";
+ parameter MT_EN_READ = "DISABLED";
+ parameter MT_EN_WRITE = "DISABLED";
+ parameter MT_EN_WRITE_LEVELING = "DISABLED";
+ parameter RD_PNTR = "0b000";
+ parameter READ_ENABLE = "DISABLED";
+ parameter RX_CENTERED = "ENABLED";
+ parameter S_READ = "0";
+ parameter S_WRITE = "0";
+ parameter SIGN_READ = "POSITIVE";
+ parameter SIGN_WRITE = "POSITIVE";
+ parameter UPDATE_QU = "UP1_AND_UP0_SAME";
+ parameter WRITE_ENABLE = "DISABLED";
+ parameter SEL_READ_BIT_ENABLE_CYCLES = "NORMAL";
+ parameter BYPASS_WR_LEVEL_SMTH_LATCH = "SMOOTHING_PATH";
+ parameter BYPASS_WR_SMTH_LATCH = "SMOOTHING_PATH";
+ parameter BYPASS_READ_SMTH_LATCH = "SMOOTHING_PATH";
+ output BTDETECT;
+ output BURSTDETECT;
+ output DATAVALID;
+ input DQSI;
+ output DQSW;
+ output DQSWRD;
+ input PAUSE;
+ input RDCLKSEL3;
+ input RDCLKSEL2;
+ input RDCLKSEL1;
+ input RDCLKSEL0;
+ input RDDIR;
+ input RDLOADN;
+ output RDPNTR2;
+ output RDPNTR1;
+ output RDPNTR0;
+ input READ3;
+ input READ2;
+ input READ1;
+ input READ0;
+ output READCOUT;
+ input READMOVE;
+ input RST;
+ input SCLK;
+ input SELCLK;
+ output DQSR90;
+ output DQSW270;
+ output WRCOUT;
+ input WRDIR;
+ input WRLOAD_N;
+ output WRLVCOUT;
+ input WRLVDIR;
+ input WRLVLOAD_N;
+ input WRLVMOVE;
+ input WRMOVE;
+ output WRPNTR2;
+ output WRPNTR1;
+ output WRPNTR0;
+ input ECLKIN;
+ input RSTSMCNT;
+ input DLLCODE8;
+ input DLLCODE7;
+ input DLLCODE6;
+ input DLLCODE5;
+ input DLLCODE4;
+ input DLLCODE3;
+ input DLLCODE2;
+ input DLLCODE1;
+ input DLLCODE0;
+endmodule
+
+module ECLKDIV_CORE (...);
+ parameter ECLK_DIV = "DISABLE";
+ parameter GSR = "ENABLED";
+ output DIVOUT;
+ input DIVRST;
+ input ECLKIN;
+ input SLIP;
+ input TESTINP3;
+ input TESTINP2;
+ input TESTINP1;
+ input TESTINP0;
+endmodule
+
+module ECLKSYNC_CORE (...);
+ parameter STOP_EN = "DISABLE";
+ input ECLKIN;
+ output ECLKOUT;
+ input STOP;
+endmodule
+
+module FBMUX_CORE (...);
+ parameter INTFB = "IGNORED";
+ parameter SEL_FBK = "DIVA";
+ parameter CLKMUX_FB = "CMUX_CLKOP";
+ parameter INTFBKDEL_SEL = "DISABLED";
+ output ENEXT;
+ output FBKCK;
+ input LGYRDYN;
+ input INTLOCK;
+ input WKUPSYNC;
+ input FBKCLK15;
+ input FBKCLK14;
+ input FBKCLK13;
+ input FBKCLK12;
+ input FBKCLK11;
+ input FBKCLK10;
+ input FBKCLK9;
+ input FBKCLK8;
+ input FBKCLK7;
+ input FBKCLK6;
+ input FBKCLK5;
+ input FBKCLK4;
+ input FBKCLK3;
+ input FBKCLK2;
+ input FBKCLK1;
+ input FBKCLK0;
+endmodule
+
+module I2CFIFO_CORE (...);
+ parameter BRNBASEDELAY = "0b0000";
+ parameter CR1CKDIS = "EN";
+ parameter CR1FIFOMODE = "REG";
+ parameter CR1GCEN = "DIS";
+ parameter CR1I2CEN = "DIS";
+ parameter CR1SDADELSEL = "NDLY0";
+ parameter CR1SLPCLKEN = "DIS";
+ parameter CR2CORERSTN = "DIS";
+ parameter CR2HARDTIE = "TIE";
+ parameter CR2INTCLREN = "DIS";
+ parameter CR2MRDCMPLWKUP = "DIS";
+ parameter CR2RXFIFOAFWKUP = "DIS";
+ parameter CR2SLVADDRWKUP = "DIS";
+ parameter GSR = "ENABLED";
+ parameter I2CRXFIFOAFVAL = "0b00000";
+ parameter I2CSLVADDRA = "0b0000000000";
+ parameter I2CTXFIFOAEVAL = "0b0000";
+ parameter INTARBLIE = "DIS";
+ parameter INTBUSFREEIE = "DIS";
+ parameter INTHGCIE = "DIS";
+ parameter INTMRDCMPLIE = "DIS";
+ parameter INTRNACKIEORRSVD = "DIS";
+ parameter INTRSVDORTROEIE = "DIS";
+ parameter INTRSVDORTRRDYIE = "DIS";
+ parameter INTRXOVERFIEORRSVD = "DIS";
+ parameter INTRXUNDERFIE = "DIS";
+ parameter INTTXOVERFIE = "DIS";
+ parameter INTTXSERRIEORRSVD = "DIS";
+ parameter LMMI_EXTRA_ONE = "DIS";
+ parameter LMMI_EXTRA_TWO = "DIS";
+ parameter NCRALTIOEN = "FABRIC";
+ parameter NCRFILTERDIS = "EN";
+ parameter NCRSDAINDLYEN = "DIS";
+ parameter NCRSDAOUTDLYEN = "DIS";
+ parameter NONUSRTESTSOFTTRIMEN = "DIS";
+ parameter NONUSRTSTSOFTTRIMVALUE = "0b000";
+ parameter REGI2CBR = "0b0000000000";
+ parameter TSPTIMERVALUE = "0b10010010111";
+ input ALTSCLIN;
+ output ALTSCLOEN;
+ output ALTSCLOUT;
+ input ALTSDAIN;
+ output ALTSDAOEN;
+ output ALTSDAOUT;
+ output BUSBUSY;
+ input FIFORESET;
+ input I2CLSRRSTN;
+ output INSLEEP;
+ output IRQ;
+ input LMMICLK;
+ input LMMIOFFSET5;
+ input LMMIOFFSET4;
+ input LMMIOFFSET3;
+ input LMMIOFFSET2;
+ input LMMIOFFSET1;
+ input LMMIOFFSET0;
+ output LMMIRDATA7;
+ output LMMIRDATA6;
+ output LMMIRDATA5;
+ output LMMIRDATA4;
+ output LMMIRDATA3;
+ output LMMIRDATA2;
+ output LMMIRDATA1;
+ output LMMIRDATA0;
+ output LMMIRDATAVALID;
+ output LMMIREADY;
+ input LMMIREQUEST;
+ input LMMIRESETN;
+ input LMMIWDATA7;
+ input LMMIWDATA6;
+ input LMMIWDATA5;
+ input LMMIWDATA4;
+ input LMMIWDATA3;
+ input LMMIWDATA2;
+ input LMMIWDATA1;
+ input LMMIWDATA0;
+ input LMMIWRRDN;
+ output MRDCMPL;
+ input OPCGLOADCLK;
+ output RXFIFOAF;
+ output RXFIFOE;
+ output RXFIFOF;
+ input SCANCLK;
+ input SCANRST;
+ input SCLIN;
+ output SCLOE;
+ output SCLOEN;
+ output SCLOUT;
+ input SDAIN;
+ output SDAOE;
+ output SDAOEN;
+ output SDAOUT;
+ input SLEEPCLKSELN;
+ output SLVADDRMATCH;
+ output SLVADDRMATCHSCL;
+ output SRDWR;
+ output TXFIFOAE;
+ output TXFIFOE;
+ output TXFIFOF;
+endmodule
+
+module LRAM_CORE (...);
+ parameter INITVAL_00 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_01 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_02 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_03 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_04 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_05 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_06 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_07 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_08 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_09 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_0F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_10 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_11 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_12 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_13 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_14 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_15 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_16 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_17 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_18 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_19 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_1F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_20 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_21 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_22 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_23 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_24 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_25 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_26 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_27 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_28 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_29 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_2F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_30 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_31 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_32 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_33 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_34 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_35 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_36 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_37 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_38 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_39 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_3F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_40 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_41 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_42 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_43 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_44 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_45 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_46 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_47 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_48 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_49 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_4F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_50 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_51 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_52 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_53 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_54 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_55 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_56 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_57 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_58 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_59 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_5F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_60 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_61 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_62 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_63 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_64 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_65 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_66 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_67 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_68 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_69 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_6F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_70 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_71 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_72 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_73 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_74 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_75 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_76 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_77 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_78 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_79 = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7A = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7B = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7C = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7D = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7E = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter INITVAL_7F = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter ASYNC_RST_RELEASE = "SYNC";
+ parameter CFG_INIT_ID = "0b00000000000";
+ parameter DATA_PRESERVE = "DISABLE";
+ parameter EBR_SP_EN = "DISABLE";
+ parameter ECC_BYTE_SEL = "ECC_EN";
+ parameter GSR = "ENABLED";
+ parameter OUT_REGMODE_A = "NO_REG";
+ parameter OUT_REGMODE_B = "NO_REG";
+ parameter RESETMODE = "SYNC";
+ parameter RST_AB_EN = "RESET_AB_DISABLE";
+ parameter SP_EN = "DISABLE";
+ parameter UNALIGNED_READ = "DISABLE";
+ input ADA13;
+ input ADA12;
+ input ADA11;
+ input ADA10;
+ input ADA9;
+ input ADA8;
+ input ADA7;
+ input ADA6;
+ input ADA5;
+ input ADA4;
+ input ADA3;
+ input ADA2;
+ input ADA1;
+ input ADA0;
+ input ADB13;
+ input ADB12;
+ input ADB11;
+ input ADB10;
+ input ADB9;
+ input ADB8;
+ input ADB7;
+ input ADB6;
+ input ADB5;
+ input ADB4;
+ input ADB3;
+ input ADB2;
+ input ADB1;
+ input ADB0;
+ input BENA_N3;
+ input BENA_N2;
+ input BENA_N1;
+ input BENA_N0;
+ input BENB_N3;
+ input BENB_N2;
+ input BENB_N1;
+ input BENB_N0;
+ input CEA;
+ input CEB;
+ input CLK;
+ input CSA;
+ input CSB;
+ input DIA31;
+ input DIA30;
+ input DIA29;
+ input DIA28;
+ input DIA27;
+ input DIA26;
+ input DIA25;
+ input DIA24;
+ input DIA23;
+ input DIA22;
+ input DIA21;
+ input DIA20;
+ input DIA19;
+ input DIA18;
+ input DIA17;
+ input DIA16;
+ input DIA15;
+ input DIA14;
+ input DIA13;
+ input DIA12;
+ input DIA11;
+ input DIA10;
+ input DIA9;
+ input DIA8;
+ input DIA7;
+ input DIA6;
+ input DIA5;
+ input DIA4;
+ input DIA3;
+ input DIA2;
+ input DIA1;
+ input DIA0;
+ input DIB31;
+ input DIB30;
+ input DIB29;
+ input DIB28;
+ input DIB27;
+ input DIB26;
+ input DIB25;
+ input DIB24;
+ input DIB23;
+ input DIB22;
+ input DIB21;
+ input DIB20;
+ input DIB19;
+ input DIB18;
+ input DIB17;
+ input DIB16;
+ input DIB15;
+ input DIB14;
+ input DIB13;
+ input DIB12;
+ input DIB11;
+ input DIB10;
+ input DIB9;
+ input DIB8;
+ input DIB7;
+ input DIB6;
+ input DIB5;
+ input DIB4;
+ input DIB3;
+ input DIB2;
+ input DIB1;
+ input DIB0;
+ output DOA31;
+ output DOA30;
+ output DOA29;
+ output DOA28;
+ output DOA27;
+ output DOA26;
+ output DOA25;
+ output DOA24;
+ output DOA23;
+ output DOA22;
+ output DOA21;
+ output DOA20;
+ output DOA19;
+ output DOA18;
+ output DOA17;
+ output DOA16;
+ output DOA15;
+ output DOA14;
+ output DOA13;
+ output DOA12;
+ output DOA11;
+ output DOA10;
+ output DOA9;
+ output DOA8;
+ output DOA7;
+ output DOA6;
+ output DOA5;
+ output DOA4;
+ output DOA3;
+ output DOA2;
+ output DOA1;
+ output DOA0;
+ output DOB31;
+ output DOB30;
+ output DOB29;
+ output DOB28;
+ output DOB27;
+ output DOB26;
+ output DOB25;
+ output DOB24;
+ output DOB23;
+ output DOB22;
+ output DOB21;
+ output DOB20;
+ output DOB19;
+ output DOB18;
+ output DOB17;
+ output DOB16;
+ output DOB15;
+ output DOB14;
+ output DOB13;
+ output DOB12;
+ output DOB11;
+ output DOB10;
+ output DOB9;
+ output DOB8;
+ output DOB7;
+ output DOB6;
+ output DOB5;
+ output DOB4;
+ output DOB3;
+ output DOB2;
+ output DOB1;
+ output DOB0;
+ input DPS;
+ output ERRDECA1;
+ output ERRDECA0;
+ output ERRDECB1;
+ output ERRDECB0;
+ input IGN;
+ input INITN;
+ input OCEA;
+ input OCEB;
+ output OEA;
+ output OEB;
+ input RSTA;
+ input RSTB;
+ input STDBYN;
+ input TBISTN;
+ input WEA;
+ input WEB;
+ output ERRDET;
+ output LRAMREADY;
+ input OPCGLOADCLK;
+ input SCANCLK;
+ input SCANRST;
+endmodule
+
+module MULT18_CORE (...);
+ parameter SFTEN = "DISABLED";
+ parameter MULT18X18 = "ENABLED";
+ parameter ROUNDHALFUP = "DISABLED";
+ parameter ROUNDRTZI = "ROUND_TO_ZERO";
+ parameter ROUNDBIT = "ROUND_TO_BIT0";
+ input SFTCTRL3;
+ input SFTCTRL2;
+ input SFTCTRL1;
+ input SFTCTRL0;
+ input ARHSIGN;
+ input BRHSIGN;
+ input ARH8;
+ input ARH7;
+ input ARH6;
+ input ARH5;
+ input ARH4;
+ input ARH3;
+ input ARH2;
+ input ARH1;
+ input ARH0;
+ input BRH8;
+ input BRH7;
+ input BRH6;
+ input BRH5;
+ input BRH4;
+ input BRH3;
+ input BRH2;
+ input BRH1;
+ input BRH0;
+ input ARL8;
+ input ARL7;
+ input ARL6;
+ input ARL5;
+ input ARL4;
+ input ARL3;
+ input ARL2;
+ input ARL1;
+ input ARL0;
+ input BRL8;
+ input BRL7;
+ input BRL6;
+ input BRL5;
+ input BRL4;
+ input BRL3;
+ input BRL2;
+ input BRL1;
+ input BRL0;
+ input PL1819;
+ input PL1818;
+ input PL1817;
+ input PL1816;
+ input PL1815;
+ input PL1814;
+ input PL1813;
+ input PL1812;
+ input PL1811;
+ input PL1810;
+ input PL189;
+ input PL188;
+ input PL187;
+ input PL186;
+ input PL185;
+ input PL184;
+ input PL183;
+ input PL182;
+ input PL181;
+ input PL180;
+ input PH1819;
+ input PH1818;
+ input PH1817;
+ input PH1816;
+ input PH1815;
+ input PH1814;
+ input PH1813;
+ input PH1812;
+ input PH1811;
+ input PH1810;
+ input PH189;
+ input PH188;
+ input PH187;
+ input PH186;
+ input PH185;
+ input PH184;
+ input PH183;
+ input PH182;
+ input PH181;
+ input PH180;
+ output SIGNED18;
+ output P3637;
+ output P3636;
+ output P3635;
+ output P3634;
+ output P3633;
+ output P3632;
+ output P3631;
+ output P3630;
+ output P3629;
+ output P3628;
+ output P3627;
+ output P3626;
+ output P3625;
+ output P3624;
+ output P3623;
+ output P3622;
+ output P3621;
+ output P3620;
+ output P3619;
+ output P3618;
+ output P3617;
+ output P3616;
+ output P3615;
+ output P3614;
+ output P3613;
+ output P3612;
+ output P3611;
+ output P3610;
+ output P369;
+ output P368;
+ output P367;
+ output P366;
+ output P365;
+ output P364;
+ output P363;
+ output P362;
+ output P361;
+ output P360;
+ input ROUNDEN;
+endmodule
+
+module MULT18X36_CORE (...);
+ parameter SFTEN = "DISABLED";
+ parameter MULT18X36 = "ENABLED";
+ parameter MULT36 = "DISABLED";
+ parameter MULT36X36H = "USED_AS_LOWER_BIT_GENERATION";
+ parameter ROUNDHALFUP = "DISABLED";
+ parameter ROUNDRTZI = "ROUND_TO_ZERO";
+ parameter ROUNDBIT = "ROUND_TO_BIT0";
+ input SFTCTRL3;
+ input SFTCTRL2;
+ input SFTCTRL1;
+ input SFTCTRL0;
+ input PH3637;
+ input PH3636;
+ input PH3635;
+ input PH3634;
+ input PH3633;
+ input PH3632;
+ input PH3631;
+ input PH3630;
+ input PH3629;
+ input PH3628;
+ input PH3627;
+ input PH3626;
+ input PH3625;
+ input PH3624;
+ input PH3623;
+ input PH3622;
+ input PH3621;
+ input PH3620;
+ input PH3619;
+ input PH3618;
+ input PH3617;
+ input PH3616;
+ input PH3615;
+ input PH3614;
+ input PH3613;
+ input PH3612;
+ input PH3611;
+ input PH3610;
+ input PH369;
+ input PH368;
+ input PH367;
+ input PH366;
+ input PH365;
+ input PH364;
+ input PH363;
+ input PH362;
+ input PH361;
+ input PH360;
+ input PL3637;
+ input PL3636;
+ input PL3635;
+ input PL3634;
+ input PL3633;
+ input PL3632;
+ input PL3631;
+ input PL3630;
+ input PL3629;
+ input PL3628;
+ input PL3627;
+ input PL3626;
+ input PL3625;
+ input PL3624;
+ input PL3623;
+ input PL3622;
+ input PL3621;
+ input PL3620;
+ input PL3619;
+ input PL3618;
+ input PL3617;
+ input PL3616;
+ input PL3615;
+ input PL3614;
+ input PL3613;
+ input PL3612;
+ input PL3611;
+ input PL3610;
+ input PL369;
+ input PL368;
+ input PL367;
+ input PL366;
+ input PL365;
+ input PL364;
+ input PL363;
+ input PL362;
+ input PL361;
+ input PL360;
+ input SGNED18H;
+ input SGNED18L;
+ output P7272;
+ output P7271;
+ output P7270;
+ output P7269;
+ output P7268;
+ output P7267;
+ output P7266;
+ output P7265;
+ output P7264;
+ output P7263;
+ output P7262;
+ output P7261;
+ output P7260;
+ output P7259;
+ output P7258;
+ output P7257;
+ output P7256;
+ output P7255;
+ output P7254;
+ output P7253;
+ output P7252;
+ output P7251;
+ output P7250;
+ output P7249;
+ output P7248;
+ output P7247;
+ output P7246;
+ output P7245;
+ output P7244;
+ output P7243;
+ output P7242;
+ output P7241;
+ output P7240;
+ output P7239;
+ output P7238;
+ output P7237;
+ output P7236;
+ output P7235;
+ output P7234;
+ output P7233;
+ output P7232;
+ output P7231;
+ output P7230;
+ output P7229;
+ output P7228;
+ output P7227;
+ output P7226;
+ output P7225;
+ output P7224;
+ output P7223;
+ output P7222;
+ output P7221;
+ output P7220;
+ output P7219;
+ output P7218;
+ output P7217;
+ output P7216;
+ output P7215;
+ output P7214;
+ output P7213;
+ output P7212;
+ output P7211;
+ output P7210;
+ output P729;
+ output P728;
+ output P727;
+ output P726;
+ output P725;
+ output P724;
+ output P723;
+ output P722;
+ output P721;
+ output P720;
+ input ROUNDEN;
+endmodule
+
+module MULT36_CORE (...);
+ parameter MULT36X36 = "ENABLED";
+ input PH7272;
+ input PH7271;
+ input PH7270;
+ input PH7269;
+ input PH7268;
+ input PH7267;
+ input PH7266;
+ input PH7265;
+ input PH7264;
+ input PH7263;
+ input PH7262;
+ input PH7261;
+ input PH7260;
+ input PH7259;
+ input PH7258;
+ input PH7257;
+ input PH7256;
+ input PH7255;
+ input PH7254;
+ input PH7253;
+ input PH7252;
+ input PH7251;
+ input PH7250;
+ input PH7249;
+ input PH7248;
+ input PH7247;
+ input PH7246;
+ input PH7245;
+ input PH7244;
+ input PH7243;
+ input PH7242;
+ input PH7241;
+ input PH7240;
+ input PH7239;
+ input PH7238;
+ input PH7237;
+ input PH7236;
+ input PH7235;
+ input PH7234;
+ input PH7233;
+ input PH7232;
+ input PH7231;
+ input PH7230;
+ input PH7229;
+ input PH7228;
+ input PH7227;
+ input PH7226;
+ input PH7225;
+ input PH7224;
+ input PH7223;
+ input PH7222;
+ input PH7221;
+ input PH7220;
+ input PH7219;
+ input PH7218;
+ input PH7217;
+ input PH7216;
+ input PH7215;
+ input PH7214;
+ input PH7213;
+ input PH7212;
+ input PH7211;
+ input PH7210;
+ input PH729;
+ input PH728;
+ input PH727;
+ input PH726;
+ input PH725;
+ input PH724;
+ input PH723;
+ input PH722;
+ input PH721;
+ input PH720;
+ input PL7272;
+ input PL7271;
+ input PL7270;
+ input PL7269;
+ input PL7268;
+ input PL7267;
+ input PL7266;
+ input PL7265;
+ input PL7264;
+ input PL7263;
+ input PL7262;
+ input PL7261;
+ input PL7260;
+ input PL7259;
+ input PL7258;
+ input PL7257;
+ input PL7256;
+ input PL7255;
+ input PL7254;
+ input PL7253;
+ input PL7252;
+ input PL7251;
+ input PL7250;
+ input PL7249;
+ input PL7248;
+ input PL7247;
+ input PL7246;
+ input PL7245;
+ input PL7244;
+ input PL7243;
+ input PL7242;
+ input PL7241;
+ input PL7240;
+ input PL7239;
+ input PL7238;
+ input PL7237;
+ input PL7236;
+ input PL7235;
+ input PL7234;
+ input PL7233;
+ input PL7232;
+ input PL7231;
+ input PL7230;
+ input PL7229;
+ input PL7228;
+ input PL7227;
+ input PL7226;
+ input PL7225;
+ input PL7224;
+ input PL7223;
+ input PL7222;
+ input PL7221;
+ input PL7220;
+ input PL7219;
+ input PL7218;
+ input PL7217;
+ input PL7216;
+ input PL7215;
+ input PL7214;
+ input PL7213;
+ input PL7212;
+ input PL7211;
+ input PL7210;
+ input PL729;
+ input PL728;
+ input PL727;
+ input PL726;
+ input PL725;
+ input PL724;
+ input PL723;
+ input PL722;
+ input PL721;
+ input PL720;
+ output PML7271;
+ output PML7270;
+ output PML7269;
+ output PML7268;
+ output PML7267;
+ output PML7266;
+ output PML7265;
+ output PML7264;
+ output PML7263;
+ output PML7262;
+ output PML7261;
+ output PML7260;
+ output PML7259;
+ output PML7258;
+ output PML7257;
+ output PML7256;
+ output PML7255;
+ output PML7254;
+ output PML7253;
+ output PML7252;
+ output PML7251;
+ output PML7250;
+ output PML7249;
+ output PML7248;
+ output PML7247;
+ output PML7246;
+ output PML7245;
+ output PML7244;
+ output PML7243;
+ output PML7242;
+ output PML7241;
+ output PML7240;
+ output PML7239;
+ output PML7238;
+ output PML7237;
+ output PML7236;
+ output PML7235;
+ output PML7234;
+ output PML7233;
+ output PML7232;
+ output PML7231;
+ output PML7230;
+ output PML7229;
+ output PML7228;
+ output PML7227;
+ output PML7226;
+ output PML7225;
+ output PML7224;
+ output PML7223;
+ output PML7222;
+ output PML7221;
+ output PML7220;
+ output PML7219;
+ output PML7218;
+ output PML7217;
+ output PML7216;
+ output PML7215;
+ output PML7214;
+ output PML7213;
+ output PML7212;
+ output PML7211;
+ output PML7210;
+ output PML729;
+ output PML728;
+ output PML727;
+ output PML726;
+ output PML725;
+ output PML724;
+ output PML723;
+ output PML722;
+ output PML721;
+ output PML720;
+ output PMH7271;
+ output PMH7270;
+ output PMH7269;
+ output PMH7268;
+ output PMH7267;
+ output PMH7266;
+ output PMH7265;
+ output PMH7264;
+ output PMH7263;
+ output PMH7262;
+ output PMH7261;
+ output PMH7260;
+ output PMH7259;
+ output PMH7258;
+ output PMH7257;
+ output PMH7256;
+ output PMH7255;
+ output PMH7254;
+ output PMH7253;
+ output PMH7252;
+ output PMH7251;
+ output PMH7250;
+ output PMH7249;
+ output PMH7248;
+ output PMH7247;
+ output PMH7246;
+ output PMH7245;
+ output PMH7244;
+ output PMH7243;
+ output PMH7242;
+ output PMH7241;
+ output PMH7240;
+ output PMH7239;
+ output PMH7238;
+ output PMH7237;
+ output PMH7236;
+ output PMH7235;
+ output PMH7234;
+ output PMH7233;
+ output PMH7232;
+ output PMH7231;
+ output PMH7230;
+ output PMH7229;
+ output PMH7228;
+ output PMH7227;
+ output PMH7226;
+ output PMH7225;
+ output PMH7224;
+ output PMH7223;
+ output PMH7222;
+ output PMH7221;
+ output PMH7220;
+ output PMH7219;
+ output PMH7218;
+ output PMH7217;
+ output PMH7216;
+ output PMH7215;
+ output PMH7214;
+ output PMH7213;
+ output PMH7212;
+ output PMH7211;
+ output PMH7210;
+ output PMH729;
+ output PMH728;
+ output PMH727;
+ output PMH726;
+ output PMH725;
+ output PMH724;
+ output PMH723;
+ output PMH722;
+ output PMH721;
+ output PMH720;
+endmodule
+
+module MULT9_CORE (...);
+ parameter SIGNEDSTATIC_EN = "DISABLED";
+ parameter ASIGNED_OPERAND_EN = "DISABLED";
+ parameter BYPASS_MULT9 = "USED";
+ parameter REGBYPSB = "REGISTER";
+ parameter REGBYPSA1 = "REGISTER";
+ parameter REGBYPSA2 = "REGISTER";
+ parameter SHIFTA = "DISABLED";
+ parameter SR_18BITSHIFT_EN = "DISABLED";
+ parameter GSR = "ENABLED";
+ parameter RESET = "SYNC";
+ input A8;
+ input A7;
+ input A6;
+ input A5;
+ input A4;
+ input A3;
+ input A2;
+ input A1;
+ input A0;
+ input ASIGNED;
+ input BR8;
+ input BR7;
+ input BR6;
+ input BR5;
+ input BR4;
+ input BR3;
+ input BR2;
+ input BR1;
+ input BR0;
+ input AS18;
+ input AS17;
+ input AS16;
+ input AS15;
+ input AS14;
+ input AS13;
+ input AS12;
+ input AS11;
+ input AS10;
+ input AS28;
+ input AS27;
+ input AS26;
+ input AS25;
+ input AS24;
+ input AS23;
+ input AS22;
+ input AS21;
+ input AS20;
+ input ASSIGNED1;
+ input ASSIGNED2;
+ input BRSIGNED;
+ input CLK;
+ input CEA;
+ input RSTA;
+ output AO8;
+ output AO7;
+ output AO6;
+ output AO5;
+ output AO4;
+ output AO3;
+ output AO2;
+ output AO1;
+ output AO0;
+ output BO8;
+ output BO7;
+ output BO6;
+ output BO5;
+ output BO4;
+ output BO3;
+ output BO2;
+ output BO1;
+ output BO0;
+ output AOSIGNED;
+ output BOSIGNED;
+ output AR8;
+ output AR7;
+ output AR6;
+ output AR5;
+ output AR4;
+ output AR3;
+ output AR2;
+ output AR1;
+ output AR0;
+ output ARSIGNED;
+ output P1819;
+ output P1818;
+ output P1817;
+ output P1816;
+ output P1815;
+ output P1814;
+ output P1813;
+ output P1812;
+ output P1811;
+ output P1810;
+ output P189;
+ output P188;
+ output P187;
+ output P186;
+ output P185;
+ output P184;
+ output P183;
+ output P182;
+ output P181;
+ output P180;
+ input CEP;
+ input RSTP;
+endmodule
+
+module OSC_CORE (...);
+ parameter DTR_EN = "ENABLED";
+ parameter HF_CLK_DIV = "1";
+ parameter HF_SED_SEC_DIV = "1";
+ parameter HF_FABRIC_EN = "DISABLED";
+ parameter HF_OSC_EN = "ENABLED";
+ parameter HFDIV_FABRIC_EN = "ENABLED";
+ parameter LF_FABRIC_EN = "DISABLED";
+ parameter LF_OUTPUT_EN = "DISABLED";
+ parameter DEBUG_N = "DISABLED";
+ output HFCLKOUT;
+ input HFOUTEN;
+ input HFSDSCEN;
+ input HFTRMFAB8;
+ input HFTRMFAB7;
+ input HFTRMFAB6;
+ input HFTRMFAB5;
+ input HFTRMFAB4;
+ input HFTRMFAB3;
+ input HFTRMFAB2;
+ input HFTRMFAB1;
+ input HFTRMFAB0;
+ output LFCLKOUT;
+ input LFTRMFAB8;
+ input LFTRMFAB7;
+ input LFTRMFAB6;
+ input LFTRMFAB5;
+ input LFTRMFAB4;
+ input LFTRMFAB3;
+ input LFTRMFAB2;
+ input LFTRMFAB1;
+ input LFTRMFAB0;
+ output HFCLKCFG;
+ output HFSDCOUT;
+endmodule
+
+module PCIE_CORE (...);
+ parameter ENABLE_USER_CFG = "DISABLED";
+ parameter PWDN_N = "DISABLED";
+ parameter GSR = "ENABLED";
+ parameter IDDQ_PCS = "DISABLED";
+ parameter PHY_MODE = "0b0000";
+ parameter ALT_CLK_SEL_VCC = "PAD";
+ parameter L0S_ADJ = "0b00000110000000";
+ parameter L0S_EXIT_LATENCY = "MORE_4_US";
+ parameter L1_EXIT_LATENCY = "MORE_64_US";
+ parameter CALIB_3DB = "ENABLED";
+ parameter DB_UPSTREAM = "6DB";
+ parameter ERR_REC_ENTRY_SEL = "RCVRY_AFTER";
+ parameter A_CHNGD_MAX = "0b100";
+ parameter A0_FORCE = "DISABLED";
+ parameter A0_FREEZE = "DISABLED";
+ parameter A0_INIT = "0b000000";
+ parameter A0DIR_VAL = "DISABLED";
+ parameter A1_FORCE = "DISABLED";
+ parameter A1_FREEZE = "DISABLED";
+ parameter A1_INIT = "0b000000";
+ parameter A1DIR_VAL = "DISABLED";
+ parameter A2_FORCE = "DISABLED";
+ parameter A2_FREEZE = "DISABLED";
+ parameter A2_INIT = "0b000000";
+ parameter A2GAIN_CALIB = "0b100110";
+ parameter ACJTAG_REG = "0b00";
+ parameter ADDR_LIMIT_PRE_MTHD_CTRL = "0b0100";
+ parameter ADDR_LIMIT_TABLE_MTHD_CTRL = "0b00101";
+ parameter ADIR_OVR = "DISABLED";
+ parameter ADV_CH_CD_SEL = "IMPLEMENT_CH";
+ parameter ADV_TARGET_LINK_SPEED_USPORT_A = "DISABLED";
+ parameter ADV_TARGET_LINK_SPEED_USPORT_B = "DISABLED";
+ parameter ADV_TARGET_LINK_SPEED_USPORT_C = "DISABLED";
+ parameter ADV_TARGET_LINK_SPEED_USPORT_D = "DISABLED";
+ parameter ADVANCE = "DISABLED";
+ parameter ALERT_ENABLE = "0b000";
+ parameter ALMOST_EMPTY_10B = "0b001110";
+ parameter MID_VALUE_10B = "0b011110";
+ parameter ALMOST_EMPTY_20B = "0b001111";
+ parameter ALMOST_EMPTY_GEN3 = "0b001100";
+ parameter ALMOST_FULL_10B = "0b110000";
+ parameter ALMOST_FULL_20B = "0b011000";
+ parameter ALMOST_FULL_GEN3 = "0b010110";
+ parameter ARRAY_DA = "0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter ARRAY_MT = "0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000011100000000000010000000000000001001000000000000011000000000000001010000000000000100";
+ parameter ARXCDRICP_RATE0 = "0b011";
+ parameter ARXCDRICP_RATE1 = "0b011";
+ parameter ARXCDRICP_RATE2 = "0b011";
+ parameter ARXDMPWRDWN = "DISABLED";
+ parameter ARXDPPWRDN = "DISABLED";
+ parameter ARXEOM_PWRDN = "POWERED_DOWN";
+ parameter ARXICP_RATE0 = "0b011";
+ parameter ARXICP_RATE1 = "0b011";
+ parameter ARXICP_RATE2 = "0b011";
+ parameter ARXOVR_OUT = "DISABLED";
+ parameter ARXRSACTAT = "0b0001";
+ parameter ARXRSAPTAT = "0b1000";
+ parameter ARXRSVCTL = "0b00000000";
+ parameter ARXSEL_OUT = "DISABLED";
+ parameter ASPM_L1_1_SUPPORTED = "SUPPORTED";
+ parameter ASPM_L1_2_SUPPORTED = "SUPPORTED";
+ parameter ASPM_SUPPORT = "L0S_AND_L1_SUPPORTED";
+ parameter ATTENTION_BUTTON_PRESENT = "NOT_SUPPORTED";
+ parameter ATTENTION_INDICATOR_PRESENT = "NOT_SUPPORTED";
+ parameter ATXICP_RATE0 = "0b101";
+ parameter ATXICP_RATE1 = "0b101";
+ parameter AUTO_SHIFT = "ENABLED";
+ parameter AUX_CURRENT = "SELF_POWERED";
+ parameter AUXCLK1US_MAX = "0b00001001";
+ parameter AUXIDL_MAX = "0b00000100";
+ parameter BAR_INDEX_CFG0_A = "0b000";
+ parameter BAR_INDEX_CFG0_B = "0b000";
+ parameter BAR_INDEX_CFG0_C = "0b000";
+ parameter BAR_INDEX_CFG0_D = "0b000";
+ parameter BAR_INDEX_CFG1_A = "0b001";
+ parameter BAR_INDEX_CFG1_B = "0b001";
+ parameter BAR_INDEX_CFG1_C = "0b001";
+ parameter BAR_INDEX_CFG1_D = "0b001";
+ parameter BAR_INDEX_CFG2_A = "0b010";
+ parameter BAR_INDEX_CFG2_B = "0b010";
+ parameter BAR_INDEX_CFG2_C = "0b010";
+ parameter BAR_INDEX_CFG2_D = "0b010";
+ parameter BAR_INDEX_CFG3_A = "0b011";
+ parameter BAR_INDEX_CFG3_B = "0b011";
+ parameter BAR_INDEX_CFG3_C = "0b011";
+ parameter BAR_INDEX_CFG3_D = "0b011";
+ parameter BAR_INDEX_CFG4_A = "0b100";
+ parameter BAR_INDEX_CFG4_B = "0b100";
+ parameter BAR_INDEX_CFG4_C = "0b100";
+ parameter BAR_INDEX_CFG4_D = "0b100";
+ parameter BAR_INDEX_CFG5_A = "0b101";
+ parameter BAR_INDEX_CFG5_B = "0b101";
+ parameter BAR_INDEX_CFG5_C = "0b101";
+ parameter BAR_INDEX_CFG5_D = "0b101";
+ parameter BIR_MSIX_PBA_A = "BAR0";
+ parameter BIR_MSIX_PBA_B = "BAR0";
+ parameter BIR_MSIX_PBA_C = "BAR0";
+ parameter BIR_MSIX_PBA_D = "BAR0";
+ parameter BIR_MSIX_TABLE_A = "BAR0";
+ parameter BIR_MSIX_TABLE_B = "BAR0";
+ parameter BIR_MSIX_TABLE_C = "BAR0";
+ parameter BIR_MSIX_TABLE_D = "BAR0";
+ parameter BYP_AVG = "USED";
+ parameter BYPASS = "PERFORM_RECEIVER_DETECTION";
+ parameter BYPASS_ADDR_DEC = "NORMAL";
+ parameter CALIB_SETTLE_MAX = "0b001";
+ parameter CALIB_STABLE_MAX = "0b11000";
+ parameter CAPABILITY_VERSION = "0b0010";
+ parameter CDR_ERR = "DISABLED";
+ parameter CDR_P1 = "CDR_PLL_RESET";
+ parameter CDR_PLL_DELTA = "0P4_PERCENT";
+ parameter CDR_REFERENCE = "0b00";
+ parameter CDRPLL_CMP_MAX = "0b00010100";
+ parameter CDRPLL_CNT_MAX = "0b00000100";
+ parameter CDRPLL_PRE_RXEQ_COARSE_TIMER = "0b01010000";
+ parameter CDRPLL_PRE_RXEQ_FINE_TIMER = "0b10110100";
+ parameter CDRPLL_PST_RXEQ_COARSE_TIMER = "0b01000000";
+ parameter CDRPLL_PST_RXEQ_FINE_TIMER = "0b01000010";
+ parameter CFG_A_BAR0 = "0b11111111111111110000000000001100";
+ parameter CFG_A_BAR1 = "0b11111111111111111111111111111111";
+ parameter CFG_A_BAR2 = "0b11111111111111111110000000001100";
+ parameter CFG_A_BAR3 = "0b11111111111111111111111111111111";
+ parameter CFG_A_BAR4 = "0b11111111111111111110000000001100";
+ parameter CFG_A_BAR5 = "0b11111111111111111111111111111111";
+ parameter CFG_B_BAR0 = "0b11111111111111110000000000001100";
+ parameter CFG_B_BAR1 = "0b11111111111111111111111111111111";
+ parameter CFG_B_BAR2 = "0b11111111111111111110000000001100";
+ parameter CFG_B_BAR3 = "0b11111111111111111111111111111111";
+ parameter CFG_B_BAR4 = "0b11111111111111111110000000001100";
+ parameter CFG_B_BAR5 = "0b11111111111111111111111111111111";
+ parameter CFG_C_BAR0 = "0b11111111111111110000000000001100";
+ parameter CFG_C_BAR1 = "0b11111111111111111111111111111111";
+ parameter CFG_C_BAR2 = "0b11111111111111111110000000001100";
+ parameter CFG_C_BAR3 = "0b11111111111111111111111111111111";
+ parameter CFG_C_BAR4 = "0b11111111111111111110000000001100";
+ parameter CFG_C_BAR5 = "0b11111111111111111111111111111111";
+ parameter CFG_D_BAR0 = "0b11111111111111110000000000001100";
+ parameter CFG_D_BAR1 = "0b11111111111111111111111111111111";
+ parameter CFG_D_BAR2 = "0b11111111111111111110000000001100";
+ parameter CFG_D_BAR3 = "0b11111111111111111111111111111111";
+ parameter CFG_D_BAR4 = "0b11111111111111111110000000001100";
+ parameter CFG_D_BAR5 = "0b11111111111111111111111111111111";
+ parameter CFG_EXP_ROM_A = "0b00000000000000000000000000000000";
+ parameter CFG_EXP_ROM_B = "0b00000000000000000000000000000000";
+ parameter CFG_EXP_ROM_C = "0b00000000000000000000000000000000";
+ parameter CFG_EXP_ROM_D = "0b00000000000000000000000000000000";
+ parameter CIS_POINTER_CARDBUS_A = "0b00000000000000000000000000000000";
+ parameter CIS_POINTER_CARDBUS_B = "0b00000000000000000000000000000000";
+ parameter CIS_POINTER_CARDBUS_C = "0b00000000000000000000000000000000";
+ parameter CIS_POINTER_CARDBUS_D = "0b00000000000000000000000000000000";
+ parameter CLASS_CODE_ID3A = "0b000100011000000000000000";
+ parameter CLASS_CODE_ID3B = "0b000100011000000000000000";
+ parameter CLASS_CODE_ID3C = "0b000100011000000000000000";
+ parameter CLASS_CODE_ID3D = "0b000100011000000000000000";
+ parameter CM_RESTORE_TIME = "0b00000000";
+ parameter CNT250NS_MAX = "0b001111100";
+ parameter COARSE_GAIN = "DISABLED";
+ parameter COEF_EN_LPBK_MASTER = "OTHERWISE";
+ parameter COEF_EN_LPBK_SLAVE = "OTHERWISE";
+ parameter COEF_ENABLE = "DETERMINE_LOCAL_PHY";
+ parameter COEF_EQTX_FORCE = "0b000000000000000000";
+ parameter COEF_LPBK_MASTER = "0b000000000000000000";
+ parameter COEF_LPBK_SLAVE = "0b000000000000000000";
+ parameter COEF0_POST = "0b000101";
+ parameter COEF0_POST_CURSOR = "0b000000";
+ parameter COEF0_PRE = "0b000000";
+ parameter COEF0_PRE_CURSOR = "0b000000";
+ parameter COEF1_POST = "0b000011";
+ parameter COEF1_POST_CURSOR = "0b000000";
+ parameter COEF1_PRE = "0b000000";
+ parameter COEF1_PRE_CURSOR = "0b000000";
+ parameter COEF10_POST = "0b000111";
+ parameter COEF10_PRE = "0b000000";
+ parameter COEF2_POST = "0b000100";
+ parameter COEF2_POST_CURSOR = "0b000000";
+ parameter COEF2_PRE = "0b000000";
+ parameter COEF2_PRE_CURSOR = "0b000000";
+ parameter COEF3_POST = "0b000010";
+ parameter COEF3_POST_CURSOR = "0b000000";
+ parameter COEF3_PRE = "0b000000";
+ parameter COEF3_PRE_CURSOR = "0b000000";
+ parameter COEF4_POST = "0b000000";
+ parameter COEF4_PRE = "0b000000";
+ parameter COEF5_POST = "0b000000";
+ parameter COEF5_PRE = "0b000001";
+ parameter COEF6_POST = "0b000000";
+ parameter COEF6_PRE = "0b000010";
+ parameter COEF7_POST = "0b000100";
+ parameter COEF7_PRE = "0b000011";
+ parameter COEF8_POST = "0b000011";
+ parameter COEF8_PRE = "0b000010";
+ parameter COEF9_POST = "0b000000";
+ parameter COEF9_PRE = "0b000011";
+ parameter COMP_128_SUPPORTED = "ENABLED";
+ parameter COMP_32_SUPPORTED = "ENABLED";
+ parameter COMP_64_SUPPORTED = "ENABLED";
+ parameter COMPLETE = "DISABLED";
+ parameter CONV_METHOD = "COMPUTE_PCIE_SPEC";
+ parameter CORE_BYPASS = "NORMAL";
+ parameter CORE_EN = "ENABLED";
+ parameter COUNT_ACK_TO_NAK = "0b00000000";
+ parameter CPL_TIMEOUT_DISABLE_SUPPORTED = "SUPPORTED";
+ parameter CPL_TIMEOUT_RANGES_SUPPORTED = "NOT_SUPPORTED";
+ parameter CRS_ENABLE = "DISABLED";
+ parameter CSTAT_DATA_SCALE = "UNKNOWN_SCALE";
+ parameter CSTAT_DATA_SELECT = "D0_POWER_CONSUMED";
+ parameter CTLE_SETTLE = "0b100";
+ parameter CTLEBIAS_1 = "0b1000";
+ parameter ATXICP_RATE2 = "0b100";
+ parameter CTLEBYPASS = "DISABLED";
+ parameter CUR_FOM = "NUMBER_OF_CLOCK";
+ parameter CUR_FOM_AVG = "0b101";
+ parameter CUST_AUTO = "DISABLED";
+ parameter CUST_CHK = "SET";
+ parameter CUST_SEL = "DISABLED";
+ parameter CUST_SKIP = "DISABLED";
+ parameter CUST_TYP = "0b000";
+ parameter CUSTOM_PATTERN = "0b00000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ parameter D1_SUPPORT = "SUPPORTED";
+ parameter D2_SUPPORT = "SUPPORTED";
+ parameter DATA_INJECT = "0b00000000000000000000000000000000";
+ parameter DATA_PM = "0b00000000";
+ parameter DEEMPH_5G_3_5DB_6DB_N = "6DB";
+ parameter DEEMPH_5G_ENABLE = "DISABLED";
+ parameter DEEMPH_LPBK_MASTER = "6P0DB";
+ parameter DEEMPH_LPBK_SLAVE = "6P0DB";
+ parameter DEVICE_ID_ID1A = "0b1110000000000100";
+ parameter DEVICE_ID_ID1B = "0b1110000000000100";
+ parameter DEVICE_ID_ID1C = "0b1110000000000100";
+ parameter DEVICE_ID_ID1D = "0b1110000000000100";
+ parameter DEVICE_PORT_TYPE = "PCIE_ENDPOINT";
+ parameter DFE_BIAS = "0b0001";
+ parameter DFE_PWDN = "DISABLED";
+ parameter DIR_PRE_GAIN = "0b00";
+ parameter DIR_PST_GAIN = "0b01";
+ parameter DIS_ARI_CAP = "ENABLED";
+ parameter DIS_CSR_RST = "DISABLED";
+ parameter DIS_INTERRUPT = "ENABLED";
+ parameter DIS_INTERRUPT_B = "ENABLED";
+ parameter DIS_INTERRUPT_C = "ENABLED";
+ parameter DIS_INTERRUPT_D = "ENABLED";
+ parameter DIS_MSI_CAP = "ENABLED";
+ parameter DIS_MSI_CAP_B = "ENABLED";
+ parameter DIS_MSI_CAP_C = "ENABLED";
+ parameter DIS_MSI_CAP_D = "ENABLED";
+ parameter DIS_MSIX_CAP = "ENABLED";
+ parameter DIS_MSIX_CAP_B = "ENABLED";
+ parameter DIS_MSIX_CAP_C = "ENABLED";
+ parameter DIS_MSIX_CAP_D = "ENABLED";
+ parameter DISABLE_FLR_CAPABILITY = "ENABLED";
+ parameter DLLP_CRC_ERR_ENABLE = "DISABLED";
+ parameter DLLP_CRC_ERR_RATE = "0b000000000000";
+ parameter DLLP_INJECT_ENABLE = "DISABLED";
+ parameter DOUBLE_TX_DATA_VALID = "ONE_CLK_EVERY_64_CLKS";
+ parameter DOWNSTREAM_EQ_SKIP_PHASE_2_3 = "NORMAL_OPERATION";
+ parameter DS_DRIVE_CLKREQ = "ENABLED";
+ parameter DS_PORT_RX_PRESET_HINT = "0b001";
+ parameter DS_PORT_TX_PRESET = "0b0011";
+ parameter DS_US_N_PORTTYPE = "UPSTREAM";
+ parameter DSI = "NO_DSI_NECESSARY";
+ parameter DSP_DIR = "ANALYSIS_OF_DATA_BY_DSP";
+ parameter DSPDIR_PRESGN = "0b11110000";
+ parameter DSPDIR_PREVAL = "0b00011000";
+ parameter DSPDIR_PSTSGN0 = "0b11111111";
+ parameter DSPDIR_PSTSGN1 = "0b00000000";
+ parameter DSPDIR_PSTVAL0 = "0b00000010";
+ parameter DSPDIR_PSTVAL1 = "0b01000000";
+ parameter EARLY_RX_EVAL = "RX_SIGNAL_AFTER_TS1";
+ parameter ECRC_GEN_CHK_CAPABLE = "SUPPORTED";
+ parameter EFF_LPBK = "PASSED";
+ parameter EI4 = "EI_IV";
+ parameter EM_INTERLOCK_PRESENT = "NOT_SUPPORTED";
+ parameter EN = "DISABLED";
+ parameter EN_ACK_TO_DIV = "ACK_SPEC";
+ parameter EN_ACK_TO_NAK = "DO_NOTHING";
+ parameter EN_ACS_VIOLATION = "DISABLED";
+ parameter EN_ASPM_L0S = "ENABLED";
+ parameter EN_ASPM_L1 = "ENABLED";
+ parameter EN_ATOMIC_OP_CAP = "ENABLED";
+ parameter EN_ATOMICOP_EGRESS_BLOCKED = "DISABLED";
+ parameter EN_ATS_CAP = "ENABLED";
+ parameter EN_BDGT_CAP = "DISABLED";
+ parameter EN_CAP = "ENABLED";
+ parameter EN_CAP_B = "ENABLED";
+ parameter EN_CAP_C = "ENABLED";
+ parameter EN_CAP_D = "ENABLED";
+ parameter EN_COMPLETER_ABORT = "DISABLED";
+ parameter EN_COMPLETION_TIMEOUT = "ENABLED";
+ parameter EN_CORR_INTERNAL_ERROR = "DISABLED";
+ parameter EN_DPA_CAP = "DISABLED";
+ parameter EN_DRCT_SCR_OFF = "OTHERWISE";
+ parameter EN_DRCT_TO_LPBK = "OTHERWISE";
+ parameter EN_EQTX_OVERRIDE = "PIPE_LOCAL_FS_AND_PIPE_LOCAL_LF";
+ parameter EN_FORCE_SCR_OFF_FAST = "OTHERWISE";
+ parameter EN_L1 = "ENABLED";
+ parameter EN_L1PMSS_CAP = "ENABLED";
+ parameter EN_L2 = "ENABLED";
+ parameter EN_LPBK_ERR_RST = "MASTER_LPBK_INCREMENT";
+ parameter EN_LTR_CAP = "ENABLED";
+ parameter EN_MC_BLOCKED_TLP = "DISABLED";
+ parameter EN_NWL_VSEC_CAP = "ENABLED";
+ parameter EN_PORT_DIS = "DISABLED";
+ parameter EN_PORT_INTLEG = "ENABLED";
+ parameter EN_RBAR_CAP_A = "ENABLED";
+ parameter EN_RBAR_CAP_B = "ENABLED";
+ parameter EN_RBAR_CAP_C = "ENABLED";
+ parameter EN_RBAR_CAP_D = "ENABLED";
+ parameter EN_RECEIVER_OVERFLOW = "DISABLED";
+ parameter EN_SELF_XLINK = "OTHERWISE";
+ parameter EN_SURPRISE_DOWN_ERROR = "DISABLED";
+ parameter EN_TLP_PREFIX_BLOCKED = "DISABLED";
+ parameter EN_UCORR_INTERNAL_ERROR = "DISABLED";
+ parameter EN_USER_WRITE = "READ_WRITE_ACCESS";
+ parameter END_END_PREFIXES_SUPPORTED = "NOT_SUPPORTED";
+ parameter END_ON_HOLD = "YES_EXIT_ON_HOLD";
+ parameter ENDCALIB_MAX = "0b10000100";
+ parameter ENDPOINT_L0S_ACCEPTABLE_LATENCY = "MAX_64_NS";
+ parameter ENDPOINT_L1_ACCEPTABLE_LATENCY = "MAX_1_US";
+ parameter ENTRY_TIME_ASPM_L0S = "0b0000000000000000";
+ parameter ENTRY_TIME_ASPM_L1 = "0b0000000000000000";
+ parameter EOM_TIME = "0b0000000000000000";
+ parameter EOM0DIR = "SELECT_DIR_1";
+ parameter EOM1DIR = "SELECT_DIR_0";
+ parameter EOMCTRL0_LOW = "DISABLED";
+ parameter EOMDIVDIS = "DISABLED";
+ parameter EOMMODE = "0b00";
+ parameter EOMRDSEL = "DISABLED";
+ parameter EOMSTART = "DISABLED";
+ parameter EOMX = "0b000000";
+ parameter EOMX_UPDATE_CNT_VALUE = "0b0011111";
+ parameter EOMY = "0b00000000";
+ parameter ERRCNT_DEC = "0b00100000";
+ parameter ERRCNT_THR = "0b1000";
+ parameter ES_PWDN = "DISABLED";
+ parameter EVAL_RST = "DISABLED";
+ parameter EXCLUDE_L0 = "INCLUDE";
+ parameter EXCLUDE_CFG_COMPLETE = "INCLUDE";
+ parameter EXCLUDE_CFG_IDLE = "INCLUDE";
+ parameter EXCLUDE_LOOPBACK_MASTER = "INCLUDE";
+ parameter EXCLUDE_REC_IDLE = "INCLUDE";
+ parameter EXCLUDE_REC_RCVR_CFG = "INCLUDE";
+ parameter EXIT_DIRECT_TO_DETECT = "DO_NOT_EXIT_TO_DETECT";
+ parameter EXT_CONTROL = "DISABLED";
+ parameter EXTENDED_TAG_FIELD_EN_DEFAULT = "EIGHT_BIT";
+ parameter EXTENDED_TAG_FIELD_SUPPORTED = "EIGHT_BIT";
+ parameter F_ARXCTLEDIR = "IGNORED";
+ parameter F_ARXCTLENULL = "0b0000";
+ parameter F_ARXDMDIR = "DISABLED";
+ parameter F_ARXDMNULL = "0b00000";
+ parameter F_ARXEOMDIR = "IGNORED";
+ parameter F_ARXEOMNULL = "0b00000";
+ parameter F_ARXESDIR = "IGNORED";
+ parameter F_ARXESNULL = "0b00000";
+ parameter F_ARXTDIR = "IGNORED";
+ parameter F_ARXTNULL = "0b00000";
+ parameter F_ASCHCAL = "IGNORED";
+ parameter F_ASCHDIR = "IGNORED";
+ parameter F_ASCHNULL = "0b0000";
+ parameter FAIL_LIMIT_ERR = "RXEQ_NOT_FAIL";
+ parameter FAST = "L0";
+ parameter FC_UPDATE_TIMER_DISABLE = "ENABLED";
+ parameter FC_UPDATE_TIMER_DIV = "PCIE_REC_VALUES";
+ parameter FILTER = "0b1001";
+ parameter FINE_GAIN = "DISABLED";
+ parameter FOM_COMPARE = "0b00000000";
+ parameter FOM_HIRES = "DISABLED";
+ parameter FOM_ITERCNT = "0b101";
+ parameter FOM_THR = "0b0100";
+ parameter FORCE_ATXDRA = "0b000000000000000000000";
+ parameter FORCE_ATXDRP = "0b000000000000000000000";
+ parameter FORCE_ATXDRR = "0b000000000000000000000";
+ parameter FORCE_ATXDRT = "0b000000000000000000000";
+ parameter FORCE_DIR_RSLT = "0b000000";
+ parameter FORCE_FOM_RSLT = "0b00000000";
+ parameter FORCE_IDLE = "DISABLED";
+ parameter FORCE_RX_DETECT = "DISABLED";
+ parameter FORCE_SIGNAL = "DISABLED";
+ parameter FREQ_LOCK = "DISABLED";
+ parameter FS = "0b110000";
+ parameter GAIN_TIMER1 = "0b0101";
+ parameter GEN12_ENA_POST_A0 = "DISABLED";
+ parameter GEN12_ENA_POST_A1A2 = "DISABLED";
+ parameter GEN12_ENA_PREA0 = "DISABLED";
+ parameter GEN3_ENA_POST_A0 = "ENABLED";
+ parameter GEN3_ENA_POST_A1A2 = "ENABLED";
+ parameter GEN3_ENA_PREA0 = "ENABLED";
+ parameter GLOBAL_INVAL_SUPPORT = "ENABLED";
+ parameter HINT = "0b000";
+ parameter HINT0_3DB = "ENABLED";
+ parameter HINT0_A0GAIN = "0b111";
+ parameter HINT0_A2GAIN = "0b111";
+ parameter HINT1_3DB = "ENABLED";
+ parameter HINT1_A0GAIN = "0b011";
+ parameter HINT1_A2GAIN = "0b101";
+ parameter HINT2_3DB = "ENABLED";
+ parameter HINT2_A0GAIN = "0b011";
+ parameter HINT2_A2GAIN = "0b111";
+ parameter HINT3_3DB = "ENABLED";
+ parameter HINT3_A0GAIN = "0b000";
+ parameter HINT3_A2GAIN = "0b111";
+ parameter HINT4_3DB = "DISABLED";
+ parameter HINT4_A0GAIN = "0b111";
+ parameter HINT4_A2GAIN = "0b111";
+ parameter HINT5_3DB = "DISABLED";
+ parameter HINT5_A0GAIN = "0b011";
+ parameter HINT5_A2GAIN = "0b101";
+ parameter HINT6_3DB = "DISABLED";
+ parameter HINT6_A0GAIN = "0b011";
+ parameter HINT6_A2GAIN = "0b111";
+ parameter HINT7_3DB = "DISABLED";
+ parameter HINT7_A0GAIN = "0b000";
+ parameter HINT7_A2GAIN = "0b111";
+ parameter HINT7_OVR = "DISABLED";
+ parameter HLD_RST = "WRITE_1";
+ parameter HOT_PLUG_CAPABLE = "NOT_SUPPORTED";
+ parameter HOT_PLUG_SURPRISE = "NOT_POSSIBLE";
+ parameter ID_DS_PORT = "0b0000000000000000";
+ parameter ID_NWL_VSEC_CAP = "0b0000000000000001";
+ parameter IGNORE_ECRC = "DISABLED";
+ parameter IGNORE_POISON = "ENABLED";
+ parameter INDICATOR = "0b00000000000000000000000000000000";
+ parameter INHIBIT = "PERFORM_RECEIVER_DETECTION";
+ parameter INJECT_DATA_ERROR_0 = "DISABLED";
+ parameter INJECT_DATA_ERROR_1 = "DISABLED";
+ parameter INJECT_DATA_ERROR_2 = "DISABLED";
+ parameter INJECT_DATA_ERROR_3 = "DISABLED";
+ parameter INJECT_DATA_ERROR_EN = "DISABLED";
+ parameter INJECT_ERR_LANE_SELECT_0 = "DISABLED";
+ parameter INJECT_ERR_LANE_SELECT_1 = "DISABLED";
+ parameter INJECT_ERR_LANE_SELECT_2 = "DISABLED";
+ parameter INJECT_ERR_LANE_SELECT_3 = "DISABLED";
+ parameter INJECT_RX_1BIT_DATA_ERR = "DISABLED";
+ parameter INJECT_RX_2BIT_DATA_ERR = "DISABLED";
+ parameter INJECT_RX_SKP_ERR = "DISABLED";
+ parameter INJECT_RX_VALID_ERR = "DISABLED";
+ parameter INT_CLR = "DISABLED";
+ parameter INT_EN = "DISABLED";
+ parameter INTERRUPT_MESSAGE_NUMBER = "0b00000";
+ parameter INVAL_Q_DEPTH = "0b00000";
+ parameter ITERATION_MAX = "0b000000";
+ parameter L1_ENTER_PLL_RESET_TIME = "0b100";
+ parameter L1_EXIT_PLL_LOCK_TIME = "0b01110";
+ parameter L1PM_SUPPORTED = "SUPPORTED";
+ parameter L2_D3HOT_ENABLE = "DISABLED";
+ parameter LANE_SELECT = "0b0000";
+ parameter LF = "0b001000";
+ parameter LF_PHY = "0b001010";
+ parameter LINK_LANE = "ENABLED";
+ parameter LPBK_EN = "DISABLED";
+ parameter LW_START_UPDN_ACK_EN = "DISABLED";
+ parameter LW_START_UPDN_COUNT = "0b000011111010";
+ parameter LW_START_UPDN_EIE_EN = "DISABLED";
+ parameter LW_START_UPDN_EN_DIR_DS = "DO_NOT_ASSERT";
+ parameter LW_START_UPDN_END_DELAY = "0b1001";
+ parameter LW_START_UPDN_RATE_EN_16G = "DISABLED";
+ parameter LW_START_UPDN_RATE_EN_2P5G = "ENABLED";
+ parameter LW_START_UPDN_RATE_EN_5G = "ENABLED";
+ parameter LW_START_UPDN_RATE_EN_8G = "ENABLED";
+ parameter LW_START_UPDN_START_DELAY = "0b1000";
+ parameter LW_START_UPDN_TIMER_EN = "DISABLED";
+ parameter MARGIN_ENABLE = "PCIE_SPEC";
+ parameter MARGIN_VALUE = "0b000";
+ parameter MASK_0 = "SKIP_RCVR_DETECTION";
+ parameter MASK_1 = "SKIP_RCVR_DETECTION";
+ parameter MASK_2 = "SKIP_RCVR_DETECTION";
+ parameter MASK_3 = "SKIP_RCVR_DETECTION";
+ parameter MAX_LINK_WIDTH = "1_LANE";
+ parameter MAX_SPEED = "8G";
+ parameter MAX_VAR = "0b00100";
+ parameter MERGE_LMMI_RDATA = "DISABLED";
+ parameter METHOD_FMERIT_CTRL = "STEP_PCIE_TX_PRESETS";
+ parameter METHOD_TX_CRED_CLEANUP = "HEADER";
+ parameter MGMT_INTLEG = "0b0000";
+ parameter MGMT_LTSSM_DIS = "DISABLED";
+ parameter MID_VALUE_20B = "0b010100";
+ parameter MID_VALUE_GEN3 = "0b001110";
+ parameter MIN_SPEED = "2P5G";
+ parameter MIN_TIME = "0_MS";
+ parameter MIN_TIME_CFG = "4US";
+ parameter MIX_DIR = "DISABLED";
+ parameter MODE_BFF = "RESTART";
+ parameter MRL_SENSOR_PRESENT = "NOT_SUPPORTED";
+ parameter MULT_ENABLE = "RECOMMENDED_VALUES";
+ parameter MULT_MESSAGE_CAPABLE_MSICAP_A = "EIGHT";
+ parameter MULT_MESSAGE_CAPABLE_MSICAP_B = "EIGHT";
+ parameter MULT_MESSAGE_CAPABLE_MSICAP_C = "EIGHT";
+ parameter MULT_MESSAGE_CAPABLE_MSICAP_D = "EIGHT";
+ parameter NFTS = "0b11111111";
+ parameter NO_COMMAND_COMPLETED_SUPPORT = "SW_NOTIF_PROVIDED";
+ parameter NO_FCMP = "DISABLED";
+ parameter NO_REMOTE_CHANGE = "DISABLED";
+ parameter NO_TX_IDLE_DELAY = "DATA_VALID_GAP";
+ parameter NUM_LANES = "1_LANE";
+ parameter NUMBER_DSLINK = "0b00000";
+ parameter NUMHI_A = "0b00000000000000000000000000000000";
+ parameter NUMHI_B = "0b00000000000000000000000000000000";
+ parameter NUMHI_C = "0b00000000000000000000000000000000";
+ parameter NUMHI_D = "0b00000000000000000000000000000000";
+ parameter NUMHOLD = "SINGLE_HOLD_RESPONSE";
+ parameter NUMLO_A = "0b00000000000000000000000000000000";
+ parameter NUMLO_B = "0b00000000000000000000000000000000";
+ parameter NUMLO_C = "0b00000000000000000000000000000000";
+ parameter NUMLO_D = "0b00000000000000000000000000000000";
+ parameter OBFF_SUPPORTED = "NOT_SUPPORTED";
+ parameter OFFSET_MSIX_PBA_A = "0b00000000000000000111000000000";
+ parameter OFFSET_MSIX_PBA_B = "0b00000000000000000111000000000";
+ parameter OFFSET_MSIX_PBA_C = "0b00000000000000000111000000000";
+ parameter OFFSET_MSIX_PBA_D = "0b00000000000000000111000000000";
+ parameter OFFSET_MSIX_TABLE_A = "0b00000000000000000110000000000";
+ parameter OFFSET_MSIX_TABLE_B = "0b00000000000000000110000000000";
+ parameter OFFSET_MSIX_TABLE_C = "0b00000000000000000110000000000";
+ parameter OFFSET_MSIX_TABLE_D = "0b00000000000000000110000000000";
+ parameter OVER_CTLE = "DISABLED";
+ parameter OVER_RX = "DISABLED";
+ parameter OVER_RXDM = "DISABLED";
+ parameter OVER_RXDP = "DISABLED";
+ parameter OVER_RXES = "DISABLED";
+ parameter OVER_RXT = "DISABLED";
+ parameter OVER_SCH = "DISABLED";
+ parameter OVER_TX = "DISABLED";
+ parameter OVERRIDE = "DISABLED";
+ parameter OVR_CDR = "DISABLED";
+ parameter OVR_DIR = "DISABLED";
+ parameter OVR_FOM = "DISABLED";
+ parameter OVR_GAIN3DB = "ENABLED";
+ parameter OVR_HINT3DB = "ENABLED";
+ parameter P_CLK_PERIOD = "0b0000111110100000";
+ parameter PAR_LPBK = "DISABLED";
+ parameter PAS = "10X";
+ parameter PATTERN_0 = "UNSCRAMBLED";
+ parameter PATTERN_1 = "UNSCRAMBLED";
+ parameter PATTERN_2 = "UNSCRAMBLED";
+ parameter PCIPM_L1_1_SUPPORTED = "SUPPORTED";
+ parameter PCIPM_L1_2_SUPPORTED = "SUPPORTED";
+ parameter PERIOD_SRIS_128B130B = "0b000000";
+ parameter PERIOD_SRIS_8B10B = "0b00000000";
+ parameter PERIOD_SRNS_128B130B = "0b00000000";
+ parameter PERIOD_SRNS_8B10B = "0b00000000";
+ parameter PHANTOM_FUNCTIONS_SUPPORTED = "NO_FUNCTION_BITS";
+ parameter PHYSICAL_SLOT_NUMBER = "0b0000000000001";
+ parameter PIN_INTERRUPT_A = "INTA";
+ parameter PIN_INTERRUPT_B = "INTA";
+ parameter PIN_INTERRUPT_C = "INTA";
+ parameter PIN_INTERRUPT_D = "INTA";
+ parameter PIPE_TX_SWING = "FULL_SWING";
+ parameter PLESIO_LPBK = "DISABLED";
+ parameter PM_REDUCE_TIMEOUTS = "DISABLED";
+ parameter PMA_DRIVEN_MODE = "PCS_DRIVEN";
+ parameter PMCSR_B2_B3_SUPPORT = "DISABLED";
+ parameter PMCSR_BUS_P_C_EN = "DISABLED";
+ parameter PME_CLOCK = "DISABLED";
+ parameter PME_SUPPORT = "0b11111";
+ parameter PMFF_ALL = "DISABLED";
+ parameter PORT_CM_RESTORE_TIME = "0b00000000";
+ parameter PORT_NUMBER = "0b00000000";
+ parameter PORT_TPOWER_ON_SCALE = "2_US";
+ parameter PORT_TPOWER_ON_VALUE = "0b00000";
+ parameter POST = "0b000000";
+ parameter POST_A0COEF = "0b001";
+ parameter POST_A1COEF = "0b001";
+ parameter POST_A2COEF = "0b001";
+ parameter POST_CURSOR_LIMIT = "0b100000";
+ parameter POST_CURSOR_STEP_SIZE = "0b001000";
+ parameter POST_ITERCNT = "0b100";
+ parameter POST_STEP = "STEP_SIZE_4";
+ parameter POWER_CONTROLLER_PRESENT = "NOT_SUPPORTED";
+ parameter POWER_INDICATOR_PRESENT = "NOT_SUPPORTED";
+ parameter POWER_REQUIRED = "AUX_POWER_NOT_REQUIRED";
+ parameter PRBS_CHK = "DISABLED";
+ parameter PRBS_GEN = "DISABLED";
+ parameter PRBS_TYP = "PRBS7";
+ parameter PRE = "0b000000";
+ parameter PRE_A0COEF = "0b101";
+ parameter PRE_A1COEF = "0b101";
+ parameter PRE_A2COEF = "0b101";
+ parameter PRE_CURSOR_LIMIT = "0b010000";
+ parameter PRE_CURSOR_STEP_SIZE = "0b000100";
+ parameter PRE_FOM = "ENABLED";
+ parameter PRE_FOM_AVG = "0b100";
+ parameter PRE_ITERCNT = "0b100";
+ parameter PRE_RXEQ_TIMER = "0b00010100";
+ parameter PRE_STEP = "STEP_SIZE_2";
+ parameter PRESET_COUNT_INI = "0b0000";
+ parameter PRESET_EN_LPBK_MASTER = "OTHERWISE";
+ parameter PRESET_EN_LPBK_SLAVE = "OTHERWISE";
+ parameter PRESET_ENABLE = "NORMAL_OP";
+ parameter PRESET_EQTX_FORCE = "0b0000";
+ parameter PRESET_LPBK_MASTER = "0b0000";
+ parameter PRESET_LPBK_SLAVE_0 = "OTHERWISE";
+ parameter PRESET_LPBK_SLAVE_1 = "OTHERWISE";
+ parameter PRESET_LPBK_SLAVE_2 = "OTHERWISE";
+ parameter PRESET_LPBK_SLAVE_3 = "OTHERWISE";
+ parameter PRESET_REJECT = "0b00000000000";
+ parameter PRESET0_POSTCURSOR = "0b1000";
+ parameter PRESET0_PRECURSOR = "0b0000";
+ parameter PRESET1_POSTCURSOR = "0b0101";
+ parameter PRESET1_PRECURSOR = "0b0000";
+ parameter PRESET10_POSTCURSOR = "0b1010";
+ parameter PRESET10_PRECURSOR = "0b0000";
+ parameter PRESET2_POSTCURSOR = "0b0110";
+ parameter PRESET2_PRECURSOR = "0b0000";
+ parameter PRESET3_POSTCURSOR = "0b0100";
+ parameter PRESET3_PRECURSOR = "0b0000";
+ parameter PRESET4_POSTCURSOR = "0b0000";
+ parameter PRESET4_PRECURSOR = "0b0000";
+ parameter PRESET5_POSTCURSOR = "0b0000";
+ parameter PRESET5_PRECURSOR = "0b0011";
+ parameter PRESET6_POSTCURSOR = "0b0000";
+ parameter PRESET6_PRECURSOR = "0b0100";
+ parameter PRESET7_POSTCURSOR = "0b0110";
+ parameter PRESET7_PRECURSOR = "0b0011";
+ parameter PRESET8_POSTCURSOR = "0b0100";
+ parameter PRESET8_PRECURSOR = "0b0100";
+ parameter PRESET9_POSTCURSOR = "0b0000";
+ parameter PRESET9_PRECURSOR = "0b0101";
+ parameter PS_REENTRY_TIME = "0b00000000";
+ parameter RATE = "2P5G";
+ parameter RATE_ENABLE = "INITIAL_SPEED_CHANGES";
+ parameter RCB = "DISABLED";
+ parameter REC_SPD_INFER_EQ_PH0123 = "EXCLUDE_TIME_SPENT";
+ parameter REC_SPD_INFER_RCVR_CFG = "EXCLUDE_TIME_SPENT";
+ parameter REC_SPD_INFER_RCVR_LOCK = "EXCLUDE_TIME_SPENT";
+ parameter DIS_FUNC_B = "ENABLED";
+ parameter DIS_FUNC_C = "ENABLED";
+ parameter DIS_FUNC_D = "ENABLED";
+ parameter REDUCE_TIMEOUTS_LTSSMSIM = "DISABLED";
+ parameter REDUCE_TIMEOUTS_SIM = "DISABLED";
+ parameter REDUCE_TS1 = "DISABLED";
+ parameter REENTRY_DISABLE = "ENABLED";
+ parameter REENTRY_TIME = "0b00000000000000";
+ parameter REQ_FEEDBACK = "0b00000000";
+ parameter RESET_EIEOS_INTERVAL_COUNT = "DISABLED";
+ parameter REVISION_ID_ID3A = "0b00000100";
+ parameter REVISION_ID_ID3B = "0b00000100";
+ parameter REVISION_ID_ID3C = "0b00000100";
+ parameter REVISION_ID_ID3D = "0b00000100";
+ parameter RL1 = "0b0011";
+ parameter RL2 = "0b0101";
+ parameter RL3 = "0b0011";
+ parameter ROUTING_SUPPORTED = "DISABLED";
+ parameter RP_COMPLETER_EN = "DISABLED";
+ parameter RSTCDR_ERR = "ENABLED";
+ parameter RSTCDR_FRQ = "ENABLED";
+ parameter RSTCDR_IDL = "DISABLED";
+ parameter RX_BYPASS_DECODE_EN = "ENABLED";
+ parameter RX_BYPASS_MSG_DEC = "NORMAL_OPERATION";
+ parameter RX_CONVERT_UR_TO_CA = "NORMAL_OPERATION";
+ parameter RX_D_ALLOC_C = "0b0000000001100000";
+ parameter RX_D_ALLOC_N = "0b0000000000000110";
+ parameter RX_D_ALLOC_P = "0b0000000001101100";
+ parameter RX_DIV_MODE1 = "0b10";
+ parameter RX_DIV_MODE0 = "DIV_2";
+ parameter RX_DIV_MODE2 = "0b00";
+ parameter RX_DL_ACTIVE_DISABLE = "BLOCK_RECEPTION_TLP";
+ parameter RX_EARLY_FORWARD_DISABLE = "FWD_RX_DATA_LL";
+ parameter RX_ERR_COR = "DISABLED";
+ parameter RX_ERR_UCOR = "DISABLED";
+ parameter RX_FORCE_RO = "DISABLED";
+ parameter RX_H_ALLOC_C = "0b000000100000";
+ parameter RX_H_ALLOC_N = "0b000000001000";
+ parameter RX_H_ALLOC_P = "0b000000010000";
+ parameter RX_HIZ = "IGNORED";
+ parameter RX_IMPED_RATIO = "0b10000000";
+ parameter RX_INHIBIT_ACK_NAK = "PROCESS_RCVD_ACK";
+ parameter RX_INHIBIT_TLP = "PROCESS_RCVD_TLP";
+ parameter RX_LCRC_INJECT_EN = "DO_NOT_INJECT_ERROR";
+ parameter RX_MALF_INJECT_EN = "DO_NOT_INJECT_ERROR";
+ parameter RX_POLINV = "NORMAL";
+ parameter RX_PRIORITY = "DISABLED";
+ parameter RX_PRIORITY_N_STARVE_THRESH = "0b00010000";
+ parameter RX_PRIORITY_P_STARVE_THRESH = "0b00010000";
+ parameter RX_PWRDN = "IGNORED";
+ parameter RX_TLP_VALID = "DISABLED";
+ parameter RXEQ_ALGO = "0b111";
+ parameter RXEQ_ENABLE = "0b100";
+ parameter RXEQ_EVAL_MAX = "0b11111111";
+ parameter RXEQ_MANUAL = "DISABLED";
+ parameter RXEQ_STATE = "0b0000";
+ parameter RXF_A = "0b0100";
+ parameter RXF_B = "0b0100";
+ parameter RXF_C = "0b0100";
+ parameter RXHF_CLKDN = "ENABLED";
+ parameter RXIDLE_MAX = "0b1111";
+ parameter RXIDLE_MAX2 = "0b0000010000000000";
+ parameter RXIDLE_MSB = "0b11";
+ parameter RXM_A = "0b10";
+ parameter RXM_B = "0b01";
+ parameter RXM_C = "0b00";
+ parameter RXN_A = "0b00100";
+ parameter RXN_B = "0b01001";
+ parameter RXN_C = "0b01111";
+ parameter RXOFF_SETTLE_MAX = "0b011";
+ parameter RXOFF_STABLE_MAX = "0b10000";
+ parameter RXPLLINIT = "DISABLED";
+ parameter RXPLLRST = "SET";
+ parameter SELECT_DIR_FOM_N = "FME_METHOD";
+ parameter SELECTABLE_DEEMPHASIS = "6P0DB";
+ parameter SEQ_NUM = "0b000000000000";
+ parameter SIGNAL_DETECT_THRESHOLD = "125_MV";
+ parameter SIZE_CFG0_A = "0b00000";
+ parameter SIZE_CFG0_B = "0b00000";
+ parameter SIZE_CFG0_C = "0b00000";
+ parameter SIZE_CFG0_D = "0b00000";
+ parameter SIZE_CFG1_A = "0b00000";
+ parameter SIZE_CFG1_B = "0b00000";
+ parameter SIZE_CFG1_C = "0b00000";
+ parameter SIZE_CFG1_D = "0b00000";
+ parameter SIZE_CFG2_A = "0b00000";
+ parameter SIZE_CFG2_B = "0b00000";
+ parameter SIZE_CFG2_C = "0b00000";
+ parameter SIZE_CFG2_D = "0b00000";
+ parameter SIZE_CFG3_A = "0b00000";
+ parameter SIZE_CFG3_B = "0b00000";
+ parameter SIZE_CFG3_C = "0b00000";
+ parameter SIZE_CFG3_D = "0b00000";
+ parameter SIZE_CFG4_A = "0b00000";
+ parameter SIZE_CFG4_B = "0b00000";
+ parameter SIZE_CFG4_C = "0b00000";
+ parameter SIZE_CFG4_D = "0b00000";
+ parameter SIZE_CFG5_A = "0b00000";
+ parameter SIZE_CFG5_B = "0b00000";
+ parameter SIZE_CFG5_C = "0b00000";
+ parameter SIZE_CFG5_D = "0b00000";
+ parameter SKIP_FINAL_COEF_CHECK = "DISABLED";
+ parameter SLOT_CLOCK_CONFIGURATION = "REFCLK_BY_SLOT";
+ parameter SLOT_IMPLEMENTED = "UNCONNECTED";
+ parameter SLOT_POWER_LIMIT_SCALE = "0b00";
+ parameter SLOT_POWER_LIMIT_VALUE = "0b00001010";
+ parameter SPEED_LPBK_CTRL = "2P5G";
+ parameter START_PRESET = "PRESET_VALUE";
+ parameter START_REMOTE_ADV = "OTHERWISE";
+ parameter STATE_DATA_N = "USE_RX_DATA_OBSERVATION";
+ parameter STEP_SELECT = "0b00000";
+ parameter STP_OVERRIDE_EN = "DISABLED";
+ parameter STP_OVERRIDE_LEN = "0b00000000000";
+ parameter STP_OVERRIDE_NEW_LEN = "0b00000000000";
+ parameter SUBSTATE_MAX = "0b00000";
+ parameter SUBSYSTEM_ID_ID2A = "0b1110000000000100";
+ parameter SUBSYSTEM_ID_ID2B = "0b1110000000000100";
+ parameter SUBSYSTEM_ID_ID2C = "0b1110000000000100";
+ parameter SUBSYSTEM_ID_ID2D = "0b1110000000000100";
+ parameter SUBSYSTEM_VENDOR_ID_ID2A = "0b0001100110101010";
+ parameter SUBSYSTEM_VENDOR_ID_ID2B = "0b0001100110101010";
+ parameter SUBSYSTEM_VENDOR_ID_ID2C = "0b0001100110101010";
+ parameter SUBSYSTEM_VENDOR_ID_ID2D = "0b0001100110101010";
+ parameter SUPP_SIZE_CFG0_A = "0b00000000000000001111";
+ parameter SUPP_SIZE_CFG0_B = "0b00000000000000001111";
+ parameter SUPP_SIZE_CFG0_C = "0b00000000000000001111";
+ parameter SUPP_SIZE_CFG0_D = "0b00000000000000001111";
+ parameter SUPP_SIZE_CFG1_A = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG1_B = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG1_C = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG1_D = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG2_A = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG2_B = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG2_C = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG2_D = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG3_A = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG3_B = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG3_C = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG3_D = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG4_A = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG4_B = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG4_C = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG4_D = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG5_A = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG5_B = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG5_C = "0b00000000000000000000";
+ parameter SUPP_SIZE_CFG5_D = "0b00000000000000000000";
+ parameter SYS_ALLOC = "PWR_BUDGET_CAP_VALUES";
+ parameter T0_RX_BYPASS_MSG_DEC = "NORMAL_OPERATION";
+ parameter TABLE_SIZE_MSIXCAP_A = "0b00000000111";
+ parameter TABLE_SIZE_MSIXCAP_B = "0b00000000111";
+ parameter TABLE_SIZE_MSIXCAP_C = "0b00000000111";
+ parameter TABLE_SIZE_MSIXCAP_D = "0b00000000111";
+ parameter TARGET_LINK_SPEED = "8G";
+ parameter TARGET_ONLY = "DISABLED";
+ parameter TD1_MEANS_ADD_HAS_N = "ECRC_CONTAINED";
+ parameter TIMEOUT_THRESHOLD_PME = "0b000000000000";
+ parameter TIMEOUT_THRESHOLD_PME_TO_ACK_DS = "0b00000000";
+ parameter TIMER = "0b00000000";
+ parameter TLP_LCRC_ERR_ENABLE = "DISABLED";
+ parameter TLP_LCRC_ERR_RATE = "0b000";
+ parameter TLP_SEQ_ERR_ENABLE = "DISABLED";
+ parameter TLUNIT = "1_MS";
+ parameter TO_EXTEND = "0b01111111";
+ parameter TRNG_A0COEF = "0b101";
+ parameter TRNG_A1COEF = "0b101";
+ parameter TRNG_A2COEF = "0b101";
+ parameter TRNG_FAST = "DISABLED";
+ parameter TRNG_ITERCNT = "0b100";
+ parameter TRNG_RXEQ_TIMER = "0b00100000";
+ parameter TS1_ACK_BLOCK_USE_PRESET = "FORCED_TO_ZERO";
+ parameter TS1_ACK_DELAY = "0b00011111";
+ parameter TS1_ACK_MASK_USE_PRESET = "IGNORES_USE_PRESET";
+ parameter TX_AMP_RATIO_MARGIN0_FULL = "0b10000000";
+ parameter TX_AMP_RATIO_MARGIN0_HALF = "0b01010000";
+ parameter TX_AMP_RATIO_MARGIN1_FULL = "0b01111000";
+ parameter TX_AMP_RATIO_MARGIN1_HALF = "0b01011000";
+ parameter TX_AMP_RATIO_MARGIN2_FULL = "0b01101000";
+ parameter TX_AMP_RATIO_MARGIN2_HALF = "0b01001000";
+ parameter TX_AMP_RATIO_MARGIN3_FULL = "0b01100000";
+ parameter TX_AMP_RATIO_MARGIN3_HALF = "0b01000000";
+ parameter TX_AMP_RATIO_MARGIN4_FULL = "0b01011000";
+ parameter TX_AMP_RATIO_MARGIN4_HALF = "0b00111000";
+ parameter TX_AMP_RATIO_MARGIN5_FULL = "0b01010000";
+ parameter TX_AMP_RATIO_MARGIN5_HALF = "0b00110000";
+ parameter TX_AMP_RATIO_MARGIN6_FULL = "0b01001000";
+ parameter TX_AMP_RATIO_MARGIN6_HALF = "0b00101000";
+ parameter TX_AMP_RATIO_MARGIN7_FULL = "0b01000000";
+ parameter TX_AMP_RATIO_MARGIN7_HALF = "0b00100000";
+ parameter TX_BYPASS_DECODE_EN = "ENABLED";
+ parameter TX_BYPASS_MSG_DEC = "NORMAL_OPERATION";
+ parameter TX_COMP_RECEIVE = "DOES_NOT_ASSERT";
+ parameter TX_CONVERT_UR_TO_CA = "NORMAL_OPERATION";
+ parameter TX_D_ALLOC_C = "0b0000000001100000";
+ parameter TX_D_ALLOC_N = "0b0000000000000110";
+ parameter TX_D_ALLOC_P = "0b0000000001101100";
+ parameter TX_DIV_MODE0 = "0b10";
+ parameter TX_DIV_MODE1 = "0b10";
+ parameter TX_DIV_MODE2 = "0b10";
+ parameter TX_EQ_EVAL_CNT_SEL = "WAIT_8_CLKS";
+ parameter TX_ERR_COR = "DISABLED";
+ parameter TX_ERR_UCOR = "DISABLED";
+ parameter TX_FORCE_RO = "DISABLED";
+ parameter TX_GAP_INJECT_EN = "DO_NOT_INJECT_GAP";
+ parameter TX_H_ALLOC_C = "0b000000100000";
+ parameter TX_H_ALLOC_N = "0b000000001000";
+ parameter TX_H_ALLOC_P = "0b000000010000";
+ parameter TX_HIZ = "IGNORED";
+ parameter TX_IMPED_RATIO = "0b10000000";
+ parameter TX_PAR1_INJECT_EN = "DO_NOT_INJECT_ERR";
+ parameter TX_PAR2_HANDLE_DISABLE = "ENABLE_HANDLING";
+ parameter TX_PAR2_INJECT_EN = "DO_NOT_INJECT_ERR";
+ parameter TX_PAR2_REPORT_DISABLE = "ENABLE_REPORTING";
+ parameter TX_POLINV = "NORMAL";
+ parameter TX_PRE_RATIO = "0b00000000";
+ parameter TX_PRE_RATIO_DEEMP0_FULL = "0b00000000";
+ parameter TX_PRE_RATIO_DEEMP0_HALF = "0b00000000";
+ parameter TX_PRE_RATIO_DEEMP1_FULL = "0b00000000";
+ parameter TX_PRE_RATIO_DEEMP1_HALF = "0b00000000";
+ parameter TX_PRIORITY = "DISABLED";
+ parameter TX_PRIORITY_N_STARVE_THRESH = "0b00010000";
+ parameter TX_PRIORITY_P_STARVE_THRESH = "0b00010000";
+ parameter TX_PST_RATIO = "0b00010101";
+ parameter TX_PST_RATIO_DEEMP0_FULL = "0b00100000";
+ parameter TX_PST_RATIO_DEEMP0_HALF = "0b00100000";
+ parameter TX_PST_RATIO_DEEMP1_FULL = "0b00010101";
+ parameter TX_PST_RATIO_DEEMP1_HALF = "0b00010101";
+ parameter TX_QUIESCE = "DISABLED";
+ parameter TX_REPLAY_ECC1_HANDLE_DISABLE = "ENABLE_CORRECTION";
+ parameter TX_REPLAY_ECC1_INJECT_EN = "DO_NOT_INJECT_ERR";
+ parameter TX_REPLAY_ECC1_REPORT_DISABLE = "ENABLE_REPORTING";
+ parameter TX_REPLAY_ECC2_HANDLE_DISABLE = "ENABLE_HANDLING";
+ parameter TX_REPLAY_ECC2_INJECT_EN = "DO_NOT_INJECT_ERR";
+ parameter TX_REPLAY_ECC2_REPORT_DISABLE = "ENABLE_REPORTING";
+ parameter TX_REQ_EQ = "DISABLED";
+ parameter TX_SELECT_RX_FEEDBACK = "REFCLK";
+ parameter TX_TLP_VALID = "DISABLED";
+ parameter TXF_A = "0b0100";
+ parameter TXF_B = "0b0100";
+ parameter TXF_C = "0b0100";
+ parameter TXHF_CLKDN = "ENABLED";
+ parameter TXM_A = "0b10";
+ parameter TXM_B = "0b01";
+ parameter TXM_C = "0b00";
+ parameter TXN_A = "0b00100";
+ parameter TXN_B = "0b01001";
+ parameter TXN_C = "0b01111";
+ parameter TXPLL_INIT = "DISABLED";
+ parameter TXPLLRST = "DISABLED";
+ parameter TYPE1_TYPE0_N = "ENDPOINT";
+ parameter U_CLK_PERIOD = "0b0001111101000000";
+ parameter US_PORT_PS_ENTRY_TIME = "0b0000000000000000";
+ parameter US_PORT_RX_PRESET_HINT = "0b010";
+ parameter US_PORT_TX_PRESET = "0b0100";
+ parameter USE_COEF_PRE_MTHD_CTRL = "PRESET_VALUE";
+ parameter USE_COEF_UPDN_CTRL = "PRESET_VALUE";
+ parameter USER_AUTO_N = "AUTOMATIC_ON_RECEPTION";
+ parameter VEC_MASK_CAPABLE_MSICAP_A = "ENABLED";
+ parameter VEC_MASK_CAPABLE_MSICAP_B = "ENABLED";
+ parameter VEC_MASK_CAPABLE_MSICAP_C = "ENABLED";
+ parameter VEC_MASK_CAPABLE_MSICAP_D = "ENABLED";
+ parameter VENDOR_ID_ID1A = "0b0001100110101010";
+ parameter VENDOR_ID_ID1B = "0b0001100110101010";
+ parameter VENDOR_ID_ID1C = "0b0001100110101010";
+ parameter VENDOR_ID_ID1D = "0b0001100110101010";
+ parameter VENDOR0_UR = "REPORT";
+ parameter VERSION_AER_CAP = "VER_0X2";
+ parameter VERSION_PM_CAP = "0b011";
+ parameter XLCY0 = "0b00000000";
+ parameter XLCY1 = "0b00000000";
+ parameter RX_ESP_RESP_WAIT = "0b01000000";
+ parameter SEL_PCLK_DIV2 = "PCLK_DIV2";
+ parameter COMPLIANCE = "ENABLED";
+ parameter LOOPBACK = "ENABLED";
+ parameter HOT_RESET = "ENABLED";
+ parameter DIS_PREVENT = "ENABLED";
+ parameter MPS_VIOLATION_RX = "DISABLED";
+ parameter MPS_VIOLATION_TX = "DISABLED";
+ parameter EN_RX_ALLOC_SEL = "HW";
+ parameter EN_TX_ALLOC_SEL = "HW";
+ parameter AUX_CLK_PERIOD = "0b1111010000100100";
+ parameter EN_PIPE_IF_CTRL = "DISABLED";
+ parameter PIPE_PWRDN = "P1";
+ parameter TX_CM_DIS = "DEASSERTED";
+ parameter RX_EI_DIS = "DEASSERTED";
+ parameter PCLKREQ_N = "DEASSERTED";
+ parameter STS_PHY_STATUS = "DEASSERTED";
+ parameter STS_PIPE_RSTN = "DEASSERTED";
+ parameter LEGACY_MODE = "MATCH_TS";
+ parameter OVERFLOW = "DISABLED";
+ parameter DIR = "RECEIVE";
+ parameter SPEED = "8G";
+ parameter LANE = "0";
+ parameter COEF_ENABLE_8G = "DISABLED";
+ parameter PRESET_ENABLE_8G = "DISABLED";
+ parameter VALUE_8G_PRE = "0b000000";
+ parameter VALUE_8G_POST = "0b000000";
+ parameter REQ_EQ_MAX_COUNT = "0b10";
+ parameter MESO_LPBK = "DISABLED";
+ parameter TX_REPLAY_ECC2_INJECT_M_1_N = "INJECT_1_ERR";
+ parameter TX_REPLAY_ECC1_INJECT_M_1_N = "INJECT_1_ERR";
+ parameter REDO = "DISABLED";
+ parameter RX_PAR_REPORT_DISABLE = "ENABLE_REPORTING";
+ parameter RX_PAR_INJECT_EN = "DO_NOT_INJECT_ERR";
+ parameter RX_ECC2_REPORT_DISABLE = "ENABLE_REPORTING";
+ parameter RX_ECC2_HANDLE_DISABLE = "ENABLE_HANDLING";
+ parameter RX_ECC2_INJECT_M_1_N = "INJECT_1_ERR";
+ parameter RX_ECC2_INJECT_TYPE = "POSTED_DATA_RAM";
+ parameter RX_ECC2_INJECT_EN = "DO_NOT_INJECT_ERR";
+ parameter RX_ECC1_REPORT_DISABLE = "ENABLE_REPORTING";
+ parameter RX_ECC1_HANDLE_DISABLE = "ENABLE_HANDLING";
+ parameter RX_ECC1_INJECT_M_1_N = "INJECT_1_ERR";
+ parameter RX_ECC1_INJECT_TYPE = "POSTED_DATA_RAM";
+ parameter RX_ECC1_INJECT_EN = "DO_NOT_INJECT_ERR";
+ parameter RX_ERR_PAR = "OTHERWISE";
+ parameter RX_ERR_ECC2 = "OTHERWISE";
+ parameter RX_ERR_ECC1 = "OTHERWISE";
+ parameter TX_PAR_REPORT_DISABLE = "ENABLE_REPORTING";
+ parameter TX_PAR_INJECT_EN = "DO_NOT_INJECT_ERR";
+ parameter TX_ECC2_REPORT_DISABLE = "ENABLE_REPORTING";
+ parameter TX_ECC2_HANDLE_DISABLE = "ENABLE_HANDLING";
+ parameter TX_ECC2_INJECT_M_1_N = "INJECT_1_ERR";
+ parameter TX_ECC2_INJECT_TYPE = "POSTED_DATA_RAM";
+ parameter TX_ECC2_INJECT_EN = "DO_NOT_INJECT_ERR";
+ parameter TX_ECC1_REPORT_DISABLE = "ENABLE_REPORTING";
+ parameter TX_ECC1_HANDLE_DISABLE = "ENABLE_HANDLING";
+ parameter TX_ECC1_INJECT_M_1_N = "INJECT_1_ERR";
+ parameter TX_ECC1_INJECT_TYPE = "POSTED_DATA_RAM";
+ parameter TX_ECC1_INJECT_EN = "DO_NOT_INJECT_ERR";
+ parameter TX_ERR_PAR = "OTHERWISE";
+ parameter TX_ERR_ECC2 = "OTHERWISE";
+ parameter TX_ERR_ECC1 = "OTHERWISE";
+ parameter MAX_PAYLOAD_SIZE_SUPPORTED = "256_BYTES";
+ parameter ARXCAL_OUT = "DISABLED";
+ parameter F_ARXDPDIR = "IGNORED";
+ parameter IDLE_INFER_REC_RCVR_CFG = "OTHERWISE";
+ parameter IDLE_INFER_LPBK_SLAVE = "OTHERWISE";
+ parameter IDLE_INFER_REC_SPEED2_SUCCESS = "OTHERWISE";
+ parameter IDLE_INFER_REC_SPEED2_UNSUCCESS = "OTHERWISE";
+ parameter IDLE_INFER_L0_TO_REC_RCVR_LOCK = "OTHERWISE";
+ parameter SPEED_CHANGE_FAIL = "OTHERWISE";
+ parameter DIRECT_TO_DETECT_FAST = "OTHERWISE";
+ parameter DIRECT_TO_RCVRY_CH_BOND = "OTHERWISE";
+ parameter DIRECT_TO_LPBK_ENTRY = "OTHERWISE";
+ parameter DIRECT_SPEED_CHANGE = "OTHERWISE";
+ parameter L0_TO_REC_RCVR_LOCK_RX_TS12 = "OTHERWISE";
+ parameter L0_TO_REC_RCVR_LOCK_RX_8G_EIE = "OTHERWISE";
+ parameter L0_TO_REC_RCVR_LOCK_RX_INFER = "OTHERWISE";
+ parameter DIRECT_TO_RCVRY_PHY = "OTHERWISE";
+ parameter DIRECT_TO_RCVRY_FRAME = "OTHERWISE";
+ parameter DIRECT_TO_RCVRY_REPLAY = "OTHERWISE";
+ parameter DIRECT_TO_HOT_RESET = "OTHERWISE";
+ parameter DIRECT_TO_DISABLE = "OTHERWISE";
+ parameter RX_L0S_DIRECT_TO_RCVRY = "OTHERWISE";
+ parameter AUTONOMOUS_WIDTH_CHANGE = "OTHERWISE";
+ parameter DIRECTED_RETRAIN_LINK = "OTHERWISE";
+ parameter ERR_TX_PIPE_UNDERFLOW = "OTHERWISE";
+ parameter TS2_DETECT3 = "OTHERWISE";
+ parameter TS2_DETECT2 = "OTHERWISE";
+ parameter TS2_DETECT1 = "OTHERWISE";
+ parameter TS2_DETECT0 = "OTHERWISE";
+ parameter TS1_DETECT3 = "OTHERWISE";
+ parameter TS1_DETECT2 = "OTHERWISE";
+ parameter TS1_DETECT1 = "OTHERWISE";
+ parameter TS1_DETECT0 = "OTHERWISE";
+ parameter TS2I_DETECT3 = "OTHERWISE";
+ parameter TS2I_DETECT2 = "OTHERWISE";
+ parameter TS2I_DETECT1 = "OTHERWISE";
+ parameter TS2I_DETECT0 = "OTHERWISE";
+ parameter TS1I_DETECT3 = "OTHERWISE";
+ parameter TS1I_DETECT2 = "OTHERWISE";
+ parameter TS1I_DETECT1 = "OTHERWISE";
+ parameter TS1I_DETECT0 = "OTHERWISE";
+ parameter FTS_DETECT3 = "OTHERWISE";
+ parameter FTS_DETECT2 = "OTHERWISE";
+ parameter FTS_DETECT1 = "OTHERWISE";
+ parameter FTS_DETECT0 = "OTHERWISE";
+ parameter SKP_DETECT3 = "OTHERWISE";
+ parameter SKP_DETECT2 = "OTHERWISE";
+ parameter SKP_DETECT1 = "OTHERWISE";
+ parameter SKP_DETECT0 = "OTHERWISE";
+ parameter EIE_DETECT3 = "OTHERWISE";
+ parameter EIE_DETECT2 = "OTHERWISE";
+ parameter EIE_DETECT1 = "OTHERWISE";
+ parameter EIE_DETECT0 = "OTHERWISE";
+ parameter EIOS_DETECT3 = "OTHERWISE";
+ parameter EIOS_DETECT2 = "OTHERWISE";
+ parameter EIOS_DETECT1 = "OTHERWISE";
+ parameter EIOS_DETECT0 = "OTHERWISE";
+ parameter DATA_DETECT3 = "OTHERWISE";
+ parameter DATA_DETECT2 = "OTHERWISE";
+ parameter DATA_DETECT1 = "OTHERWISE";
+ parameter DATA_DETECT0 = "OTHERWISE";
+ parameter SDS_DETECT3 = "OTHERWISE";
+ parameter SDS_DETECT2 = "OTHERWISE";
+ parameter SDS_DETECT1 = "OTHERWISE";
+ parameter SDS_DETECT0 = "OTHERWISE";
+ parameter INFO_BAD_TLP_NULL_ERR = "OTHERWISE";
+ parameter INFO_BAD_TLP_PHY_ERR = "OTHERWISE";
+ parameter INFO_BAD_TLP_MALF_ERR = "OTHERWISE";
+ parameter INFO_BAD_TLP_ECRC_ERR = "OTHERWISE";
+ parameter INFO_SCHEDULE_DUPL_ACK = "OTHERWISE";
+ parameter INFO_BAD_TLP_SEQ_ERR = "OTHERWISE";
+ parameter INFO_BAD_TLP_CRC_ERR = "OTHERWISE";
+ parameter INFO_NAK_RECEIVED = "OTHERWISE";
+ parameter INFO_DESKEW_OVERFLOW_ERROR = "OTHERWISE";
+ parameter INFO_TX_DATA_UNDERFLOW = "OTHERWISE";
+ parameter INFO_REPLAY_STARTED = "OTHERWISE";
+ parameter ERR_AER_TX_PAR2 = "OTHERWISE";
+ parameter ERR_AER_TX_REPLAY_ECC2 = "OTHERWISE";
+ parameter ERR_AER_TX_REPLAY_ECC1 = "OTHERWISE";
+ parameter ERR_AER_SURPRISE_DOWN = "OTHERWISE";
+ parameter ERR_AER_DL_PROTOCOL_ERROR = "OTHERWISE";
+ parameter ERR_AER_REPLAY_TIMER_TIMEOUT = "OTHERWISE";
+ parameter ERR_AER_REPLAY_NUM_ROLLOVER = "OTHERWISE";
+ parameter ERR_AER_BAD_DLLP = "OTHERWISE";
+ parameter ERR_AER_BAD_TLP = "OTHERWISE";
+ parameter ERR_AER_RECEIVER_ERROR = "OTHERWISE";
+ parameter P_RX_LIM_H = "DISABLED";
+ parameter P_RX_LIM_D = "DISABLED";
+ parameter N_RX_LIM_H = "DISABLED";
+ parameter N_RX_LIM_D = "DISABLED";
+ parameter C_RX_LIM_H = "DISABLED";
+ parameter C_RX_LIM_D = "DISABLED";
+ parameter P_TX_LIM_H = "DISABLED";
+ parameter P_TX_LIM_D = "DISABLED";
+ parameter N_TX_LIM_H = "DISABLED";
+ parameter N_TX_LIM_D = "DISABLED";
+ parameter C_TX_LIM_H = "DISABLED";
+ parameter C_TX_LIM_D = "DISABLED";
+ parameter MAX_RSA_WAIT = "0b00101000";
+ parameter F_ARXDPNULL = "0b00000";
+ input ACTACMD;
+ input ACTDR11;
+ input ACTEN;
+ input ACTHIGHZ;
+ input ACTMD;
+ output ACJNOUT;
+ output ACJPOUT;
+ input AUXCK;
+ input CKUSRI;
+ output CKUSRO;
+ input ECKIN;
+ input ECKIND2;
+ output ECKINDO;
+ input ERSTN;
+ input ERSTND2;
+ input ERXCKD2;
+ output ERXCKDO;
+ input ERXRSND2;
+ input ETXCKD2;
+ output ETXCKDO;
+ input ETXRSND2;
+ output FLR3;
+ output FLR2;
+ output FLR1;
+ output FLR0;
+ input FLRACK3;
+ input FLRACK2;
+ input FLRACK1;
+ input FLRACK0;
+ input MINTLEG3;
+ input MINTLEG2;
+ input MINTLEG1;
+ input MINTLEG0;
+ output MINTO;
+ input PERSTN;
+ output PMCTRL4;
+ output PMCTRL3;
+ output PMCTRL2;
+ output PMCTRL1;
+ output PMCTRL0;
+ output PMCTRLEN;
+ input PMDPAST4;
+ input PMDPAST3;
+ input PMDPAST2;
+ input PMDPAST1;
+ input PMDPAST0;
+ input PRMSGSD;
+ input PRNOSNP12;
+ input PRNOSNP11;
+ input PRNOSNP10;
+ input PRNOSNP9;
+ input PRNOSNP8;
+ input PRNOSNP7;
+ input PRNOSNP6;
+ input PRNOSNP5;
+ input PRNOSNP4;
+ input PRNOSNP3;
+ input PRNOSNP2;
+ input PRNOSNP1;
+ input PRNOSNP0;
+ input PRNSNPRE;
+ input PRSNOOP12;
+ input PRSNOOP11;
+ input PRSNOOP10;
+ input PRSNOOP9;
+ input PRSNOOP8;
+ input PRSNOOP7;
+ input PRSNOOP6;
+ input PRSNOOP5;
+ input PRSNOOP4;
+ input PRSNOOP3;
+ input PRSNOOP2;
+ input PRSNOOP1;
+ input PRSNOOP0;
+ input PRSNPRE;
+ input PPBDREG31;
+ input PPBDREG30;
+ input PPBDREG29;
+ input PPBDREG28;
+ input PPBDREG27;
+ input PPBDREG26;
+ input PPBDREG25;
+ input PPBDREG24;
+ input PPBDREG23;
+ input PPBDREG22;
+ input PPBDREG21;
+ input PPBDREG20;
+ input PPBDREG19;
+ input PPBDREG18;
+ input PPBDREG17;
+ input PPBDREG16;
+ input PPBDREG15;
+ input PPBDREG14;
+ input PPBDREG13;
+ input PPBDREG12;
+ input PPBDREG11;
+ input PPBDREG10;
+ input PPBDREG9;
+ input PPBDREG8;
+ input PPBDREG7;
+ input PPBDREG6;
+ input PPBDREG5;
+ input PPBDREG4;
+ input PPBDREG3;
+ input PPBDREG2;
+ input PPBDREG1;
+ input PPBDREG0;
+ output PPBDSEL7;
+ output PPBDSEL6;
+ output PPBDSEL5;
+ output PPBDSEL4;
+ output PPBDSEL3;
+ output PPBDSEL2;
+ output PPBDSEL1;
+ output PPBDSEL0;
+ input REXTCK;
+ input REXTRST;
+ input RSTUSRN;
+ output UDLLKUP;
+ input ULTSDIS;
+ output UPLLKUP;
+ output UTLLKUP;
+ input UCFGADDR11;
+ input UCFGADDR10;
+ input UCFGADDR9;
+ input UCFGADDR8;
+ input UCFGADDR7;
+ input UCFGADDR6;
+ input UCFGADDR5;
+ input UCFGADDR4;
+ input UCFGADDR3;
+ input UCFGADDR2;
+ input UCFGF2;
+ input UCFGF1;
+ input UCFGF0;
+ output UCFGRDD31;
+ output UCFGRDD30;
+ output UCFGRDD29;
+ output UCFGRDD28;
+ output UCFGRDD27;
+ output UCFGRDD26;
+ output UCFGRDD25;
+ output UCFGRDD24;
+ output UCFGRDD23;
+ output UCFGRDD22;
+ output UCFGRDD21;
+ output UCFGRDD20;
+ output UCFGRDD19;
+ output UCFGRDD18;
+ output UCFGRDD17;
+ output UCFGRDD16;
+ output UCFGRDD15;
+ output UCFGRDD14;
+ output UCFGRDD13;
+ output UCFGRDD12;
+ output UCFGRDD11;
+ output UCFGRDD10;
+ output UCFGRDD9;
+ output UCFGRDD8;
+ output UCFGRDD7;
+ output UCFGRDD6;
+ output UCFGRDD5;
+ output UCFGRDD4;
+ output UCFGRDD3;
+ output UCFGRDD2;
+ output UCFGRDD1;
+ output UCFGRDD0;
+ output UCFGRDE;
+ output UCFGRDY;
+ input UCFGSERD;
+ input UCFGVD;
+ input UCFGWRBE3;
+ input UCFGWRBE2;
+ input UCFGWRBE1;
+ input UCFGWRBE0;
+ input UCFGWRD31;
+ input UCFGWRD30;
+ input UCFGWRD29;
+ input UCFGWRD28;
+ input UCFGWRD27;
+ input UCFGWRD26;
+ input UCFGWRD25;
+ input UCFGWRD24;
+ input UCFGWRD23;
+ input UCFGWRD22;
+ input UCFGWRD21;
+ input UCFGWRD20;
+ input UCFGWRD19;
+ input UCFGWRD18;
+ input UCFGWRD17;
+ input UCFGWRD16;
+ input UCFGWRD15;
+ input UCFGWRD14;
+ input UCFGWRD13;
+ input UCFGWRD12;
+ input UCFGWRD11;
+ input UCFGWRD10;
+ input UCFGWRD9;
+ input UCFGWRD8;
+ input UCFGWRD7;
+ input UCFGWRD6;
+ input UCFGWRD5;
+ input UCFGWRD4;
+ input UCFGWRD3;
+ input UCFGWRD2;
+ input UCFGWRD1;
+ input UCFGWRD0;
+ input UCFGWRDN;
+ input USERAUPD;
+ input USERTRS3;
+ input USERTRS2;
+ input USERTRS1;
+ input USERTRS0;
+ input LMMICLK;
+ input LMMIOFFSET16;
+ input LMMIOFFSET15;
+ input LMMIOFFSET14;
+ input LMMIOFFSET13;
+ input LMMIOFFSET12;
+ input LMMIOFFSET11;
+ input LMMIOFFSET10;
+ input LMMIOFFSET9;
+ input LMMIOFFSET8;
+ input LMMIOFFSET7;
+ input LMMIOFFSET6;
+ input LMMIOFFSET5;
+ input LMMIOFFSET4;
+ input LMMIOFFSET3;
+ input LMMIOFFSET2;
+ output LMMIRDATA31;
+ output LMMIRDATA30;
+ output LMMIRDATA29;
+ output LMMIRDATA28;
+ output LMMIRDATA27;
+ output LMMIRDATA26;
+ output LMMIRDATA25;
+ output LMMIRDATA24;
+ output LMMIRDATA23;
+ output LMMIRDATA22;
+ output LMMIRDATA21;
+ output LMMIRDATA20;
+ output LMMIRDATA19;
+ output LMMIRDATA18;
+ output LMMIRDATA17;
+ output LMMIRDATA16;
+ output LMMIRDATA15;
+ output LMMIRDATA14;
+ output LMMIRDATA13;
+ output LMMIRDATA12;
+ output LMMIRDATA11;
+ output LMMIRDATA10;
+ output LMMIRDATA9;
+ output LMMIRDATA8;
+ output LMMIRDATA7;
+ output LMMIRDATA6;
+ output LMMIRDATA5;
+ output LMMIRDATA4;
+ output LMMIRDATA3;
+ output LMMIRDATA2;
+ output LMMIRDATA1;
+ output LMMIRDATA0;
+ output LMMIRDATAVALID;
+ output LMMIREADY;
+ input LMMIREQUEST;
+ input LMMIRESETN;
+ input LMMIWDATA31;
+ input LMMIWDATA30;
+ input LMMIWDATA29;
+ input LMMIWDATA28;
+ input LMMIWDATA27;
+ input LMMIWDATA26;
+ input LMMIWDATA25;
+ input LMMIWDATA24;
+ input LMMIWDATA23;
+ input LMMIWDATA22;
+ input LMMIWDATA21;
+ input LMMIWDATA20;
+ input LMMIWDATA19;
+ input LMMIWDATA18;
+ input LMMIWDATA17;
+ input LMMIWDATA16;
+ input LMMIWDATA15;
+ input LMMIWDATA14;
+ input LMMIWDATA13;
+ input LMMIWDATA12;
+ input LMMIWDATA11;
+ input LMMIWDATA10;
+ input LMMIWDATA9;
+ input LMMIWDATA8;
+ input LMMIWDATA7;
+ input LMMIWDATA6;
+ input LMMIWDATA5;
+ input LMMIWDATA4;
+ input LMMIWDATA3;
+ input LMMIWDATA2;
+ input LMMIWDATA1;
+ input LMMIWDATA0;
+ input LMMIWRRDN;
+ output VRXCMDD12;
+ output VRXCMDD11;
+ output VRXCMDD10;
+ output VRXCMDD9;
+ output VRXCMDD8;
+ output VRXCMDD7;
+ output VRXCMDD6;
+ output VRXCMDD5;
+ output VRXCMDD4;
+ output VRXCMDD3;
+ output VRXCMDD2;
+ output VRXCMDD1;
+ output VRXCMDD0;
+ input VRXCINIT;
+ input VRXCNH11;
+ input VRXCNH10;
+ input VRXCNH9;
+ input VRXCNH8;
+ input VRXCNH7;
+ input VRXCNH6;
+ input VRXCNH5;
+ input VRXCNH4;
+ input VRXCNH3;
+ input VRXCNH2;
+ input VRXCNH1;
+ input VRXCNH0;
+ input VRXCNINF;
+ input VRXCRRE;
+ output VRXD31;
+ output VRXD30;
+ output VRXD29;
+ output VRXD28;
+ output VRXD27;
+ output VRXD26;
+ output VRXD25;
+ output VRXD24;
+ output VRXD23;
+ output VRXD22;
+ output VRXD21;
+ output VRXD20;
+ output VRXD19;
+ output VRXD18;
+ output VRXD17;
+ output VRXD16;
+ output VRXD15;
+ output VRXD14;
+ output VRXD13;
+ output VRXD12;
+ output VRXD11;
+ output VRXD10;
+ output VRXD9;
+ output VRXD8;
+ output VRXD7;
+ output VRXD6;
+ output VRXD5;
+ output VRXD4;
+ output VRXD3;
+ output VRXD2;
+ output VRXD1;
+ output VRXD0;
+ output VRXDP3;
+ output VRXDP2;
+ output VRXDP1;
+ output VRXDP0;
+ output VRXEOP;
+ output VRXERR;
+ output VRXF1;
+ output VRXF0;
+ input VRXRDY;
+ output VRXSEL1;
+ output VRXSEL0;
+ output VRXSOP;
+ output VRXVD;
+ output VXCDINIT;
+ output VXCDNH11;
+ output VXCDNH10;
+ output VXCDNH9;
+ output VXCDNH8;
+ output VXCDNH7;
+ output VXCDNH6;
+ output VXCDNH5;
+ output VXCDNH4;
+ output VXCDNH3;
+ output VXCDNH2;
+ output VXCDNH1;
+ output VXCDNH0;
+ output VTXCRRE;
+ input VXD31;
+ input VXD30;
+ input VXD29;
+ input VXD28;
+ input VXD27;
+ input VXD26;
+ input VXD25;
+ input VXD24;
+ input VXD23;
+ input VXD22;
+ input VXD21;
+ input VXD20;
+ input VXD19;
+ input VXD18;
+ input VXD17;
+ input VXD16;
+ input VXD15;
+ input VXD14;
+ input VXD13;
+ input VXD12;
+ input VXD11;
+ input VXD10;
+ input VXD9;
+ input VXD8;
+ input VXD7;
+ input VXD6;
+ input VXD5;
+ input VXD4;
+ input VXD3;
+ input VXD2;
+ input VXD1;
+ input VXD0;
+ input VXDP3;
+ input VXDP2;
+ input VXDP1;
+ input VXDP0;
+ input VXEOP;
+ input VXEOPN;
+ output VXRDY;
+ input VXSOP;
+ input VXVD;
+ output TESTOUT7;
+ output TESTOUT6;
+ output TESTOUT5;
+ output TESTOUT4;
+ output TESTOUT3;
+ output TESTOUT2;
+ output TESTOUT1;
+ output TESTOUT0;
+ input REFCLKNA;
+ (* iopad_external_pin *)
+ input S0REFCKN;
+ (* iopad_external_pin *)
+ input S0REFCKP;
+ (* iopad_external_pin *)
+ input S0REFRET;
+ (* iopad_external_pin *)
+ input S0REXT;
+ (* iopad_external_pin *)
+ input S0RXN;
+ (* iopad_external_pin *)
+ input S0RXP;
+ (* iopad_external_pin *)
+ output S0TXN;
+ (* iopad_external_pin *)
+ output S0TXP;
+ input CLKREQI;
+ output CLKREQO;
+ output CLKREQOE;
+ input SCANCLK;
+ input SCANRST;
+ input OPCGLDCK;
+ input ALTCLKIN;
+endmodule
+
+module PLL_CORE (...);
+ parameter BW_CTL_BIAS = "0b0101";
+ parameter CLKOP_TRIM = "0b0000";
+ parameter CLKOS_TRIM = "0b0000";
+ parameter CLKOS2_TRIM = "0b0000";
+ parameter CLKOS3_TRIM = "0b0000";
+ parameter CLKOS4_TRIM = "0b0000";
+ parameter CLKOS5_TRIM = "0b0000";
+ parameter CRIPPLE = "5P";
+ parameter CSET = "40P";
+ parameter DELAY_CTRL = "200PS";
+ parameter DELA = "0";
+ parameter DELB = "0";
+ parameter DELC = "0";
+ parameter DELD = "0";
+ parameter DELE = "0";
+ parameter DELF = "0";
+ parameter DIRECTION = "DISABLED";
+ parameter DIVA = "0";
+ parameter DIVB = "0";
+ parameter DIVC = "0";
+ parameter DIVD = "0";
+ parameter DIVE = "0";
+ parameter DIVF = "0";
+ parameter DYN_SEL = "0b000";
+ parameter DYN_SOURCE = "STATIC";
+ parameter ENCLK_CLKOP = "DISABLED";
+ parameter ENCLK_CLKOS = "DISABLED";
+ parameter ENCLK_CLKOS2 = "DISABLED";
+ parameter ENCLK_CLKOS3 = "DISABLED";
+ parameter ENCLK_CLKOS4 = "DISABLED";
+ parameter ENCLK_CLKOS5 = "DISABLED";
+ parameter ENABLE_SYNC = "DISABLED";
+ parameter FAST_LOCK_EN = "ENABLED";
+ parameter V2I_1V_EN = "DISABLED";
+ parameter FBK_CUR_BLE = "0b00000000";
+ parameter FBK_EDGE_SEL = "POSITIVE";
+ parameter FBK_IF_TIMING_CTL = "0b00";
+ parameter FBK_INTEGER_MODE = "DISABLED";
+ parameter FBK_MASK = "0b00001000";
+ parameter FBK_MMD_DIG = "8";
+ parameter FBK_MMD_PULS_CTL = "0b0000";
+ parameter FBK_MODE = "0b00";
+ parameter FBK_PI_BYPASS = "NOT_BYPASSED";
+ parameter FBK_PI_RC = "0b1100";
+ parameter FBK_PR_CC = "0b0000";
+ parameter FBK_PR_IC = "0b1000";
+ parameter FLOAT_CP = "DISABLED";
+ parameter FLOCK_CTRL = "2X";
+ parameter FLOCK_EN = "ENABLED";
+ parameter FLOCK_SRC_SEL = "REFCLK";
+ parameter FORCE_FILTER = "DISABLED";
+ parameter I_CTRL = "10UA";
+ parameter IPI_CMP = "0b1000";
+ parameter IPI_CMPN = "0b0011";
+ parameter IPI_COMP_EN = "DISABLED";
+ parameter IPP_CTRL = "0b1000";
+ parameter IPP_SEL = "0b1111";
+ parameter KP_VCO = "0b11001";
+ parameter LDT_INT_LOCK_STICKY = "DISABLED";
+ parameter LDT_LOCK = "1536CYC";
+ parameter LDT_LOCK_SEL = "U_FREQ";
+ parameter LEGACY_ATT = "DISABLED";
+ parameter LOAD_REG = "DISABLED";
+ parameter OPENLOOP_EN = "DISABLED";
+ parameter PHIA = "0";
+ parameter PHIB = "0";
+ parameter PHIC = "0";
+ parameter PHID = "0";
+ parameter PHIE = "0";
+ parameter PHIF = "0";
+ parameter PLLPDN_EN = "DISABLED";
+ parameter PLLPD_N = "UNUSED";
+ parameter PLLRESET_ENA = "DISABLED";
+ parameter REF_INTEGER_MODE = "DISABLED";
+ parameter REF_MASK = "0b00000000";
+ parameter REF_MMD_DIG = "8";
+ parameter REF_MMD_IN = "0b00001000";
+ parameter REF_MMD_PULS_CTL = "0b0000";
+ parameter REF_TIMING_CTL = "0b00";
+ parameter REFIN_RESET = "SET";
+ parameter RESET_LF = "DISABLED";
+ parameter ROTATE = "DISABLED";
+ parameter SEL_OUTA = "DISABLED";
+ parameter SEL_OUTB = "DISABLED";
+ parameter SEL_OUTC = "DISABLED";
+ parameter SEL_OUTD = "DISABLED";
+ parameter SEL_OUTE = "DISABLED";
+ parameter SEL_OUTF = "DISABLED";
+ parameter SLEEP = "DISABLED";
+ parameter SSC_DITHER = "DISABLED";
+ parameter SSC_EN_CENTER_IN = "DOWN_TRIANGLE";
+ parameter SSC_EN_SDM = "DISABLED";
+ parameter SSC_EN_SSC = "DISABLED";
+ parameter SSC_F_CODE = "0b000000000000000";
+ parameter SSC_N_CODE = "0b000010100";
+ parameter SSC_ORDER = "SDM_ORDER2";
+ parameter SSC_PI_BYPASS = "NOT_BYPASSED";
+ parameter SSC_REG_WEIGHTING_SEL = "0b000";
+ parameter SSC_SQUARE_MODE = "DISABLED";
+ parameter SSC_STEP_IN = "0b0000000";
+ parameter SSC_TBASE = "0b000000000000";
+ parameter STDBY_ATT = "DISABLED";
+ parameter TRIMOP_BYPASS_N = "BYPASSED";
+ parameter TRIMOS_BYPASS_N = "BYPASSED";
+ parameter TRIMOS2_BYPASS_N = "BYPASSED";
+ parameter TRIMOS3_BYPASS_N = "BYPASSED";
+ parameter TRIMOS4_BYPASS_N = "BYPASSED";
+ parameter TRIMOS5_BYPASS_N = "BYPASSED";
+ parameter V2I_KVCO_SEL = "85";
+ parameter V2I_PP_ICTRL = "0b00110";
+ parameter V2I_PP_RES = "10K";
+ parameter CLKMUX_FB = "CMUX_CLKOP";
+ parameter SEL_FBK = "DIVA";
+ parameter DIV_DEL = "0b0000001";
+ parameter PHASE_SEL_DEL = "0b000";
+ parameter PHASE_SEL_DEL_P1 = "0b000";
+ parameter EXTERNAL_DIVIDE_FACTOR = "0";
+ input CIBDIR;
+ input CIBDSEL2;
+ input CIBDSEL1;
+ input CIBDSEL0;
+ input CIBLDREG;
+ input CIBROT;
+ output CLKOP;
+ output CLKOS;
+ output CLKOS2;
+ output CLKOS3;
+ output CLKOS4;
+ output CLKOS5;
+ input ENEXT;
+ input ENCLKOP;
+ input ENCLKOS;
+ input ENCLKOS2;
+ input ENCLKOS3;
+ input ENCLKOS4;
+ input ENCLKOS5;
+ input FBKCK;
+ output INTFBK5;
+ output INTFBK4;
+ output INTFBK3;
+ output INTFBK2;
+ output INTFBK1;
+ output INTFBK0;
+ output INTLOCK;
+ input LEGACY;
+ output LEGRDYN;
+ input LMMICLK;
+ input LMMIOFFSET6;
+ input LMMIOFFSET5;
+ input LMMIOFFSET4;
+ input LMMIOFFSET3;
+ input LMMIOFFSET2;
+ input LMMIOFFSET1;
+ input LMMIOFFSET0;
+ output LMMIRDATA7;
+ output LMMIRDATA6;
+ output LMMIRDATA5;
+ output LMMIRDATA4;
+ output LMMIRDATA3;
+ output LMMIRDATA2;
+ output LMMIRDATA1;
+ output LMMIRDATA0;
+ output LMMIRDATAVALID;
+ output LMMIREADY;
+ input LMMIREQUEST;
+ input LMMIRESETN;
+ input LMMIWDATA7;
+ input LMMIWDATA6;
+ input LMMIWDATA5;
+ input LMMIWDATA4;
+ input LMMIWDATA3;
+ input LMMIWDATA2;
+ input LMMIWDATA1;
+ input LMMIWDATA0;
+ input LMMIWRRDN;
+ output LOCK;
+ output PFDDN;
+ output PFDUP;
+ input PLLRESET;
+ input REFCK;
+ input STDBY;
+ input ZRSEL3;
+ output REFMUXCK;
+ input PLLPDN;
+ output REGQA;
+ output REGQB;
+ output REGQB1;
+ output CLKOUTDL;
+ input ROTDEL;
+ input DIRDEL;
+ input ROTDELP1;
+ input GRAYTEST4;
+ input GRAYTEST3;
+ input GRAYTEST2;
+ input GRAYTEST1;
+ input GRAYTEST0;
+ input BINTEST1;
+ input BINTEST0;
+ input DIRDELP1;
+ input GRAYACT4;
+ input GRAYACT3;
+ input GRAYACT2;
+ input GRAYACT1;
+ input GRAYACT0;
+ input BINACT1;
+ input BINACT0;
+ input OPCGLDCK;
+ input SCANRST;
+ input SCANCLK;
+endmodule
+
+module PREADD9_CORE (...);
+ parameter SIGNEDSTATIC_EN = "DISABLED";
+ parameter SUBSTRACT_EN = "SUBTRACTION";
+ parameter CSIGNED = "DISABLED";
+ parameter BSIGNED_OPERAND_EN = "DISABLED";
+ parameter BYPASS_PREADD9 = "USED";
+ parameter REGBYPSBR0 = "REGISTER";
+ parameter REGBYPSBR1 = "BYPASS";
+ parameter REGBYPSBL = "REGISTER";
+ parameter SHIFTBR = "REGISTER";
+ parameter SHIFTBL = "REGISTER";
+ parameter GSR = "ENABLED";
+ parameter PREADDCAS_EN = "DISABLED";
+ parameter SR_18BITSHIFT_EN = "DISABLED";
+ parameter OPC = "INPUT_B_AS_PREADDER_OPERAND";
+ parameter RESET = "SYNC";
+ input B8;
+ input B7;
+ input B6;
+ input B5;
+ input B4;
+ input B3;
+ input B2;
+ input B1;
+ input B0;
+ input BSIGNED;
+ input C9;
+ input C8;
+ input C7;
+ input C6;
+ input C5;
+ input C4;
+ input C3;
+ input C2;
+ input C1;
+ input C0;
+ input BRS18;
+ input BRS17;
+ input BRS16;
+ input BRS15;
+ input BRS14;
+ input BRS13;
+ input BRS12;
+ input BRS11;
+ input BRS10;
+ input BRS28;
+ input BRS27;
+ input BRS26;
+ input BRS25;
+ input BRS24;
+ input BRS23;
+ input BRS22;
+ input BRS21;
+ input BRS20;
+ input BLS18;
+ input BLS17;
+ input BLS16;
+ input BLS15;
+ input BLS14;
+ input BLS13;
+ input BLS12;
+ input BLS11;
+ input BLS10;
+ input BLS28;
+ input BLS27;
+ input BLS26;
+ input BLS25;
+ input BLS24;
+ input BLS23;
+ input BLS22;
+ input BLS21;
+ input BLS20;
+ input BRSS1;
+ input BRSS2;
+ input BLSS1;
+ input BLSS2;
+ input PRCASIN;
+ input CLK;
+ input RSTB;
+ input CEB;
+ input RSTCL;
+ input CECL;
+ output BRSO8;
+ output BRSO7;
+ output BRSO6;
+ output BRSO5;
+ output BRSO4;
+ output BRSO3;
+ output BRSO2;
+ output BRSO1;
+ output BRSO0;
+ output BLSO8;
+ output BLSO7;
+ output BLSO6;
+ output BLSO5;
+ output BLSO4;
+ output BLSO3;
+ output BLSO2;
+ output BLSO1;
+ output BLSO0;
+ output BRSOSGND;
+ output BLSOSGND;
+ output PRCASOUT;
+ output BR8;
+ output BR7;
+ output BR6;
+ output BR5;
+ output BR4;
+ output BR3;
+ output BR2;
+ output BR1;
+ output BR0;
+ output BRSIGNED;
+endmodule
+
+module REFMUX_CORE (...);
+ parameter REFSEL_ATT = "MC1";
+ parameter SEL1 = "SELECT_REFCLK1";
+ parameter SEL_REF2 = "REFCLK2_0";
+ parameter SEL_REF1 = "REFCLK1_0";
+ output REFCK;
+ output ZRSEL3;
+ input REFSEL;
+ input REFCLK17;
+ input REFCLK16;
+ input REFCLK15;
+ input REFCLK14;
+ input REFCLK13;
+ input REFCLK12;
+ input REFCLK11;
+ input REFCLK10;
+ input REFCLK27;
+ input REFCLK26;
+ input REFCLK25;
+ input REFCLK24;
+ input REFCLK23;
+ input REFCLK22;
+ input REFCLK21;
+ input REFCLK20;
+endmodule
+
+module REG18_CORE (...);
+ parameter REGBYPS = "REGISTER";
+ parameter GSR = "ENABLED";
+ parameter RESET = "SYNC";
+ input PM17;
+ input PM16;
+ input PM15;
+ input PM14;
+ input PM13;
+ input PM12;
+ input PM11;
+ input PM10;
+ input PM9;
+ input PM8;
+ input PM7;
+ input PM6;
+ input PM5;
+ input PM4;
+ input PM3;
+ input PM2;
+ input PM1;
+ input PM0;
+ output PP17;
+ output PP16;
+ output PP15;
+ output PP14;
+ output PP13;
+ output PP12;
+ output PP11;
+ output PP10;
+ output PP9;
+ output PP8;
+ output PP7;
+ output PP6;
+ output PP5;
+ output PP4;
+ output PP3;
+ output PP2;
+ output PP1;
+ output PP0;
+ input CEP;
+ input RSTP;
+ input CLK;
+endmodule
+
+module SEIO18_CORE (...);
+ parameter MIPI_ID = "0";
+ parameter PULLMODE = "DOWN";
+ parameter MIPI = "DISABLED";
+ parameter ENADC_IN = "DISABLED";
+ input I;
+ input DOLP;
+ (* iopad_external_pin *)
+ inout B;
+ output O;
+ output INLP;
+ input T;
+ output INADC;
+endmodule
+
+module SEIO33_CORE (...);
+ parameter PULLMODE = "DOWN";
+ (* iopad_external_pin *)
+ inout B;
+ output O;
+ input I;
+ input T;
+ input I3CRESEN;
+ input I3CWKPU;
+endmodule
+
+module SGMIICDR_CORE (...);
+ parameter GSR = "ENABLED";
+ parameter DCOITUNE4LSB = "0_PERCENT";
+ parameter DCOCTLGI = "0_PERCENT";
+ parameter DCOSTEP = "100_PERCENT";
+ parameter DCOCALDIV = "100_PERCENT";
+ parameter DCOIOSTUNE = "0_PERCENT";
+ parameter DCOFLTDAC = "80MHZ";
+ parameter DCOSTARTVAL = "NOMINAL";
+ parameter DCONUOFLSB = "NEG_60_PERCENT";
+ parameter RPWDNB = "POWER_UP";
+ parameter CDR_CNT4SEL = "BYPASSED";
+ parameter DCOITUNE = "100_PERCENT";
+ parameter BAND_THRESHOLD = "0b000000";
+ parameter AUTO_FACQ_EN = "ENABLED";
+ parameter AUTO_CALIB_EN = "ENABLED";
+ parameter CDR_LOL_SET = "1000_PPM";
+ parameter FC2DCO_FLOOP = "DISABLED";
+ parameter FC2DCO_DLOOP = "DISABLED";
+ parameter CALIB_TIME_SEL = "24_CYC";
+ parameter CALIB_CK_MODE = "BY_2";
+ parameter BAND_CALIB_MODE = "256_FDBK_CLK_CYC";
+ parameter REG_BAND_SEL = "0b00000";
+ parameter REG_BAND_OFFSET = "0b0000";
+ parameter REG_IDAC_SEL = "0b00000000";
+ parameter LB_CTL = "DISABLED";
+ parameter REG_IDAC_EN = "DISABLED";
+ parameter ATDCFG = "0_PS";
+ parameter ATDDLY = "0_PS";
+ parameter BDAVOID_ENB = "ENABLED";
+ parameter BYPASSATD = "NOT_BYPASS";
+ parameter DCOIUPDNX2 = "1X";
+ parameter IDAC_EN = "DISABLED";
+ parameter FB_CLK_DIV = "0b010";
+ parameter EN_RECALIB = "ENABLED";
+ input DCALIRST;
+ input DFACQRST;
+ input RRST;
+ input SPCLK;
+ output SRCLK;
+ output SRXD9;
+ output SRXD8;
+ output SRXD7;
+ output SRXD6;
+ output SRXD5;
+ output SRXD4;
+ output SRXD3;
+ output SRXD2;
+ output SRXD1;
+ output SRXD0;
+ input LMMICLK;
+ input LMMIREQUEST;
+ input LMMIWRRDN;
+ input LMMIOFFSET3;
+ input LMMIOFFSET2;
+ input LMMIOFFSET1;
+ input LMMIOFFSET0;
+ input LMMIWDATA7;
+ input LMMIWDATA6;
+ input LMMIWDATA5;
+ input LMMIWDATA4;
+ input LMMIWDATA3;
+ input LMMIWDATA2;
+ input LMMIWDATA1;
+ input LMMIWDATA0;
+ output LMMIRDATA7;
+ output LMMIRDATA6;
+ output LMMIRDATA5;
+ output LMMIRDATA4;
+ output LMMIRDATA3;
+ output LMMIRDATA2;
+ output LMMIRDATA1;
+ output LMMIRDATA0;
+ output LMMIRDATAVALID;
+ output LMMIREADY;
+ input LMMIRESETN;
+ input RSTBFBW;
+ input RSTBRXF;
+ input SGMIIIN;
+ input SREFCLK;
+ output CDRLOL;
+ input OPCGLOADCLK;
+ input SCANCLK;
+ input SCANRST;
+endmodule
+
+module GSR (...);
+ parameter SYNCMODE = "ASYNC";
+ input GSR_N;
+ input CLK;
+endmodule
+
+module DCC (...);
+ parameter DCCEN = "0";
+ input CE;
+ input CLKI;
+ output CLKO;
+endmodule
+
+module DCS (...);
+ parameter DCSMODE = "GND";
+ input CLK0;
+ input CLK1;
+ output DCSOUT;
+ input SEL;
+ input SELFORCE;
+endmodule
+
+module GSR_CORE (...);
+ parameter GSR = "ENABLED";
+ parameter GSR_SYNC = "ASYNC";
+ output GSROUT;
+ input CLK;
+ input GSR_N;
+endmodule
+
+module PCLKDIV (...);
+ parameter DIV_PCLKDIV = "X1";
+ parameter GSR = "ENABLED";
+ parameter TESTEN_PCLKDIV = "0";
+ parameter TESTMODE_PCLKDIV = "0";
+ input CLKIN;
+ output CLKOUT;
+ input LSRPDIV;
+ input PCLKDIVTESTINP2;
+ input PCLKDIVTESTINP1;
+ input PCLKDIVTESTINP0;
+endmodule
+
+(* keep *)
+module PUR (...);
+ parameter RST_PULSE = "1";
+ input PUR;
+endmodule
+
+module PCLKDIVSP (...);
+ parameter DIV_PCLKDIV = "X1";
+ parameter GSR = "ENABLED";
+ input CLKIN;
+ output CLKOUT;
+ input LSRPDIV;
+endmodule
+
diff --git a/techlibs/nexus/dsp_map.v b/techlibs/nexus/dsp_map.v
new file mode 100644
index 000000000..b12528309
--- /dev/null
+++ b/techlibs/nexus/dsp_map.v
@@ -0,0 +1,79 @@
+module \$__NX_MUL36X36 (input [35:0] A, input [35:0] B, output [71:0] Y);
+
+ parameter A_WIDTH = 36;
+ parameter B_WIDTH = 36;
+ parameter Y_WIDTH = 72;
+ parameter A_SIGNED = 0;
+ parameter B_SIGNED = 0;
+
+ MULT36X36 #(
+ .REGINPUTA("BYPASS"),
+ .REGINPUTB("BYPASS"),
+ .REGOUTPUT("BYPASS")
+ ) _TECHMAP_REPLACE_ (
+ .A(A), .B(B),
+ .SIGNEDA(A_SIGNED ? 1'b1 : 1'b0),
+ .SIGNEDB(B_SIGNED ? 1'b1 : 1'b0),
+ .Z(Y)
+ );
+endmodule
+
+module \$__NX_MUL36X18 (input [35:0] A, input [17:0] B, output [53:0] Y);
+
+ parameter A_WIDTH = 36;
+ parameter B_WIDTH = 18;
+ parameter Y_WIDTH = 54;
+ parameter A_SIGNED = 0;
+ parameter B_SIGNED = 0;
+
+ MULT18X36 #(
+ .REGINPUTA("BYPASS"),
+ .REGINPUTB("BYPASS"),
+ .REGOUTPUT("BYPASS")
+ ) _TECHMAP_REPLACE_ (
+ .A(B), .B(A),
+ .SIGNEDA(B_SIGNED ? 1'b1 : 1'b0),
+ .SIGNEDB(A_SIGNED ? 1'b1 : 1'b0),
+ .Z(Y)
+ );
+endmodule
+
+module \$__NX_MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y);
+
+ parameter A_WIDTH = 18;
+ parameter B_WIDTH = 18;
+ parameter Y_WIDTH = 36;
+ parameter A_SIGNED = 0;
+ parameter B_SIGNED = 0;
+
+ MULT18X18 #(
+ .REGINPUTA("BYPASS"),
+ .REGINPUTB("BYPASS"),
+ .REGOUTPUT("BYPASS")
+ ) _TECHMAP_REPLACE_ (
+ .A(A), .B(B),
+ .SIGNEDA(A_SIGNED ? 1'b1 : 1'b0),
+ .SIGNEDB(B_SIGNED ? 1'b1 : 1'b0),
+ .Z(Y)
+ );
+endmodule
+
+module \$__NX_MUL9X9 (input [8:0] A, input [8:0] B, output [17:0] Y);
+
+ parameter A_WIDTH = 9;
+ parameter B_WIDTH = 9;
+ parameter Y_WIDTH = 18;
+ parameter A_SIGNED = 0;
+ parameter B_SIGNED = 0;
+
+ MULT9X9 #(
+ .REGINPUTA("BYPASS"),
+ .REGINPUTB("BYPASS"),
+ .REGOUTPUT("BYPASS")
+ ) _TECHMAP_REPLACE_ (
+ .A(A), .B(B),
+ .SIGNEDA(A_SIGNED ? 1'b1 : 1'b0),
+ .SIGNEDB(B_SIGNED ? 1'b1 : 1'b0),
+ .Z(Y)
+ );
+endmodule
diff --git a/techlibs/nexus/latches_map.v b/techlibs/nexus/latches_map.v
new file mode 100644
index 000000000..c28f88cf7
--- /dev/null
+++ b/techlibs/nexus/latches_map.v
@@ -0,0 +1,11 @@
+module \$_DLATCH_N_ (E, D, Q);
+ wire [1023:0] _TECHMAP_DO_ = "simplemap; opt";
+ input E, D;
+ output Q = !E ? D : Q;
+endmodule
+
+module \$_DLATCH_P_ (E, D, Q);
+ wire [1023:0] _TECHMAP_DO_ = "simplemap; opt";
+ input E, D;
+ output Q = E ? D : Q;
+endmodule
diff --git a/techlibs/nexus/lrams.txt b/techlibs/nexus/lrams.txt
new file mode 100644
index 000000000..481629b98
--- /dev/null
+++ b/techlibs/nexus/lrams.txt
@@ -0,0 +1,22 @@
+bram $__NX_PDPSC512K
+ init 1
+
+ abits 14
+ dbits 32
+
+ groups 2
+ ports 1 1
+ wrmode 1 0
+ enable 4 1
+ transp 0 0
+ clocks 2 2
+ clkpol 2 2
+endbram
+
+match $__NX_PDPSC512K
+ # explicitly requested LRAM only, due to limited availability and
+ # slower Fmax
+ attribute lram
+ shuffle_enable A
+ make_transp
+endmatch
diff --git a/techlibs/nexus/lrams_init.vh b/techlibs/nexus/lrams_init.vh
new file mode 100644
index 000000000..31a7ba4a8
--- /dev/null
+++ b/techlibs/nexus/lrams_init.vh
@@ -0,0 +1,128 @@
+.INITVAL_00($sformatf("0x%05120x", permute_init(INIT[0 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_01($sformatf("0x%05120x", permute_init(INIT[1 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_02($sformatf("0x%05120x", permute_init(INIT[2 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_03($sformatf("0x%05120x", permute_init(INIT[3 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_04($sformatf("0x%05120x", permute_init(INIT[4 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_05($sformatf("0x%05120x", permute_init(INIT[5 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_06($sformatf("0x%05120x", permute_init(INIT[6 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_07($sformatf("0x%05120x", permute_init(INIT[7 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_08($sformatf("0x%05120x", permute_init(INIT[8 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_09($sformatf("0x%05120x", permute_init(INIT[9 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_0A($sformatf("0x%05120x", permute_init(INIT[10 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_0B($sformatf("0x%05120x", permute_init(INIT[11 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_0C($sformatf("0x%05120x", permute_init(INIT[12 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_0D($sformatf("0x%05120x", permute_init(INIT[13 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_0E($sformatf("0x%05120x", permute_init(INIT[14 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_0F($sformatf("0x%05120x", permute_init(INIT[15 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_10($sformatf("0x%05120x", permute_init(INIT[16 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_11($sformatf("0x%05120x", permute_init(INIT[17 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_12($sformatf("0x%05120x", permute_init(INIT[18 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_13($sformatf("0x%05120x", permute_init(INIT[19 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_14($sformatf("0x%05120x", permute_init(INIT[20 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_15($sformatf("0x%05120x", permute_init(INIT[21 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_16($sformatf("0x%05120x", permute_init(INIT[22 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_17($sformatf("0x%05120x", permute_init(INIT[23 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_18($sformatf("0x%05120x", permute_init(INIT[24 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_19($sformatf("0x%05120x", permute_init(INIT[25 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_1A($sformatf("0x%05120x", permute_init(INIT[26 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_1B($sformatf("0x%05120x", permute_init(INIT[27 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_1C($sformatf("0x%05120x", permute_init(INIT[28 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_1D($sformatf("0x%05120x", permute_init(INIT[29 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_1E($sformatf("0x%05120x", permute_init(INIT[30 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_1F($sformatf("0x%05120x", permute_init(INIT[31 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_20($sformatf("0x%05120x", permute_init(INIT[32 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_21($sformatf("0x%05120x", permute_init(INIT[33 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_22($sformatf("0x%05120x", permute_init(INIT[34 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_23($sformatf("0x%05120x", permute_init(INIT[35 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_24($sformatf("0x%05120x", permute_init(INIT[36 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_25($sformatf("0x%05120x", permute_init(INIT[37 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_26($sformatf("0x%05120x", permute_init(INIT[38 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_27($sformatf("0x%05120x", permute_init(INIT[39 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_28($sformatf("0x%05120x", permute_init(INIT[40 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_29($sformatf("0x%05120x", permute_init(INIT[41 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_2A($sformatf("0x%05120x", permute_init(INIT[42 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_2B($sformatf("0x%05120x", permute_init(INIT[43 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_2C($sformatf("0x%05120x", permute_init(INIT[44 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_2D($sformatf("0x%05120x", permute_init(INIT[45 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_2E($sformatf("0x%05120x", permute_init(INIT[46 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_2F($sformatf("0x%05120x", permute_init(INIT[47 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_30($sformatf("0x%05120x", permute_init(INIT[48 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_31($sformatf("0x%05120x", permute_init(INIT[49 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_32($sformatf("0x%05120x", permute_init(INIT[50 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_33($sformatf("0x%05120x", permute_init(INIT[51 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_34($sformatf("0x%05120x", permute_init(INIT[52 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_35($sformatf("0x%05120x", permute_init(INIT[53 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_36($sformatf("0x%05120x", permute_init(INIT[54 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_37($sformatf("0x%05120x", permute_init(INIT[55 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_38($sformatf("0x%05120x", permute_init(INIT[56 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_39($sformatf("0x%05120x", permute_init(INIT[57 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_3A($sformatf("0x%05120x", permute_init(INIT[58 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_3B($sformatf("0x%05120x", permute_init(INIT[59 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_3C($sformatf("0x%05120x", permute_init(INIT[60 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_3D($sformatf("0x%05120x", permute_init(INIT[61 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_3E($sformatf("0x%05120x", permute_init(INIT[62 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_3F($sformatf("0x%05120x", permute_init(INIT[63 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_40($sformatf("0x%05120x", permute_init(INIT[64 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_41($sformatf("0x%05120x", permute_init(INIT[65 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_42($sformatf("0x%05120x", permute_init(INIT[66 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_43($sformatf("0x%05120x", permute_init(INIT[67 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_44($sformatf("0x%05120x", permute_init(INIT[68 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_45($sformatf("0x%05120x", permute_init(INIT[69 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_46($sformatf("0x%05120x", permute_init(INIT[70 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_47($sformatf("0x%05120x", permute_init(INIT[71 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_48($sformatf("0x%05120x", permute_init(INIT[72 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_49($sformatf("0x%05120x", permute_init(INIT[73 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_4A($sformatf("0x%05120x", permute_init(INIT[74 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_4B($sformatf("0x%05120x", permute_init(INIT[75 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_4C($sformatf("0x%05120x", permute_init(INIT[76 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_4D($sformatf("0x%05120x", permute_init(INIT[77 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_4E($sformatf("0x%05120x", permute_init(INIT[78 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_4F($sformatf("0x%05120x", permute_init(INIT[79 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_50($sformatf("0x%05120x", permute_init(INIT[80 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_51($sformatf("0x%05120x", permute_init(INIT[81 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_52($sformatf("0x%05120x", permute_init(INIT[82 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_53($sformatf("0x%05120x", permute_init(INIT[83 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_54($sformatf("0x%05120x", permute_init(INIT[84 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_55($sformatf("0x%05120x", permute_init(INIT[85 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_56($sformatf("0x%05120x", permute_init(INIT[86 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_57($sformatf("0x%05120x", permute_init(INIT[87 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_58($sformatf("0x%05120x", permute_init(INIT[88 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_59($sformatf("0x%05120x", permute_init(INIT[89 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_5A($sformatf("0x%05120x", permute_init(INIT[90 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_5B($sformatf("0x%05120x", permute_init(INIT[91 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_5C($sformatf("0x%05120x", permute_init(INIT[92 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_5D($sformatf("0x%05120x", permute_init(INIT[93 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_5E($sformatf("0x%05120x", permute_init(INIT[94 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_5F($sformatf("0x%05120x", permute_init(INIT[95 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_60($sformatf("0x%05120x", permute_init(INIT[96 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_61($sformatf("0x%05120x", permute_init(INIT[97 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_62($sformatf("0x%05120x", permute_init(INIT[98 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_63($sformatf("0x%05120x", permute_init(INIT[99 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_64($sformatf("0x%05120x", permute_init(INIT[100 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_65($sformatf("0x%05120x", permute_init(INIT[101 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_66($sformatf("0x%05120x", permute_init(INIT[102 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_67($sformatf("0x%05120x", permute_init(INIT[103 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_68($sformatf("0x%05120x", permute_init(INIT[104 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_69($sformatf("0x%05120x", permute_init(INIT[105 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_6A($sformatf("0x%05120x", permute_init(INIT[106 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_6B($sformatf("0x%05120x", permute_init(INIT[107 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_6C($sformatf("0x%05120x", permute_init(INIT[108 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_6D($sformatf("0x%05120x", permute_init(INIT[109 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_6E($sformatf("0x%05120x", permute_init(INIT[110 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_6F($sformatf("0x%05120x", permute_init(INIT[111 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_70($sformatf("0x%05120x", permute_init(INIT[112 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_71($sformatf("0x%05120x", permute_init(INIT[113 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_72($sformatf("0x%05120x", permute_init(INIT[114 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_73($sformatf("0x%05120x", permute_init(INIT[115 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_74($sformatf("0x%05120x", permute_init(INIT[116 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_75($sformatf("0x%05120x", permute_init(INIT[117 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_76($sformatf("0x%05120x", permute_init(INIT[118 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_77($sformatf("0x%05120x", permute_init(INIT[119 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_78($sformatf("0x%05120x", permute_init(INIT[120 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_79($sformatf("0x%05120x", permute_init(INIT[121 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_7A($sformatf("0x%05120x", permute_init(INIT[122 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_7B($sformatf("0x%05120x", permute_init(INIT[123 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_7C($sformatf("0x%05120x", permute_init(INIT[124 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_7D($sformatf("0x%05120x", permute_init(INIT[125 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_7E($sformatf("0x%05120x", permute_init(INIT[126 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
+.INITVAL_7F($sformatf("0x%05120x", permute_init(INIT[127 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
diff --git a/techlibs/nexus/lrams_map.v b/techlibs/nexus/lrams_map.v
new file mode 100644
index 000000000..938a0e843
--- /dev/null
+++ b/techlibs/nexus/lrams_map.v
@@ -0,0 +1,56 @@
+module \$__NX_PDPSC512K (CLK2, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+ parameter CFG_ABITS = 14;
+ parameter CFG_DBITS = 32;
+ parameter CFG_ENABLE_A = 4;
+
+ parameter CLKPOL2 = 1;
+ parameter [524287:0] INIT = 524287'b0;
+
+ input CLK2;
+
+ input [CFG_ABITS-1:0] A1ADDR;
+ input [CFG_DBITS-1:0] A1DATA;
+ input [CFG_ENABLE_A-1:0] A1EN;
+
+ input [CFG_ABITS-1:0] B1ADDR;
+ output [CFG_DBITS-1:0] B1DATA;
+ input B1EN;
+
+ wire clk;
+ wire [31:0] rd;
+ assign B1DATA = rd[CFG_DBITS-1:0];
+
+ generate
+ if (CLKPOL2)
+ assign clk = CLK2;
+ else
+ INV clk_inv_i (.A(CLK2), .Z(clk));
+ endgenerate
+
+ wire we = |A1EN;
+
+ localparam INIT_CHUNK_SIZE = 4096;
+
+ function [5119:0] permute_init;
+ input [INIT_CHUNK_SIZE-1:0] chunk;
+ integer i;
+ begin
+ for (i = 0; i < 128; i = i + 1'b1)
+ permute_init[i * 40 +: 40] = {8'b0, chunk[i * 32 +: 32]};
+ end
+ endfunction
+
+ generate
+ PDPSC512K #(
+ .OUTREG("NO_REG"),
+ .ECC_BYTE_SEL("BYTE_EN"),
+`include "lrams_init.vh"
+ .GSR("DISABLED")
+ ) _TECHMAP_REPLACE_ (
+ .CLK(clk), .RSTR(1'b0),
+ .DI(A1DATA), .ADW(A1ADDR), .CEW(we), .WE(we), .CSW(1'b1),
+ .ADR(B1ADDR), .DO(rd), .CER(B1EN), .CSR(1'b1),
+ );
+ endgenerate
+
+endmodule
diff --git a/techlibs/nexus/lutrams.txt b/techlibs/nexus/lutrams.txt
new file mode 100644
index 000000000..2568b9998
--- /dev/null
+++ b/techlibs/nexus/lutrams.txt
@@ -0,0 +1,26 @@
+bram $__NEXUS_DPR16X4
+ init 1
+ abits 4
+ dbits 4
+ groups 2
+ ports 1 1
+ wrmode 0 1
+ enable 0 1
+ transp 0 0
+ clocks 0 1
+ clkpol 0 2
+endbram
+
+# The syn_* attributes are described in:
+# https://www.latticesemi.com/-/media/LatticeSemi/Documents/Tutorials/AK/LatticeDiamondTutorial311.ashx
+attr_icase 1
+
+match $__NEXUS_DPR16X4
+ attribute !syn_ramstyle syn_ramstyle=auto syn_ramstyle=distributed
+ attribute !syn_romstyle syn_romstyle=auto
+ attribute !ram_block
+ attribute !rom_block
+ attribute !logic_block
+ make_outreg
+ min wports 1
+endmatch
diff --git a/techlibs/nexus/lutrams_map.v b/techlibs/nexus/lutrams_map.v
new file mode 100644
index 000000000..0910664ce
--- /dev/null
+++ b/techlibs/nexus/lutrams_map.v
@@ -0,0 +1,34 @@
+module \$__NEXUS_DPR16X4 (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
+ parameter [63:0] INIT = 64'b0;
+ parameter CLKPOL2 = 1;
+ input CLK1;
+
+ input [3:0] A1ADDR;
+ output [3:0] A1DATA;
+
+ input [3:0] B1ADDR;
+ input [3:0] B1DATA;
+ input B1EN;
+
+
+ wire wck;
+
+ generate
+ if (CLKPOL2)
+ assign wck = CLK1;
+ else
+ INV wck_inv_i (.A(CLK1), .Z(wck));
+ endgenerate
+
+ DPR16X4 #(
+ .INITVAL($sformatf("0x%08x", INIT))
+ ) _TECHMAP_REPLACE_ (
+ .RAD(A1ADDR),
+ .DO(A1DATA),
+
+ .WAD(B1ADDR),
+ .DI(B1DATA),
+ .WCK(CLK1),
+ .WRE(B1EN)
+ );
+endmodule
diff --git a/techlibs/nexus/parse_init.vh b/techlibs/nexus/parse_init.vh
new file mode 100644
index 000000000..0f9ab7897
--- /dev/null
+++ b/techlibs/nexus/parse_init.vh
@@ -0,0 +1,33 @@
+function [15:0] parse_init;
+ input [((2+(16/4))*8)-1:0] init;
+ reg [7:0] c;
+ integer i;
+ begin
+ for (i = 0; i < (16/4); i = i + 1) begin
+ c = init[(i * 8) +: 8];
+ if (c >= "0" && c <= "9")
+ parse_init[(i * 4) +: 4] = (c - "0");
+ else if (c >= "A" && c <= "F")
+ parse_init[(i * 4) +: 4] = (c - "A") + 10;
+ else if (c >= "a" && c <= "f")
+ parse_init[(i * 4) +: 4] = (c - "a") + 10;
+ end
+ end
+endfunction
+
+function [63:0] parse_init_64;
+ input [((2+(64/4))*8)-1:0] init;
+ reg [7:0] c;
+ integer i;
+ begin
+ for (i = 0; i < (64/4); i = i + 1) begin
+ c = init[(i * 8) +: 8];
+ if (c >= "0" && c <= "9")
+ parse_init_64[(i * 4) +: 4] = (c - "0");
+ else if (c >= "A" && c <= "F")
+ parse_init_64[(i * 4) +: 4] = (c - "A") + 10;
+ else if (c >= "a" && c <= "f")
+ parse_init_64[(i * 4) +: 4] = (c - "a") + 10;
+ end
+ end
+endfunction
diff --git a/techlibs/nexus/synth_nexus.cc b/techlibs/nexus/synth_nexus.cc
new file mode 100644
index 000000000..03bff0649
--- /dev/null
+++ b/techlibs/nexus/synth_nexus.cc
@@ -0,0 +1,426 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * 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
+ * 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 SynthNexusPass : public ScriptPass
+{
+ SynthNexusPass() : ScriptPass("synth_nexus", "synthesis for Lattice Nexus FPGAs") { }
+
+ void on_register() override
+ {
+ RTLIL::constpad["synth_nexus.abc9.W"] = "300";
+ }
+
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" synth_nexus [options]\n");
+ log("\n");
+ log("This command runs synthesis for Lattice Nexus FPGAs.\n");
+ log("\n");
+ log(" -top <module>\n");
+ log(" use the specified module as top module\n");
+ log("\n");
+ log(" -family <device>\n");
+ log(" run synthesis for the specified Nexus device\n");
+ log(" supported values: lifcl, lfd2nx\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(" -vm <file>\n");
+ log(" write the design to the specified structural Verilog file. writing of\n");
+ log(" an output file 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(" -dff\n");
+ log(" run 'abc'/'abc9' with -dff option\n");
+ log("\n");
+ log(" -retime\n");
+ log(" run 'abc' with '-dff -D 1' options\n");
+ log("\n");
+ log(" -noccu2\n");
+ log(" do not use CCU2 cells in output netlist\n");
+ log("\n");
+ log(" -nodffe\n");
+ log(" do not use flipflops with CE in output netlist\n");
+ log("\n");
+ log(" -nolram\n");
+ log(" do not use large RAM cells in output netlist\n");
+ log(" note that large RAM must be explicitly requested with a (* lram *)\n");
+ log(" attribute on the memory.\n");
+ log("\n");
+ log(" -nobram\n");
+ log(" do not use block RAM cells in output netlist\n");
+ log("\n");
+ log(" -nolutram\n");
+ log(" do not use LUT RAM cells in output netlist\n");
+ log("\n");
+ log(" -nowidelut\n");
+ log(" do not use PFU muxes to implement LUTs larger than LUT4s\n");
+ log("\n");
+ log(" -noiopad\n");
+ log(" do not insert IO buffers\n");
+ log("\n");
+ log(" -nodsp\n");
+ log(" do not infer DSP multipliers\n");
+ log("\n");
+ log(" -abc9\n");
+ log(" use new ABC9 flow (EXPERIMENTAL)\n");
+ log("\n");
+ log("The following commands are executed by this synthesis command:\n");
+ help_script();
+ log("\n");
+ }
+
+ string top_opt, json_file, vm_file, family;
+ bool noccu2, nodffe, nolram, nobram, nolutram, nowidelut, noiopad, nodsp, flatten, dff, retime, abc9;
+
+ void clear_flags() override
+ {
+ top_opt = "-auto-top";
+ family = "lifcl";
+ json_file = "";
+ vm_file = "";
+ noccu2 = false;
+ nodffe = false;
+ nolram = false;
+ nobram = false;
+ nolutram = false;
+ nowidelut = false;
+ noiopad = false;
+ nodsp = false;
+ flatten = true;
+ dff = false;
+ retime = 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] == "-json" && argidx+1 < args.size()) {
+ json_file = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-vm" && argidx+1 < args.size()) {
+ vm_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] == "-family") && argidx+1 < args.size()) {
+ family = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-flatten") {
+ flatten = true;
+ continue;
+ }
+ if (args[argidx] == "-noflatten") {
+ flatten = false;
+ continue;
+ }
+ if (args[argidx] == "-dff") {
+ dff = true;
+ continue;
+ }
+ if (args[argidx] == "-nodsp") {
+ nodsp = true;
+ continue;
+ }
+ if (args[argidx] == "-retime") {
+ retime = true;
+ continue;
+ }
+ if (args[argidx] == "-noccu2") {
+ noccu2 = true;
+ continue;
+ }
+ if (args[argidx] == "-nodffe") {
+ nodffe = true;
+ continue;
+ }
+ if (args[argidx] == "-nolram") {
+ nolram = true;
+ continue;
+ }
+ if (args[argidx] == "-nobram") {
+ nobram = true;
+ continue;
+ }
+ if (args[argidx] == "-nolutram") {
+ nolutram = true;
+ continue;
+ }
+ if (args[argidx] == "-nowidelut") {
+ nowidelut = true;
+ continue;
+ }
+ if (args[argidx] == "-noiopad") {
+ noiopad = true;
+ continue;
+ }
+ if (args[argidx] == "-abc9") {
+ abc9 = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ if (!design->full_selection())
+ log_cmd_error("This command only operates on fully selected designs!\n");
+
+ if (abc9 && retime)
+ log_cmd_error("-retime option not currently compatible with -abc9!\n");
+
+ log_header(design, "Executing SYNTH_NEXUS pass.\n");
+ log_push();
+
+ run_script(design, run_from, run_to);
+
+ log_pop();
+ }
+
+ struct DSPRule {
+ int a_maxwidth;
+ int b_maxwidth;
+ int a_minwidth;
+ int b_minwidth;
+ std::string prim;
+ };
+
+ const std::vector<DSPRule> dsp_rules = {
+ {36, 36, 22, 22, "$__NX_MUL36X36"},
+ {36, 18, 22, 10, "$__NX_MUL36X18"},
+ {18, 18, 10, 4, "$__NX_MUL18X18"},
+ {18, 18, 4, 10, "$__NX_MUL18X18"},
+ { 9, 9, 4, 4, "$__NX_MUL9X9"},
+ };
+
+ void script() override
+ {
+
+ if (family != "lifcl" && family != "lfd2nx")
+ log_cmd_error("Invalid Nexus -family setting: '%s'.\n", family.c_str());
+
+ if (check_label("begin"))
+ {
+ run("read_verilog -lib -specify +/nexus/cells_sim.v +/nexus/cells_xtra.v");
+ run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
+ }
+
+ if (check_label("coarse"))
+ {
+ run("proc");
+ if (flatten || help_mode)
+ 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");
+
+ if (help_mode) {
+ run("techmap -map +/mul2dsp.v [...]", "(unless -nodsp)");
+ run("techmap -map +/nexus/dsp_map.v", "(unless -nodsp)");
+ } else if (!nodsp) {
+ for (const auto &rule : dsp_rules) {
+ run(stringf("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=%d -D DSP_B_MAXWIDTH=%d -D DSP_A_MINWIDTH=%d -D DSP_B_MINWIDTH=%d -D DSP_NAME=%s",
+ rule.a_maxwidth, rule.b_maxwidth, rule.a_minwidth, rule.b_minwidth, rule.prim.c_str()));
+ run("chtype -set $mul t:$__soft_mul");
+ }
+ run("techmap -map +/nexus/dsp_map.v");
+ }
+
+ run("alumacc");
+ run("opt");
+ run("memory -nomap");
+ run("opt_clean");
+ }
+
+ if (!nolram && check_label("map_lram", "(skip if -nolram)"))
+ {
+ run("memory_bram -rules +/nexus/lrams.txt");
+ run("setundef -zero -params t:$__NX_PDPSC512K");
+ run("techmap -map +/nexus/lrams_map.v");
+ }
+
+ if (!nobram && check_label("map_bram", "(skip if -nobram)"))
+ {
+ run("memory_bram -rules +/nexus/brams.txt");
+ run("setundef -zero -params t:$__NX_PDP16K");
+ run("techmap -map +/nexus/brams_map.v");
+ }
+
+ if (!nolutram && check_label("map_lutram", "(skip if -nolutram)"))
+ {
+ run("memory_bram -rules +/nexus/lutrams.txt");
+ run("setundef -zero -params t:$__NEXUS_DPR16X4");
+ run("techmap -map +/nexus/lutrams_map.v");
+ }
+
+ 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"))
+ {
+ if (noccu2)
+ run("techmap");
+ 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 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)");
+ }
+
+ if (check_label("map_ffs"))
+ {
+ run("opt_clean");
+ std::string dfflegalize_args = " -cell $_DFF_P_ 01 -cell $_DFF_PP?_ r -cell $_SDFF_PP?_ r -cell $_DLATCH_?_ x";
+ if (help_mode) {
+ dfflegalize_args += " [-cell $_DFFE_PP_ 01 -cell $_DFFE_PP?P_ r -cell $_SDFFE_PP?P_ r]";
+ } else if (!nodffe) {
+ dfflegalize_args += " -cell $_DFFE_PP_ 01 -cell $_DFFE_PP?P_ r -cell $_SDFFE_PP?P_ r";
+ }
+ run("dfflegalize" + dfflegalize_args, "($_*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("techmap -D NO_LUT -map +/nexus/cells_map.v");
+ run("opt_expr -undriven -mux_undef");
+ run("simplemap");
+ run("attrmvcp -copy -attr syn_useioff");
+ run("opt_clean");
+ }
+
+ if (check_label("map_luts"))
+ {
+ run("techmap -map +/nexus/latches_map.v");
+
+ if (abc9) {
+ std::string abc9_opts;
+ if (nowidelut)
+ abc9_opts += " -maxlut 4";
+ std::string k = "synth_nexus.abc9.W";
+ if (active_design && active_design->scratchpad.count(k))
+ abc9_opts += stringf(" -W %s", active_design->scratchpad_get_string(k).c_str());
+ else
+ abc9_opts += stringf(" -W %s", RTLIL::constpad.at(k).c_str());
+ if (nowidelut)
+ abc9_opts += " -maxlut 4";
+ if (dff)
+ abc9_opts += " -dff";
+ run("abc9" + abc9_opts);
+ } else {
+ std::string abc_args = " -dress";
+ if (nowidelut)
+ abc_args += " -lut 4";
+ else
+ abc_args += " -lut 4:5";
+ if (dff)
+ abc_args += " -dff";
+ run("abc" + abc_args);
+ }
+ run("clean");
+ }
+
+ if (check_label("map_cells"))
+ {
+ run("techmap -map +/nexus/cells_map.v");
+
+ // This is needed for Radiant, but perhaps not optimal for nextpnr...
+ run("setundef -zero");
+
+ run("hilomap -singleton -hicell VHI Z -locell VLO Z");
+ run("clean");
+ }
+
+ if (check_label("check"))
+ {
+ run("autoname");
+ run("hierarchy -check");
+ run("stat");
+ run("check -noinit");
+ run("blackbox =A:whitebox");
+ }
+
+ if (check_label("json"))
+ {
+ if (!json_file.empty() || help_mode)
+ run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));
+ }
+
+ if (check_label("vm"))
+ {
+ if (!vm_file.empty() || help_mode)
+ run(stringf("write_verilog %s", help_mode ? "<file-name>" : vm_file.c_str()));
+ }
+ }
+} SynthNexusPass;
+
+PRIVATE_NAMESPACE_END
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/Makefile.inc b/techlibs/sf2/Makefile.inc
index cc3054ace..cade49f37 100644
--- a/techlibs/sf2/Makefile.inc
+++ b/techlibs/sf2/Makefile.inc
@@ -1,6 +1,5 @@
OBJS += techlibs/sf2/synth_sf2.o
-OBJS += techlibs/sf2/sf2_iobs.o
$(eval $(call add_share_file,share/sf2,techlibs/sf2/arith_map.v))
$(eval $(call add_share_file,share/sf2,techlibs/sf2/cells_map.v))
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_map.v b/techlibs/sf2/cells_map.v
index 70f3b3b16..88782995e 100644
--- a/techlibs/sf2/cells_map.v
+++ b/techlibs/sf2/cells_map.v
@@ -1,59 +1,27 @@
-module \$_DFF_N_ (input D, C, output Q);
- SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(1'b1), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
+module \$_DFFE_PN0P_ (input D, C, R, E, output Q);
+ SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(E), .ALn(R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
endmodule
-module \$_DFF_P_ (input D, C, output Q);
- SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(1'b1), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
+module \$_DFFE_PN1P_ (input D, C, R, E, output Q);
+ SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(E), .ALn(R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
endmodule
-module \$_DFF_NN0_ (input D, C, R, output Q);
- SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
+module \$_SDFFCE_PN0P_ (input D, C, R, E, output Q);
+ SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(E), .ALn(1'b1), .ADn(1'b0), .SLn(R), .SD(1'b0), .LAT(1'b0), .Q(Q));
endmodule
-module \$_DFF_NN1_ (input D, C, R, output Q);
- SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
+module \$_SDFFCE_PN1P_ (input D, C, R, E, output Q);
+ SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(E), .ALn(1'b1), .ADn(1'b0), .SLn(R), .SD(1'b1), .LAT(1'b0), .Q(Q));
endmodule
-module \$_DFF_NP0_ (input D, C, R, output Q);
- SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(!R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
+module \$_DLATCH_PN0_ (input D, R, E, output Q);
+ SLE _TECHMAP_REPLACE_ (.D(D), .CLK(E), .EN(1'b1), .ALn(R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b1), .Q(Q));
endmodule
-module \$_DFF_NP1_ (input D, C, R, output Q);
- SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(!R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
+module \$_DLATCH_PN1_ (input D, R, E, output Q);
+ SLE _TECHMAP_REPLACE_ (.D(D), .CLK(E), .EN(1'b1), .ALn(R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b1), .Q(Q));
endmodule
-module \$_DFF_PN0_ (input D, C, R, output Q);
- SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
-endmodule
-
-module \$_DFF_PN1_ (input D, C, R, output Q);
- SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
-endmodule
-
-module \$_DFF_PP0_ (input D, C, R, output Q);
- SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(!R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
-endmodule
-
-module \$_DFF_PP1_ (input D, C, R, output Q);
- SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(!R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
-endmodule
-
-// module \$_DFFE_NN_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule
-// module \$_DFFE_PN_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule
-//
-// module \$_DFFE_NP_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule
-// module \$_DFFE_PP_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule
-//
-// module \$_DFFE_NN0P_ (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule
-// module \$_DFFE_NN1P_ (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule
-// module \$_DFFE_PN0P_ (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule
-// module \$_DFFE_PN1P_ (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule
-//
-// module \$_DFFE_NP0P_ (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule
-// module \$_DFFE_NP1P_ (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule
-// module \$_DFFE_PP0P_ (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule
-// module \$_DFFE_PP1P_ (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule
-
`ifndef NO_LUT
module \$lut (A, Y);
parameter WIDTH = 0;
diff --git a/techlibs/sf2/cells_sim.v b/techlibs/sf2/cells_sim.v
index c62748b11..4b57bad7b 100644
--- a/techlibs/sf2/cells_sim.v
+++ b/techlibs/sf2/cells_sim.v
@@ -1,21 +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
);
@@ -76,6 +75,7 @@ endmodule
module CLKINT (
input A,
+ (* clkbuf_driver *)
output Y
);
assign Y = A;
@@ -83,6 +83,7 @@ endmodule
module CLKINT_PRESERVE (
input A,
+ (* clkbuf_driver *)
output Y
);
assign Y = A;
@@ -90,6 +91,7 @@ endmodule
module GCLKINT (
input A, EN,
+ (* clkbuf_driver *)
output Y
);
assign Y = A & EN;
@@ -97,6 +99,7 @@ endmodule
module RCLKINT (
input A,
+ (* clkbuf_driver *)
output Y
);
assign Y = A;
@@ -104,6 +107,7 @@ endmodule
module RGCLKINT (
input A, EN,
+ (* clkbuf_driver *)
output Y
);
assign Y = A & EN;
@@ -113,6 +117,7 @@ module SLE (
output Q,
input ADn,
input ALn,
+ (* clkbuf_sink *)
input CLK,
input D,
input LAT,
@@ -155,9 +160,41 @@ endmodule
// module SYSRESET
// module SYSCTRL_RESET_STATUS
// module LIVE_PROBE_FB
-// module GCLKBUF
-// module GCLKBUF_DIFF
-// module GCLKBIBUF
+
+(* blackbox *)
+module GCLKBUF (
+ (* iopad_external_pin *)
+ input PAD,
+ input EN,
+ (* clkbuf_driver *)
+ output Y
+);
+endmodule
+
+(* blackbox *)
+module GCLKBUF_DIFF (
+ (* iopad_external_pin *)
+ input PADP,
+ (* iopad_external_pin *)
+ input PADN,
+ input EN,
+ (* clkbuf_driver *)
+ output Y
+);
+endmodule
+
+(* blackbox *)
+module GCLKBIBUF (
+ input D,
+ input E,
+ input EN,
+ (* iopad_external_pin *)
+ inout PAD,
+ (* clkbuf_driver *)
+ output Y
+);
+endmodule
+
// module DFN1
// module DFN1C0
// module DFN1E1
@@ -288,38 +325,118 @@ module XOR8 (
endmodule
// module UJTAG
-// module BIBUF
-// module BIBUF_DIFF
-// module CLKBIBUF
+
+module BIBUF (
+ input D,
+ input E,
+ (* iopad_external_pin *)
+ inout PAD,
+ output Y
+);
+ assign PAD = E ? D : 1'bz;
+ assign Y = PAD;
+endmodule
+
+(* blackbox *)
+module BIBUF_DIFF (
+ input D,
+ input E,
+ (* iopad_external_pin *)
+ inout PADP,
+ (* iopad_external_pin *)
+ inout PADN,
+ output Y
+);
+endmodule
+
+module CLKBIBUF (
+ input D,
+ input E,
+ (* iopad_external_pin *)
+ inout PAD,
+ (* clkbuf_driver *)
+ output Y
+);
+ assign PAD = E ? D : 1'bz;
+ assign Y = PAD;
+endmodule
module CLKBUF (
+ (* iopad_external_pin *)
input PAD,
+ (* clkbuf_driver *)
output Y
);
assign Y = PAD;
endmodule
-// module CLKBUF_DIFF
+(* blackbox *)
+module CLKBUF_DIFF (
+ (* iopad_external_pin *)
+ input PADP,
+ (* iopad_external_pin *)
+ input PADN,
+ (* clkbuf_driver *)
+ output Y
+);
+endmodule
module INBUF (
+ (* iopad_external_pin *)
input PAD,
output Y
);
assign Y = PAD;
endmodule
-// module INBUF_DIFF
+(* blackbox *)
+module INBUF_DIFF (
+ (* iopad_external_pin *)
+ input PADP,
+ (* iopad_external_pin *)
+ input PADN,
+ output Y
+);
+endmodule
module OUTBUF (
input D,
+ (* iopad_external_pin *)
output PAD
);
assign PAD = D;
endmodule
-// module OUTBUF_DIFF
-// module TRIBUFF
-// module TRIBUFF_DIFF
+(* blackbox *)
+module OUTBUF_DIFF (
+ input D,
+ (* iopad_external_pin *)
+ output PADP,
+ (* iopad_external_pin *)
+ output PADN
+);
+endmodule
+
+module TRIBUFF (
+ input D,
+ input E,
+ (* iopad_external_pin *)
+ output PAD
+);
+ assign PAD = E ? D : 1'bz;
+endmodule
+
+(* blackbox *)
+module TRIBUFF_DIFF (
+ input D,
+ input E,
+ (* iopad_external_pin *)
+ output PADP,
+ (* iopad_external_pin *)
+ output PADN
+);
+endmodule
+
// module DDR_IN
// module DDR_OUT
// module RAM1K18
diff --git a/techlibs/sf2/sf2_iobs.cc b/techlibs/sf2/sf2_iobs.cc
deleted file mode 100644
index 5fd719ce5..000000000
--- a/techlibs/sf2/sf2_iobs.cc
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * yosys -- Yosys Open SYnthesis Suite
- *
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#include "kernel/yosys.h"
-#include "kernel/sigtools.h"
-
-USING_YOSYS_NAMESPACE
-PRIVATE_NAMESPACE_BEGIN
-
-static void handle_iobufs(Module *module, bool clkbuf_mode)
-{
- SigMap sigmap(module);
-
- pool<SigBit> clk_bits;
- pool<SigBit> handled_io_bits;
- dict<SigBit, SigBit> rewrite_bits;
- vector<pair<Cell*, SigBit>> pad_bits;
-
- for (auto cell : module->cells())
- {
- if (clkbuf_mode && cell->type == ID(SLE)) {
- for (auto bit : sigmap(cell->getPort(ID::CLK)))
- clk_bits.insert(bit);
- }
- if (cell->type.in(ID(INBUF), ID(OUTBUF), ID(TRIBUFF), ID(BIBUF), ID(CLKBUF), ID(CLKBIBUF),
- ID(INBUF_DIFF), ID(OUTBUF_DIFF), ID(BIBUFF_DIFF), ID(TRIBUFF_DIFF), ID(CLKBUF_DIFF),
- ID(GCLKBUF), ID(GCLKBUF_DIFF), ID(GCLKBIBUF))) {
- for (auto bit : sigmap(cell->getPort(ID(PAD))))
- handled_io_bits.insert(bit);
- }
- }
-
- for (auto wire : vector<Wire*>(module->wires()))
- {
- if (!wire->port_input && !wire->port_output)
- continue;
-
- for (int index = 0; index < GetSize(wire); index++)
- {
- SigBit bit(wire, index);
- SigBit canonical_bit = sigmap(bit);
-
- if (handled_io_bits.count(canonical_bit))
- continue;
-
- if (wire->port_input && wire->port_output)
- log_error("Failed to add buffer for inout port bit %s.\n", log_signal(bit));
-
- IdString buf_type, buf_port;
-
- if (wire->port_output) {
- buf_type = ID(OUTBUF);
- buf_port = ID::D;
- } else if (clkbuf_mode && clk_bits.count(canonical_bit)) {
- buf_type = ID(CLKBUF);
- buf_port = ID::Y;
- } else {
- buf_type = ID(INBUF);
- buf_port = ID::Y;
- }
-
- Cell *c = module->addCell(NEW_ID, buf_type);
- SigBit new_bit = module->addWire(NEW_ID);
- c->setPort(buf_port, new_bit);
- pad_bits.push_back(make_pair(c, bit));
- rewrite_bits[canonical_bit] = new_bit;
-
- log("Added %s cell %s for port bit %s.\n", log_id(c->type), log_id(c), log_signal(bit));
- }
- }
-
- auto rewrite_function = [&](SigSpec &s) {
- for (auto &bit : s) {
- SigBit canonical_bit = sigmap(bit);
- if (rewrite_bits.count(canonical_bit))
- bit = rewrite_bits.at(canonical_bit);
- }
- };
-
- module->rewrite_sigspecs(rewrite_function);
-
- for (auto &it : pad_bits)
- it.first->setPort(ID(PAD), it.second);
-}
-
-static void handle_clkint(Module *module)
-{
- SigMap sigmap(module);
-
- pool<SigBit> clk_bits;
- vector<SigBit> handled_clk_bits;
-
- for (auto cell : module->cells())
- {
- if (cell->type == ID(SLE)) {
- for (auto bit : sigmap(cell->getPort(ID::CLK)))
- clk_bits.insert(bit);
- }
- if (cell->type.in(ID(CLKBUF), ID(CLKBIBUF), ID(CLKBUF_DIFF), ID(GCLKBUF), ID(GCLKBUF_DIFF), ID(GCLKBIBUF),
- ID(CLKINT), ID(CLKINT_PRESERVE), ID(GCLKINT), ID(RCLKINT), ID(RGCLKINT))) {
- for (auto bit : sigmap(cell->getPort(ID::Y)))
- handled_clk_bits.push_back(bit);
- }
- }
-
- for (auto bit : handled_clk_bits)
- clk_bits.erase(bit);
-
- for (auto cell : vector<Cell*>(module->cells()))
- for (auto &conn : cell->connections())
- {
- if (!cell->output(conn.first))
- continue;
-
- SigSpec sig = conn.second;
- bool did_something = false;
-
- for (auto &bit : sig) {
- SigBit canonical_bit = sigmap(bit);
- if (clk_bits.count(canonical_bit)) {
- Cell *c = module->addCell(NEW_ID, ID(CLKINT));
- SigBit new_bit = module->addWire(NEW_ID);
- c->setPort(ID::A, new_bit);
- c->setPort(ID::Y, bit);
- log("Added %s cell %s for clock signal %s.\n", log_id(c->type), log_id(c), log_signal(bit));
- clk_bits.erase(canonical_bit);
- did_something = true;
- bit = new_bit;
- }
- }
-
- if (did_something)
- cell->setPort(conn.first, sig);
- }
-
- for (auto bit : clk_bits)
- log_error("Failed to insert CLKINT for clock signal %s.\n", log_signal(bit));
-}
-
-struct Sf2IobsPass : public Pass {
- Sf2IobsPass() : Pass("sf2_iobs", "SF2: insert IO buffers") { }
- void help() override
- {
- // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
- log("\n");
- log(" sf2_iobs [options] [selection]\n");
- log("\n");
- log("Add SF2 I/O buffers and global buffers to top module as needed.\n");
- log("\n");
- log(" -clkbuf\n");
- log(" Insert PAD->global_net clock buffers\n");
- log("\n");
- }
- void execute(std::vector<std::string> args, RTLIL::Design *design) override
- {
- bool clkbuf_mode = false;
-
- log_header(design, "Executing sf2_iobs pass (insert IO buffers).\n");
-
- size_t argidx;
- for (argidx = 1; argidx < args.size(); argidx++)
- {
- if (args[argidx] == "-clkbuf") {
- clkbuf_mode = true;
- continue;
- }
- break;
- }
- extra_args(args, argidx, design);
-
- Module *module = design->top_module();
-
- if (module == nullptr)
- log_cmd_error("No top module found.\n");
-
- handle_iobufs(module, clkbuf_mode);
- handle_clkint(module);
- }
-} Sf2IobsPass;
-
-PRIVATE_NAMESPACE_END
diff --git a/techlibs/sf2/synth_sf2.cc b/techlibs/sf2/synth_sf2.cc
index 6b2a3f9b8..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
@@ -187,6 +187,7 @@ struct SynthSf2Pass : public ScriptPass
if (check_label("map_ffs"))
{
+ run("dfflegalize -cell $_DFFE_PN?P_ x -cell $_SDFFCE_PN?P_ x -cell $_DLATCH_PN?_ x");
run("techmap -D NO_LUT -map +/sf2/cells_map.v");
run("opt_expr -mux_undef");
run("simplemap");
@@ -209,10 +210,16 @@ struct SynthSf2Pass : public ScriptPass
if (check_label("map_iobs"))
{
- if (help_mode)
- run("sf2_iobs [-clkbuf]", "(unless -noiobs)");
- else if (iobs)
- run(clkbuf ? "sf2_iobs -clkbuf" : "sf2_iobs");
+ if (help_mode || iobs) {
+ if (help_mode) {
+ run("clkbufmap -buf CLKINT Y:A [-inpad CLKBUF Y:PAD]", "(unless -noiobs, -inpad only passed if -clkbuf)");
+ } else if (clkbuf) {
+ run("clkbufmap -buf CLKINT Y:A -inpad CLKBUF Y:PAD");
+ } else {
+ run("clkbufmap -buf CLKINT Y:A");
+ }
+ run("iopadmap -bits -inpad INBUF Y:PAD -outpad OUTBUF D:PAD -toutpad TRIBUFF E:D:PAD -tinoutpad BIBUF E:Y:D:PAD", "(unless -noiobs");
+ }
run("clean");
}
@@ -221,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/Makefile.inc b/techlibs/xilinx/Makefile.inc
index d4d863831..ba87278de 100644
--- a/techlibs/xilinx/Makefile.inc
+++ b/techlibs/xilinx/Makefile.inc
@@ -42,8 +42,7 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut4_lutrams.txt))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut6_lutrams.txt))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lutrams_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v))
-$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_ff_map.v))
-$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_ff_map.v))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/ff_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/mux_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc3s_mult_map.v))
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 2fc216908..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
@@ -35,13 +35,7 @@ module _80_xilinx_lcu (P, G, CI, CO);
genvar i;
-`ifdef _EXPLICIT_CARRY
- localparam EXPLICIT_CARRY = 1'b1;
-`else
- localparam EXPLICIT_CARRY = 1'b0;
-`endif
-
-generate if (EXPLICIT_CARRY || `LUT_SIZE == 4) begin
+generate if (`LUT_SIZE == 4) begin
(* force_downto *)
wire [WIDTH-1:0] C = {CO, CI};
@@ -135,12 +129,6 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
genvar i;
-`ifdef _EXPLICIT_CARRY
- localparam EXPLICIT_CARRY = 1'b1;
-`else
- localparam EXPLICIT_CARRY = 1'b0;
-`endif
-
generate if (`LUT_SIZE == 4) begin
(* force_downto *)
@@ -163,105 +151,7 @@ generate if (`LUT_SIZE == 4) begin
);
end endgenerate
-end else if (EXPLICIT_CARRY) begin
-
- (* force_downto *)
- wire [Y_WIDTH-1:0] S = AA ^ BB;
-
- wire CINIT;
- // Carry chain.
- //
- // VPR requires that the carry chain never hit the fabric. The CO input
- // to this techmap is the carry outputs for synthesis, e.g. might hit the
- // fabric.
- //
- // So we maintain two wire sets, CO_CHAIN is the carry that is for VPR,
- // e.g. off fabric dedicated chain. CO is the carry outputs that are
- // available to the fabric.
- (* force_downto *)
- wire [Y_WIDTH-1:0] CO_CHAIN;
- (* force_downto *)
- wire [Y_WIDTH-1:0] C = {CO_CHAIN, CINIT};
-
- // If carry chain is being initialized to a constant, techmap the constant
- // source. Otherwise techmap the fabric source.
- generate for (i = 0; i < 1; i = i + 1) begin:slice
- CARRY0 #(.CYINIT_FABRIC(1)) carry(
- .CI_INIT(CI),
- .DI(AA[0]),
- .S(S[0]),
- .CO_CHAIN(CO_CHAIN[0]),
- .CO_FABRIC(CO[0]),
- .O(Y[0])
- );
- end endgenerate
-
- generate for (i = 1; i < Y_WIDTH-1; i = i + 1) begin:slice
- if(i % 4 == 0) begin
- CARRY0 carry (
- .CI(C[i]),
- .DI(AA[i]),
- .S(S[i]),
- .CO_CHAIN(CO_CHAIN[i]),
- .CO_FABRIC(CO[i]),
- .O(Y[i])
- );
- end
- else
- begin
- CARRY carry (
- .CI(C[i]),
- .DI(AA[i]),
- .S(S[i]),
- .CO_CHAIN(CO_CHAIN[i]),
- .CO_FABRIC(CO[i]),
- .O(Y[i])
- );
- end
- end endgenerate
-
- generate for (i = Y_WIDTH-1; i < Y_WIDTH; i = i + 1) begin:slice
- if(i % 4 == 0) begin
- CARRY0 top_of_carry (
- .CI(C[i]),
- .DI(AA[i]),
- .S(S[i]),
- .CO_CHAIN(CO_CHAIN[i]),
- .O(Y[i])
- );
- end
- else
- begin
- CARRY top_of_carry (
- .CI(C[i]),
- .DI(AA[i]),
- .S(S[i]),
- .CO_CHAIN(CO_CHAIN[i]),
- .O(Y[i])
- );
- end
- // Turns out CO_FABRIC and O both use [ABCD]MUX, so provide
- // a non-congested path to output the top of the carry chain.
- // Registering the output of the CARRY block would solve this, but not
- // all designs do that.
- if((i+1) % 4 == 0) begin
- CARRY0 carry_output (
- .CI(CO_CHAIN[i]),
- .DI(0),
- .S(0),
- .O(CO[i])
- );
- end
- else
- begin
- CARRY carry_output (
- .CI(CO_CHAIN[i]),
- .DI(0),
- .S(0),
- .O(CO[i])
- );
- end
- end endgenerate
+ assign X = S;
end else begin
@@ -305,8 +195,8 @@ end else begin
end
end endgenerate
-end endgenerate
-
assign X = S;
+
+end endgenerate
endmodule
diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v
index 97f050f76..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
@@ -18,43 +18,6 @@
*
*/
-// Convert negative-polarity reset to positive-polarity
-(* techmap_celltype = "$_DFF_NN0_" *)
-module _90_dff_nn0_to_np0 (input D, C, R, output Q); \$_DFF_NP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
-(* techmap_celltype = "$_DFF_PN0_" *)
-module _90_dff_pn0_to_pp0 (input D, C, R, output Q); \$_DFF_PP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
-(* techmap_celltype = "$_DFF_NN1_" *)
-module _90_dff_nn1_to_np1 (input D, C, R, output Q); \$_DFF_NP1_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
-(* techmap_celltype = "$_DFF_PN1_" *)
-module _90_dff_pn1_to_pp1 (input D, C, R, output Q); \$_DFF_PP1_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
-
-(* techmap_celltype = "$_DFFE_NN0P_" *)
-module _90_dffe_nn0_to_np0 (input D, C, R, E, output Q); \$_DFFE_NP0P_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R), .E(E)); endmodule
-(* techmap_celltype = "$_DFFE_PN0P_" *)
-module _90_dffe_pn0_to_pp0 (input D, C, R, E, output Q); \$_DFFE_PP0P_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R), .E(E)); endmodule
-(* techmap_celltype = "$_DFFE_NN1P_" *)
-module _90_dffe_nn1_to_np1 (input D, C, R, E, output Q); \$_DFFE_NP1P_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R), .E(E)); endmodule
-(* techmap_celltype = "$_DFFE_PN1P_" *)
-module _90_dffe_pn1_to_pp1 (input D, C, R, E, output Q); \$_DFFE_PP1P_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R), .E(E)); endmodule
-
-(* techmap_celltype = "$_SDFF_NN0_" *)
-module _90_dffs_nn0_to_np0 (input D, C, R, output Q); \$_SDFF_NP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
-(* techmap_celltype = "$_SDFF_PN0_" *)
-module _90_dffs_pn0_to_pp0 (input D, C, R, output Q); \$_SDFF_PP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
-(* techmap_celltype = "$_SDFF_NN1_" *)
-module _90_dffs_nn1_to_np1 (input D, C, R, output Q); \$_SDFF_NP1_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
-(* techmap_celltype = "$_SDFF_PN1_" *)
-module _90_dffs_pn1_to_pp1 (input D, C, R, output Q); \$_SDFF_PP1_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
-
-(* techmap_celltype = "$_SDFFE_NN0P_" *)
-module _90_dffse_nn0_to_np0 (input D, C, R, E, output Q); \$_SDFFE_NP0P_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R), .E(E)); endmodule
-(* techmap_celltype = "$_SDFFE_PN0P_" *)
-module _90_dffse_pn0_to_pp0 (input D, C, R, E, output Q); \$_SDFFE_PP0P_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R), .E(E)); endmodule
-(* techmap_celltype = "$_SDFFE_NN1P_" *)
-module _90_dffse_nn1_to_np1 (input D, C, R, E, output Q); \$_SDFFE_NP1P_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R), .E(E)); endmodule
-(* techmap_celltype = "$_SDFFE_PN1P_" *)
-module _90_dffse_pn1_to_pp1 (input D, C, R, E, output Q); \$_SDFFE_PP1P_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R), .E(E)); endmodule
-
module \$__SHREG_ (input C, input D, input E, output Q);
parameter DEPTH = 0;
parameter [DEPTH-1:0] INIT = 0;
@@ -396,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 f5850d8a2..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
@@ -455,29 +455,6 @@ module CARRY8(
assign CO[7] = S[7] ? CO[6] : DI[7];
endmodule
-`ifdef _EXPLICIT_CARRY
-
-module CARRY0(output CO_CHAIN, CO_FABRIC, O, input CI, CI_INIT, DI, S);
- parameter CYINIT_FABRIC = 0;
- wire CI_COMBINE;
- if(CYINIT_FABRIC) begin
- assign CI_COMBINE = CI_INIT;
- end else begin
- assign CI_COMBINE = CI;
- end
- assign CO_CHAIN = S ? CI_COMBINE : DI;
- assign CO_FABRIC = S ? CI_COMBINE : DI;
- assign O = S ^ CI_COMBINE;
-endmodule
-
-module CARRY(output CO_CHAIN, CO_FABRIC, O, input CI, DI, S);
- assign CO_CHAIN = S ? CI : DI;
- assign CO_FABRIC = S ? CI : DI;
- assign O = S ^ CI;
-endmodule
-
-`endif
-
module ORCY (output O, input CI, I);
assign O = CI | I;
endmodule
@@ -656,6 +633,41 @@ module FDRSE (
Q <= d;
endmodule
+module FDRSE_1 (
+ output reg Q,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_C_INVERTED" *)
+ input C,
+ (* invertible_pin = "IS_CE_INVERTED" *)
+ input CE,
+ (* invertible_pin = "IS_D_INVERTED" *)
+ input D,
+ (* invertible_pin = "IS_R_INVERTED" *)
+ input R,
+ (* invertible_pin = "IS_S_INVERTED" *)
+ input S
+);
+ parameter [0:0] INIT = 1'b0;
+ parameter [0:0] IS_C_INVERTED = 1'b0;
+ parameter [0:0] IS_CE_INVERTED = 1'b0;
+ parameter [0:0] IS_D_INVERTED = 1'b0;
+ parameter [0:0] IS_R_INVERTED = 1'b0;
+ parameter [0:0] IS_S_INVERTED = 1'b0;
+ initial Q <= INIT;
+ wire c = C ^ IS_C_INVERTED;
+ wire ce = CE ^ IS_CE_INVERTED;
+ wire d = D ^ IS_D_INVERTED;
+ wire r = R ^ IS_R_INVERTED;
+ wire s = S ^ IS_S_INVERTED;
+ always @(negedge c)
+ if (r)
+ Q <= 0;
+ else if (s)
+ Q <= 1;
+ else if (ce)
+ Q <= d;
+endmodule
+
(* abc9_box, lib_whitebox *)
module FDCE (
output reg Q,
@@ -860,6 +872,51 @@ module FDCPE (
assign Q = qs ? qp : qc;
endmodule
+module FDCPE_1 (
+ output wire Q,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_C_INVERTED" *)
+ input C,
+ input CE,
+ (* invertible_pin = "IS_CLR_INVERTED" *)
+ input CLR,
+ input D,
+ (* invertible_pin = "IS_PRE_INVERTED" *)
+ input PRE
+);
+ parameter [0:0] INIT = 1'b0;
+ parameter [0:0] IS_C_INVERTED = 1'b0;
+ parameter [0:0] IS_CLR_INVERTED = 1'b0;
+ parameter [0:0] IS_PRE_INVERTED = 1'b0;
+ wire c = C ^ IS_C_INVERTED;
+ wire clr = CLR ^ IS_CLR_INVERTED;
+ wire pre = PRE ^ IS_PRE_INVERTED;
+ // Hacky model to avoid simulation-synthesis mismatches.
+ reg qc, qp, qs;
+ initial qc = INIT;
+ initial qp = INIT;
+ initial qs = 0;
+ always @(negedge c, posedge clr) begin
+ if (clr)
+ qc <= 0;
+ else if (CE)
+ qc <= D;
+ end
+ always @(negedge c, posedge pre) begin
+ if (pre)
+ qp <= 1;
+ else if (CE)
+ qp <= D;
+ end
+ always @* begin
+ if (clr)
+ qs <= 0;
+ else if (pre)
+ qs <= 1;
+ end
+ assign Q = qs ? qp : qc;
+endmodule
+
module LDCE (
output reg Q,
(* invertible_pin = "IS_CLR_INVERTED" *)
@@ -2046,6 +2103,105 @@ module RAM64M8 (
end
endmodule
+module RAM32X16DR8 (
+ output DOA,
+ output DOB,
+ output DOC,
+ output DOD,
+ output DOE,
+ output DOF,
+ output DOG,
+ output [1:0] DOH,
+ input [5:0] ADDRA, ADDRB, ADDRC, ADDRD, ADDRE, ADDRF, ADDRG,
+ input [4:0] ADDRH,
+ input [1:0] DIA,
+ input [1:0] DIB,
+ input [1:0] DIC,
+ input [1:0] DID,
+ input [1:0] DIE,
+ input [1:0] DIF,
+ input [1:0] DIG,
+ input [1:0] DIH,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE
+);
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ reg [63:0] mem_a, mem_b, mem_c, mem_d, mem_e, mem_f, mem_g, mem_h;
+ assign DOA = mem_a[ADDRA];
+ assign DOB = mem_b[ADDRB];
+ assign DOC = mem_c[ADDRC];
+ assign DOD = mem_d[ADDRD];
+ assign DOE = mem_e[ADDRE];
+ assign DOF = mem_f[ADDRF];
+ assign DOG = mem_g[ADDRG];
+ assign DOH = mem_h[2*ADDRH+:2];
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ always @(posedge clk)
+ if (WE) begin
+ mem_a[2*ADDRH+:2] <= DIA;
+ mem_b[2*ADDRH+:2] <= DIB;
+ mem_c[2*ADDRH+:2] <= DIC;
+ mem_d[2*ADDRH+:2] <= DID;
+ mem_e[2*ADDRH+:2] <= DIE;
+ mem_f[2*ADDRH+:2] <= DIF;
+ mem_g[2*ADDRH+:2] <= DIG;
+ mem_h[2*ADDRH+:2] <= DIH;
+ end
+endmodule
+
+module RAM64X8SW (
+ output [7:0] O,
+ input [5:0] A,
+ input D,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE,
+ input [2:0] WSEL
+);
+ parameter [63:0] INIT_A = 64'h0000000000000000;
+ parameter [63:0] INIT_B = 64'h0000000000000000;
+ parameter [63:0] INIT_C = 64'h0000000000000000;
+ parameter [63:0] INIT_D = 64'h0000000000000000;
+ parameter [63:0] INIT_E = 64'h0000000000000000;
+ parameter [63:0] INIT_F = 64'h0000000000000000;
+ parameter [63:0] INIT_G = 64'h0000000000000000;
+ parameter [63:0] INIT_H = 64'h0000000000000000;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ reg [63:0] mem_a = INIT_A;
+ reg [63:0] mem_b = INIT_B;
+ reg [63:0] mem_c = INIT_C;
+ reg [63:0] mem_d = INIT_D;
+ reg [63:0] mem_e = INIT_E;
+ reg [63:0] mem_f = INIT_F;
+ reg [63:0] mem_g = INIT_G;
+ reg [63:0] mem_h = INIT_H;
+ assign O[7] = mem_a[A];
+ assign O[6] = mem_b[A];
+ assign O[5] = mem_c[A];
+ assign O[4] = mem_d[A];
+ assign O[3] = mem_e[A];
+ assign O[2] = mem_f[A];
+ assign O[1] = mem_g[A];
+ assign O[0] = mem_h[A];
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ always @(posedge clk)
+ if (WE) begin
+ case (WSEL)
+ 3'b111: mem_a[A] <= D;
+ 3'b110: mem_b[A] <= D;
+ 3'b101: mem_c[A] <= D;
+ 3'b100: mem_d[A] <= D;
+ 3'b011: mem_e[A] <= D;
+ 3'b010: mem_f[A] <= D;
+ 3'b001: mem_g[A] <= D;
+ 3'b000: mem_h[A] <= D;
+ endcase
+ end
+endmodule
+
// ROM.
module ROM16X1 (
@@ -2358,6 +2514,8 @@ parameter integer PREG = 1;
// The multiplier.
wire signed [35:0] P_MULT;
+wire signed [17:0] A_MULT;
+wire signed [17:0] B_MULT;
assign P_MULT = A_MULT * B_MULT;
// The cascade output.
@@ -2396,8 +2554,6 @@ always @(posedge CLK) begin
end
// The register enables.
-wire signed [17:0] A_MULT;
-wire signed [17:0] B_MULT;
assign A_MULT = (AREG == 1) ? A_REG : A;
assign B_MULT = (BREG == 1) ? B_REG : B_MUX;
assign P = (PREG == 1) ? P_REG : P_MULT;
@@ -3037,8 +3193,12 @@ endmodule
// Virtex 6, Series 7.
`ifdef YOSYS
-(* abc9_box=!(PREG || AREG || ADREG || BREG || CREG || DREG || MREG),
- lib_whitebox=!(PREG || AREG || ADREG || BREG || CREG || DREG || MREG) *)
+(* abc9_box=!(PREG || AREG || ADREG || BREG || CREG || DREG || MREG)
+`ifdef ALLOW_WHITEBOX_DSP48E1
+ // Do not make DSP48E1 a whitebox for ABC9 even if fully combinatorial, since it is a big complex block
+ , lib_whitebox=!(PREG || AREG || ADREG || BREG || CREG || DREG || MREG || INMODEREG || OPMODEREG || ALUMODEREG || CARRYINREG || CARRYINSELREG)
+`endif
+*)
`endif
module DSP48E1 (
output [29:0] ACOUT,
@@ -3526,11 +3686,15 @@ module DSP48E1 (
if (OPMODEr[3:2] != 2'b01) $fatal(1, "OPMODEr[3:2] must be 2'b01 when OPMODEr[1:0] is 2'b01");
`endif
end
- 2'b10: begin X = P;
+ 2'b10:
+ if (PREG == 1)
+ X = P;
+ else begin
+ X = 48'bx;
`ifndef YOSYS
- if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[1:0] is 2'b10");
+ $fatal(1, "PREG must be 1 when OPMODEr[1:0] is 2'b10");
`endif
- end
+ end
2'b11: X = $signed({Ar2, Br2});
default: X = 48'bx;
endcase
@@ -3552,20 +3716,36 @@ module DSP48E1 (
case (OPMODEr[6:4])
3'b000: Z = 48'b0;
3'b001: Z = PCIN;
- 3'b010: begin Z = P;
+ 3'b010:
+ if (PREG == 1)
+ Z = P;
+ else begin
+ Z = 48'bx;
`ifndef YOSYS
- if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] i0s 3'b010");
+ $fatal(1, "PREG must be 1 when OPMODEr[6:4] is 3'b010");
`endif
- end
+ end
3'b011: Z = Cr;
- 3'b100: begin Z = P;
+ 3'b100:
+ if (PREG == 1 && OPMODEr[3:0] === 4'b1000)
+ Z = P;
+ else begin
+ Z = 48'bx;
`ifndef YOSYS
- if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] is 3'b100");
- if (OPMODEr[3:0] != 4'b1000) $fatal(1, "OPMODEr[3:0] must be 4'b1000 when OPMODEr[6:4] i0s 3'b100");
+ if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] is 3'b100");
+ if (OPMODEr[3:0] != 4'b1000) $fatal(1, "OPMODEr[3:0] must be 4'b1000 when OPMODEr[6:4] i0s 3'b100");
`endif
- end
+ end
3'b101: Z = $signed(PCIN[47:17]);
- 3'b110: Z = $signed(P[47:17]);
+ 3'b110:
+ if (PREG == 1)
+ Z = $signed(P[47:17]);
+ else begin
+ Z = 48'bx;
+`ifndef YOSYS
+ $fatal(1, "PREG must be 1 when OPMODEr[6:4] is 3'b110");
+`endif
+ end
default: Z = 48'bx;
endcase
end
@@ -3591,10 +3771,34 @@ module DSP48E1 (
3'b001: cin_muxed = ~PCIN[47];
3'b010: cin_muxed = CARRYCASCIN;
3'b011: cin_muxed = PCIN[47];
- 3'b100: cin_muxed = CARRYCASCOUT;
- 3'b101: cin_muxed = ~P[47];
+ 3'b100:
+ if (PREG == 1)
+ cin_muxed = CARRYCASCOUT;
+ else begin
+ cin_muxed = 1'bx;
+`ifndef YOSYS
+ $fatal(1, "PREG must be 1 when CARRYINSEL is 3'b100");
+`endif
+ end
+ 3'b101:
+ if (PREG == 1)
+ cin_muxed = ~P[47];
+ else begin
+ cin_muxed = 1'bx;
+`ifndef YOSYS
+ $fatal(1, "PREG must be 1 when CARRYINSEL is 3'b101");
+`endif
+ end
3'b110: cin_muxed = A24_xnor_B17;
- 3'b111: cin_muxed = P[47];
+ 3'b111:
+ if (PREG == 1)
+ cin_muxed = P[47];
+ else begin
+ cin_muxed = 1'bx;
+`ifndef YOSYS
+ $fatal(1, "PREG must be 1 when CARRYINSEL is 3'b111");
+`endif
+ end
default: cin_muxed = 1'bx;
endcase
end
@@ -4186,4 +4390,3 @@ module RAMB36E1 (
if (|DOB_REG) (posedge CLKBWRCLK => (DOPBDOP : 4'bx)) = 882;
endspecify
endmodule
-
diff --git a/techlibs/xilinx/cells_xtra.py b/techlibs/xilinx/cells_xtra.py
index f086291ab..cb23b9787 100644
--- a/techlibs/xilinx/cells_xtra.py
+++ b/techlibs/xilinx/cells_xtra.py
@@ -57,6 +57,8 @@ CELLS = [
# Cell('RAM32M16', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM64M', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('RAM64M8', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM32X16DR8', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM64X8SW', port_attrs={'WCLK': ['clkbuf_sink']}),
# Cell('ROM16X1'),
# Cell('ROM32X1'),
# Cell('ROM64X1'),
@@ -188,6 +190,11 @@ CELLS = [
# I/O logic.
# Virtex 2, Spartan 3.
+ # Note: these two are not officially listed in the HDL library guide, but
+ # they are more fundamental than OFDDR* and are necessary to construct
+ # differential DDR outputs (OFDDR* can only do single-ended).
+ Cell('FDDRCPE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink']}),
+ Cell('FDDRRSE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink']}),
Cell('IFDDRCPE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink'], 'D': ['iopad_external_pin']}),
Cell('IFDDRRSE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink'], 'D': ['iopad_external_pin']}),
Cell('OFDDRCPE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink'], 'Q': ['iopad_external_pin']}),
@@ -238,12 +245,12 @@ CELLS = [
'CLKDIVP': ['clkbuf_sink'],
}),
Cell('OSERDESE2', port_attrs={'CLK': ['clkbuf_sink'], 'CLKDIV': ['clkbuf_sink']}),
- Cell('PHASER_IN'),
- Cell('PHASER_IN_PHY'),
- Cell('PHASER_OUT'),
- Cell('PHASER_OUT_PHY'),
- Cell('PHASER_REF'),
- Cell('PHY_CONTROL'),
+ Cell('PHASER_IN', keep=True),
+ Cell('PHASER_IN_PHY', keep=True),
+ Cell('PHASER_OUT', keep=True),
+ Cell('PHASER_OUT_PHY', keep=True),
+ Cell('PHASER_REF', keep=True),
+ Cell('PHY_CONTROL', keep=True),
# Ultrascale.
Cell('IDDRE1', port_attrs={'C': ['clkbuf_sink'], 'CB': ['clkbuf_sink']}),
Cell('ODDRE1', port_attrs={'C': ['clkbuf_sink']}),
@@ -257,7 +264,7 @@ CELLS = [
}),
Cell('OSERDESE3', port_attrs={'CLK': ['clkbuf_sink'], 'CLKDIV': ['clkbuf_sink']}),
Cell('BITSLICE_CONTROL', keep=True),
- Cell('RIU_OR'),
+ Cell('RIU_OR', keep=True),
Cell('RX_BITSLICE'),
Cell('RXTX_BITSLICE'),
Cell('TX_BITSLICE'),
@@ -322,7 +329,7 @@ CELLS = [
Cell('PULLUP'),
# Misc.
Cell('DCIRESET', keep=True),
- Cell('HPIO_VREF'), # Ultrascale
+ Cell('HPIO_VREF', keep=True), # Ultrascale
# Clock buffers (global).
# Cell('BUFG', port_attrs={'O': ['clkbuf_driver']}),
@@ -451,6 +458,7 @@ CELLS = [
Cell('FRAME_ECC_VIRTEX6'),
Cell('FRAME_ECCE2'), # Series 7
Cell('FRAME_ECCE3'), # Ultrascale
+ Cell('FRAME_ECCE4'), # Ultrascale+
# AXSS command access.
Cell('USR_ACCESS_VIRTEX4'),
Cell('USR_ACCESS_VIRTEX5'),
@@ -465,10 +473,10 @@ CELLS = [
Cell('EFUSE_USR'),
# ADC.
- Cell('SYSMON'), # Virtex 5/6
- Cell('XADC'), # Series 7
- Cell('SYSMONE1'), # Ultrascale
- Cell('SYSMONE4'), # Ultrascale+
+ Cell('SYSMON', keep=True), # Virtex 5/6
+ Cell('XADC', keep=True), # Series 7
+ Cell('SYSMONE1', keep=True), # Ultrascale
+ Cell('SYSMONE4', keep=True), # Ultrascale+
# Gigabit transceivers.
# Spartan 6.
@@ -502,18 +510,30 @@ CELLS = [
# Ultrascale.
Cell('GTHE3_CHANNEL'),
Cell('GTHE3_COMMON'),
- Cell('GTHE4_CHANNEL'),
- Cell('GTHE4_COMMON'),
Cell('GTYE3_CHANNEL'),
Cell('GTYE3_COMMON'),
- Cell('GTYE4_CHANNEL'),
- Cell('GTYE4_COMMON'),
Cell('IBUFDS_GTE3', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
- Cell('IBUFDS_GTE4', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
Cell('OBUFDS_GTE3', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
Cell('OBUFDS_GTE3_ADV', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
+ # Ultrascale+.
+ Cell('GTHE4_CHANNEL'),
+ Cell('GTHE4_COMMON'),
+ Cell('GTYE4_CHANNEL'),
+ Cell('GTYE4_COMMON'),
+ Cell('IBUFDS_GTE4', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
Cell('OBUFDS_GTE4', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
Cell('OBUFDS_GTE4_ADV', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
+ # Ultrascale+ GTM.
+ Cell('GTM_DUAL'), # not in the libraries guide
+ Cell('IBUFDS_GTM', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
+ Cell('OBUFDS_GTM', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
+ Cell('OBUFDS_GTM_ADV', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
+
+ # High-speed ADC/DAC.
+ Cell('HSDAC'), # not in libraries guide
+ Cell('HSADC'), # not in libraries guide
+ Cell('RFDAC'), # not in libraries guide
+ Cell('RFADC'), # not in libraries guide
# PCIE IP.
Cell('PCIE_A1'), # Spartan 6
@@ -523,6 +543,7 @@ CELLS = [
Cell('PCIE_3_0'), # Series 7
Cell('PCIE_3_1'), # Ultrascale
Cell('PCIE40E4'), # Ultrascale+
+ Cell('PCIE4CE4'), # Ultrascale+ v2 (not in the libraries guide)
# Ethernet IP.
Cell('EMAC'), # Virtex 4
@@ -531,17 +552,29 @@ CELLS = [
Cell('CMAC'), # Ultrascale
Cell('CMACE4'), # Ultrsacale+
+ # Hard memory controllers.
+ Cell('MCB'), # Spartan 6 Memory Controller Block
+ Cell('HBM_REF_CLK', keep=True), # not in liraries guide
+ # not sure how the following relate to the hw
+ Cell('HBM_SNGLBLI_INTF_APB', keep=True), # not in liraries guide
+ Cell('HBM_SNGLBLI_INTF_AXI', keep=True), # not in liraries guide
+ Cell('HBM_ONE_STACK_INTF', keep=True), # not in liraries guide
+ Cell('HBM_TWO_STACK_INTF', keep=True), # not in liraries guide
+
# PowerPC.
# TODO PPC405 (Virtex 2)
Cell('PPC405_ADV'), # Virtex 4
Cell('PPC440'), # Virtex 5
+ # ARM.
+ Cell('PS7', keep=True), # The Zynq 7000 ARM Processor System (not in libraries guide).
+ Cell('PS8', keep=True), # The Zynq Ultrascale+ ARM Processor System (not in libraries guide).
+
# Misc hard IP.
- Cell('MCB'), # Spartan 6 Memory Controller Block
- Cell('PS7', keep=True), # The Zynq 7000 ARM Processor System.
- Cell('PS8', keep=True), # The Zynq Ultrascale+ ARM Processor System.
Cell('ILKN'), # Ultrascale Interlaken
Cell('ILKNE4'), # Ultrascale+ Interlaken
+ Cell('VCU', keep=True), # Zynq MPSoC Video Codec Unit (not in libraries guide).
+ Cell('FE'), # Zynq RFSoC Forward Error Correction (not in libraries guide).
]
@@ -554,100 +587,101 @@ class State(Enum):
def xtract_cell_decl(cell, dirs, outf):
for dir in dirs:
- fname = os.path.join(dir, cell.name + '.v')
- try:
- with open(fname) as f:
- state = State.OUTSIDE
- found = False
- # Probably the most horrible Verilog "parser" ever written.
- module_ports = []
- invertible_ports = set()
- for l in f:
- l = l.partition('//')[0]
- l = l.strip()
- if l == 'module {}'.format(cell.name) or l.startswith('module {} '.format(cell.name)):
- if found:
- print('Multiple modules in {}.'.format(fname))
- sys.exit(1)
- elif state != State.OUTSIDE:
- print('Nested modules in {}.'.format(fname))
- sys.exit(1)
- found = True
- state = State.IN_MODULE
- if cell.keep:
- outf.write('(* keep *)\n')
- outf.write('module {} (...);\n'.format(cell.name))
- elif l.startswith('module '):
- if state != State.OUTSIDE:
- print('Nested modules in {}.'.format(fname))
- sys.exit(1)
- state = State.IN_OTHER_MODULE
- elif l.startswith('task '):
- if state == State.IN_MODULE:
- state = State.IN_TASK
- elif l.startswith('function '):
- if state == State.IN_MODULE:
- state = State.IN_FUNCTION
- elif l == 'endtask':
- if state == State.IN_TASK:
- state = State.IN_MODULE
- elif l == 'endfunction':
- if state == State.IN_FUNCTION:
+ for ext in ['.v', '.sv']:
+ fname = os.path.join(dir, cell.name + ext)
+ try:
+ with open(fname) as f:
+ state = State.OUTSIDE
+ found = False
+ # Probably the most horrible Verilog "parser" ever written.
+ module_ports = []
+ invertible_ports = set()
+ for l in f:
+ l = l.partition('//')[0]
+ l = l.strip()
+ if l == 'module {}'.format(cell.name) or l.startswith('module {} '.format(cell.name)):
+ if found:
+ print('Multiple modules in {}.'.format(fname))
+ sys.exit(1)
+ elif state != State.OUTSIDE:
+ print('Nested modules in {}.'.format(fname))
+ sys.exit(1)
+ found = True
state = State.IN_MODULE
- elif l == 'endmodule':
- if state == State.IN_MODULE:
- for kind, rng, port in module_ports:
- for attr in cell.port_attrs.get(port, []):
- outf.write(' (* {} *)\n'.format(attr))
- if port in invertible_ports:
- outf.write(' (* invertible_pin = "IS_{}_INVERTED" *)\n'.format(port))
- if rng is None:
- outf.write(' {} {};\n'.format(kind, port))
+ if cell.keep:
+ outf.write('(* keep *)\n')
+ outf.write('module {} (...);\n'.format(cell.name))
+ elif l.startswith('module '):
+ if state != State.OUTSIDE:
+ print('Nested modules in {}.'.format(fname))
+ sys.exit(1)
+ state = State.IN_OTHER_MODULE
+ elif l.startswith('task '):
+ if state == State.IN_MODULE:
+ state = State.IN_TASK
+ elif l.startswith('function '):
+ if state == State.IN_MODULE:
+ state = State.IN_FUNCTION
+ elif l == 'endtask':
+ if state == State.IN_TASK:
+ state = State.IN_MODULE
+ elif l == 'endfunction':
+ if state == State.IN_FUNCTION:
+ state = State.IN_MODULE
+ elif l == 'endmodule':
+ if state == State.IN_MODULE:
+ for kind, rng, port in module_ports:
+ for attr in cell.port_attrs.get(port, []):
+ outf.write(' (* {} *)\n'.format(attr))
+ if port in invertible_ports:
+ outf.write(' (* invertible_pin = "IS_{}_INVERTED" *)\n'.format(port))
+ if rng is None:
+ outf.write(' {} {};\n'.format(kind, port))
+ else:
+ outf.write(' {} {} {};\n'.format(kind, rng, port))
+ outf.write(l + '\n')
+ outf.write('\n')
+ elif state != State.IN_OTHER_MODULE:
+ print('endmodule in weird place in {}.'.format(cell.name, fname))
+ sys.exit(1)
+ state = State.OUTSIDE
+ elif l.startswith(('input ', 'output ', 'inout ')) and state == State.IN_MODULE:
+ if l.endswith((';', ',')):
+ l = l[:-1]
+ if ';' in l:
+ print('Weird port line in {} [{}].'.format(fname, l))
+ sys.exit(1)
+ kind, _, ports = l.partition(' ')
+ for port in ports.split(','):
+ port = port.strip()
+ if port.startswith('['):
+ rng, port = port.split()
else:
- outf.write(' {} {} {};\n'.format(kind, rng, port))
- outf.write(l + '\n')
- outf.write('\n')
- elif state != State.IN_OTHER_MODULE:
- print('endmodule in weird place in {}.'.format(cell.name, fname))
- sys.exit(1)
- state = State.OUTSIDE
- elif l.startswith(('input ', 'output ', 'inout ')) and state == State.IN_MODULE:
- if l.endswith((';', ',')):
- l = l[:-1]
- if ';' in l:
- print('Weird port line in {} [{}].'.format(fname, l))
- sys.exit(1)
- kind, _, ports = l.partition(' ')
- for port in ports.split(','):
- port = port.strip()
- if port.startswith('['):
- rng, port = port.split()
- else:
- rng = None
- module_ports.append((kind, rng, port))
- elif l.startswith('parameter ') and state == State.IN_MODULE:
- if 'UNPLACED' in l:
- continue
- if l.endswith((';', ',')):
- l = l[:-1]
- while ' ' in l:
- l = l.replace(' ', ' ')
- if ';' in l:
- print('Weird parameter line in {} [{}].'.format(fname, l))
- sys.exit(1)
- outf.write(' {};\n'.format(l))
- match = re.search('IS_([a-zA-Z0-9_]+)_INVERTED', l)
- if match:
- invertible_ports.add(match[1])
- if state != State.OUTSIDE:
- print('endmodule not found in {}.'.format(fname))
- sys.exit(1)
- if not found:
- print('Cannot find module {} in {}.'.format(cell.name, fname))
- sys.exit(1)
- return
- except FileNotFoundError:
- continue
+ rng = None
+ module_ports.append((kind, rng, port))
+ elif l.startswith('parameter ') and state == State.IN_MODULE:
+ if 'UNPLACED' in l:
+ continue
+ if l.endswith((';', ',')):
+ l = l[:-1]
+ while ' ' in l:
+ l = l.replace(' ', ' ')
+ if ';' in l:
+ print('Weird parameter line in {} [{}].'.format(fname, l))
+ sys.exit(1)
+ outf.write(' {};\n'.format(l))
+ match = re.search('IS_([a-zA-Z0-9_]+)_INVERTED', l)
+ if match:
+ invertible_ports.add(match[1])
+ if state != State.OUTSIDE:
+ print('endmodule not found in {}.'.format(fname))
+ sys.exit(1)
+ if not found:
+ print('Cannot find module {} in {}.'.format(cell.name, fname))
+ sys.exit(1)
+ return
+ except FileNotFoundError:
+ continue
print('Cannot find {}.'.format(cell.name))
sys.exit(1)
@@ -659,6 +693,7 @@ if __name__ == '__main__':
dirs = [
os.path.join(args.vivado_dir, 'data/verilog/src/xeclib'),
+ os.path.join(args.vivado_dir, 'data/verilog/src/unisims'),
os.path.join(args.vivado_dir, 'data/verilog/src/retarget'),
os.path.join(args.ise_dir, 'ISE_DS/ISE/verilog/xeclib/unisims'),
]
diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v
index 3021f6b5a..1187101fd 100644
--- a/techlibs/xilinx/cells_xtra.v
+++ b/techlibs/xilinx/cells_xtra.v
@@ -5301,6 +5301,34 @@ module DSP48E2 (...);
input RSTP;
endmodule
+module FDDRCPE (...);
+ parameter INIT = 1'b0;
+ (* clkbuf_sink *)
+ input C0;
+ (* clkbuf_sink *)
+ input C1;
+ input CE;
+ input D0;
+ input D1;
+ input CLR;
+ input PRE;
+ output Q;
+endmodule
+
+module FDDRRSE (...);
+ parameter INIT = 1'b0;
+ output Q;
+ (* clkbuf_sink *)
+ input C0;
+ (* clkbuf_sink *)
+ input C1;
+ input CE;
+ input D0;
+ input D1;
+ input R;
+ input S;
+endmodule
+
module IFDDRCPE (...);
output Q0;
output Q1;
@@ -5966,6 +5994,7 @@ module OSERDESE2 (...);
input TCE;
endmodule
+(* keep *)
module PHASER_IN (...);
parameter integer CLKOUT_DIV = 4;
parameter DQS_BIAS_MODE = "FALSE";
@@ -6002,6 +6031,7 @@ module PHASER_IN (...);
input [5:0] COUNTERLOADVAL;
endmodule
+(* keep *)
module PHASER_IN_PHY (...);
parameter BURST_MODE = "FALSE";
parameter integer CLKOUT_DIV = 4;
@@ -6046,6 +6076,7 @@ module PHASER_IN_PHY (...);
input [5:0] COUNTERLOADVAL;
endmodule
+(* keep *)
module PHASER_OUT (...);
parameter integer CLKOUT_DIV = 4;
parameter COARSE_BYPASS = "FALSE";
@@ -6087,6 +6118,7 @@ module PHASER_OUT (...);
input [8:0] COUNTERLOADVAL;
endmodule
+(* keep *)
module PHASER_OUT_PHY (...);
parameter integer CLKOUT_DIV = 4;
parameter COARSE_BYPASS = "FALSE";
@@ -6133,6 +6165,7 @@ module PHASER_OUT_PHY (...);
input [8:0] COUNTERLOADVAL;
endmodule
+(* keep *)
module PHASER_REF (...);
parameter [0:0] IS_RST_INVERTED = 1'b0;
parameter [0:0] IS_PWRDWN_INVERTED = 1'b0;
@@ -6144,6 +6177,7 @@ module PHASER_REF (...);
input RST;
endmodule
+(* keep *)
module PHY_CONTROL (...);
parameter integer AO_TOGGLE = 0;
parameter [3:0] AO_WRLVL_EN = 4'b0000;
@@ -6224,6 +6258,7 @@ module ODDRE1 (...);
parameter [0:0] IS_C_INVERTED = 1'b0;
parameter [0:0] IS_D1_INVERTED = 1'b0;
parameter [0:0] IS_D2_INVERTED = 1'b0;
+ parameter SIM_DEVICE = "ULTRASCALE";
parameter [0:0] SRVAL = 1'b0;
output Q;
(* clkbuf_sink *)
@@ -6437,6 +6472,7 @@ module BITSLICE_CONTROL (...);
input [39:0] TX_BIT_CTRL_IN_TRI;
endmodule
+(* keep *)
module RIU_OR (...);
parameter SIM_DEVICE = "ULTRASCALE";
parameter real SIM_VERSION = 2.0;
@@ -7246,6 +7282,7 @@ module DCIRESET (...);
input RST;
endmodule
+(* keep *)
module HPIO_VREF (...);
parameter VREF_CNTR = "OFF";
output VREF;
@@ -7256,6 +7293,8 @@ module BUFGCE (...);
parameter CE_TYPE = "SYNC";
parameter [0:0] IS_CE_INVERTED = 1'b0;
parameter [0:0] IS_I_INVERTED = 1'b0;
+ parameter SIM_DEVICE = "ULTRASCALE";
+ parameter STARTUP_SYNC = "FALSE";
(* clkbuf_driver *)
output O;
(* invertible_pin = "IS_CE_INVERTED" *)
@@ -7306,6 +7345,8 @@ module BUFGMUX_VIRTEX4 (...);
endmodule
module BUFG_GT (...);
+ parameter SIM_DEVICE = "ULTRASCALE";
+ parameter STARTUP_SYNC = "FALSE";
(* clkbuf_driver *)
output O;
input CE;
@@ -7325,6 +7366,8 @@ module BUFG_GT_SYNC (...);
endmodule
module BUFG_PS (...);
+ parameter SIM_DEVICE = "ULTRASCALE_PLUS";
+ parameter STARTUP_SYNC = "FALSE";
(* clkbuf_driver *)
output O;
input I;
@@ -7332,9 +7375,13 @@ endmodule
module BUFGCE_DIV (...);
parameter integer BUFGCE_DIVIDE = 1;
+ parameter CE_TYPE = "SYNC";
+ parameter HARDSYNC_CLR = "FALSE";
parameter [0:0] IS_CE_INVERTED = 1'b0;
parameter [0:0] IS_CLR_INVERTED = 1'b0;
parameter [0:0] IS_I_INVERTED = 1'b0;
+ parameter SIM_DEVICE = "ULTRASCALE";
+ parameter STARTUP_SYNC = "FALSE";
(* clkbuf_driver *)
output O;
(* invertible_pin = "IS_CE_INVERTED" *)
@@ -7931,14 +7978,18 @@ module MMCM_BASE (...);
endmodule
module MMCME2_ADV (...);
+ parameter real CLKIN_FREQ_MAX = 1066.000;
+ parameter real CLKIN_FREQ_MIN = 10.000;
+ parameter real CLKPFD_FREQ_MAX = 550.000;
+ parameter real CLKPFD_FREQ_MIN = 10.000;
+ parameter real VCOCLK_FREQ_MAX = 1600.000;
+ parameter real VCOCLK_FREQ_MIN = 600.000;
parameter BANDWIDTH = "OPTIMIZED";
parameter real CLKFBOUT_MULT_F = 5.000;
parameter real CLKFBOUT_PHASE = 0.000;
parameter CLKFBOUT_USE_FINE_PS = "FALSE";
parameter real CLKIN1_PERIOD = 0.000;
parameter real CLKIN2_PERIOD = 0.000;
- parameter real CLKIN_FREQ_MAX = 1066.000;
- parameter real CLKIN_FREQ_MIN = 10.000;
parameter real CLKOUT0_DIVIDE_F = 1.000;
parameter real CLKOUT0_DUTY_CYCLE = 0.500;
parameter real CLKOUT0_PHASE = 0.000;
@@ -7968,8 +8019,6 @@ module MMCME2_ADV (...);
parameter real CLKOUT6_DUTY_CYCLE = 0.500;
parameter real CLKOUT6_PHASE = 0.000;
parameter CLKOUT6_USE_FINE_PS = "FALSE";
- parameter real CLKPFD_FREQ_MAX = 550.000;
- parameter real CLKPFD_FREQ_MIN = 10.000;
parameter COMPENSATION = "ZHOLD";
parameter integer DIVCLK_DIVIDE = 1;
parameter [0:0] IS_CLKINSEL_INVERTED = 1'b0;
@@ -7983,9 +8032,6 @@ module MMCME2_ADV (...);
parameter SS_MODE = "CENTER_HIGH";
parameter integer SS_MOD_PERIOD = 10000;
parameter STARTUP_WAIT = "FALSE";
- parameter real VCOCLK_FREQ_MAX = 1600.000;
- parameter real VCOCLK_FREQ_MIN = 600.000;
- parameter STARTUP_WAIT = "FALSE";
output CLKFBOUT;
output CLKFBOUTB;
output CLKFBSTOPPED;
@@ -8181,14 +8227,18 @@ module PLLE2_BASE (...);
endmodule
module MMCME3_ADV (...);
+ parameter real CLKIN_FREQ_MAX = 1066.000;
+ parameter real CLKIN_FREQ_MIN = 10.000;
+ parameter real CLKPFD_FREQ_MAX = 550.000;
+ parameter real CLKPFD_FREQ_MIN = 10.000;
+ parameter real VCOCLK_FREQ_MAX = 1600.000;
+ parameter real VCOCLK_FREQ_MIN = 600.000;
parameter BANDWIDTH = "OPTIMIZED";
parameter real CLKFBOUT_MULT_F = 5.000;
parameter real CLKFBOUT_PHASE = 0.000;
parameter CLKFBOUT_USE_FINE_PS = "FALSE";
parameter real CLKIN1_PERIOD = 0.000;
parameter real CLKIN2_PERIOD = 0.000;
- parameter real CLKIN_FREQ_MAX = 1066.000;
- parameter real CLKIN_FREQ_MIN = 10.000;
parameter real CLKOUT0_DIVIDE_F = 1.000;
parameter real CLKOUT0_DUTY_CYCLE = 0.500;
parameter real CLKOUT0_PHASE = 0.000;
@@ -8218,8 +8268,6 @@ module MMCME3_ADV (...);
parameter real CLKOUT6_DUTY_CYCLE = 0.500;
parameter real CLKOUT6_PHASE = 0.000;
parameter CLKOUT6_USE_FINE_PS = "FALSE";
- parameter real CLKPFD_FREQ_MAX = 550.000;
- parameter real CLKPFD_FREQ_MIN = 10.000;
parameter COMPENSATION = "AUTO";
parameter integer DIVCLK_DIVIDE = 1;
parameter [0:0] IS_CLKFBIN_INVERTED = 1'b0;
@@ -8236,9 +8284,6 @@ module MMCME3_ADV (...);
parameter SS_MODE = "CENTER_HIGH";
parameter integer SS_MOD_PERIOD = 10000;
parameter STARTUP_WAIT = "FALSE";
- parameter real VCOCLK_FREQ_MAX = 1600.000;
- parameter real VCOCLK_FREQ_MIN = 600.000;
- parameter STARTUP_WAIT = "FALSE";
output CDDCDONE;
output CLKFBOUT;
output CLKFBOUTB;
@@ -8343,10 +8388,14 @@ module MMCME3_BASE (...);
endmodule
module PLLE3_ADV (...);
- parameter integer CLKFBOUT_MULT = 5;
- parameter real CLKFBOUT_PHASE = 0.000;
parameter real CLKIN_FREQ_MAX = 1066.000;
parameter real CLKIN_FREQ_MIN = 70.000;
+ parameter real CLKPFD_FREQ_MAX = 667.500;
+ parameter real CLKPFD_FREQ_MIN = 70.000;
+ parameter real VCOCLK_FREQ_MAX = 1335.000;
+ parameter real VCOCLK_FREQ_MIN = 600.000;
+ parameter integer CLKFBOUT_MULT = 5;
+ parameter real CLKFBOUT_PHASE = 0.000;
parameter real CLKIN_PERIOD = 0.000;
parameter integer CLKOUT0_DIVIDE = 1;
parameter real CLKOUT0_DUTY_CYCLE = 0.500;
@@ -8355,8 +8404,6 @@ module PLLE3_ADV (...);
parameter real CLKOUT1_DUTY_CYCLE = 0.500;
parameter real CLKOUT1_PHASE = 0.000;
parameter CLKOUTPHY_MODE = "VCO_2X";
- parameter real CLKPFD_FREQ_MAX = 667.500;
- parameter real CLKPFD_FREQ_MIN = 70.000;
parameter COMPENSATION = "AUTO";
parameter integer DIVCLK_DIVIDE = 1;
parameter [0:0] IS_CLKFBIN_INVERTED = 1'b0;
@@ -8365,9 +8412,6 @@ module PLLE3_ADV (...);
parameter [0:0] IS_RST_INVERTED = 1'b0;
parameter real REF_JITTER = 0.010;
parameter STARTUP_WAIT = "FALSE";
- parameter real VCOCLK_FREQ_MAX = 1335.000;
- parameter real VCOCLK_FREQ_MIN = 600.000;
- parameter STARTUP_WAIT = "FALSE";
output CLKFBOUT;
output CLKOUT0;
output CLKOUT0B;
@@ -8430,14 +8474,18 @@ module PLLE3_BASE (...);
endmodule
module MMCME4_ADV (...);
+ parameter real CLKIN_FREQ_MAX = 1066.000;
+ parameter real CLKIN_FREQ_MIN = 10.000;
+ parameter real CLKPFD_FREQ_MAX = 550.000;
+ parameter real CLKPFD_FREQ_MIN = 10.000;
+ parameter real VCOCLK_FREQ_MAX = 1600.000;
+ parameter real VCOCLK_FREQ_MIN = 800.000;
parameter BANDWIDTH = "OPTIMIZED";
parameter real CLKFBOUT_MULT_F = 5.000;
parameter real CLKFBOUT_PHASE = 0.000;
parameter CLKFBOUT_USE_FINE_PS = "FALSE";
parameter real CLKIN1_PERIOD = 0.000;
parameter real CLKIN2_PERIOD = 0.000;
- parameter real CLKIN_FREQ_MAX = 1066.000;
- parameter real CLKIN_FREQ_MIN = 10.000;
parameter real CLKOUT0_DIVIDE_F = 1.000;
parameter real CLKOUT0_DUTY_CYCLE = 0.500;
parameter real CLKOUT0_PHASE = 0.000;
@@ -8467,8 +8515,6 @@ module MMCME4_ADV (...);
parameter real CLKOUT6_DUTY_CYCLE = 0.500;
parameter real CLKOUT6_PHASE = 0.000;
parameter CLKOUT6_USE_FINE_PS = "FALSE";
- parameter real CLKPFD_FREQ_MAX = 550.000;
- parameter real CLKPFD_FREQ_MIN = 10.000;
parameter COMPENSATION = "AUTO";
parameter integer DIVCLK_DIVIDE = 1;
parameter [0:0] IS_CLKFBIN_INVERTED = 1'b0;
@@ -8485,9 +8531,6 @@ module MMCME4_ADV (...);
parameter SS_MODE = "CENTER_HIGH";
parameter integer SS_MOD_PERIOD = 10000;
parameter STARTUP_WAIT = "FALSE";
- parameter real VCOCLK_FREQ_MAX = 1600.000;
- parameter real VCOCLK_FREQ_MIN = 800.000;
- parameter STARTUP_WAIT = "FALSE";
output CDDCDONE;
output CLKFBOUT;
output CLKFBOUTB;
@@ -8592,10 +8635,14 @@ module MMCME4_BASE (...);
endmodule
module PLLE4_ADV (...);
- parameter integer CLKFBOUT_MULT = 5;
- parameter real CLKFBOUT_PHASE = 0.000;
parameter real CLKIN_FREQ_MAX = 1066.000;
parameter real CLKIN_FREQ_MIN = 70.000;
+ parameter real CLKPFD_FREQ_MAX = 667.500;
+ parameter real CLKPFD_FREQ_MIN = 70.000;
+ parameter real VCOCLK_FREQ_MAX = 1500.000;
+ parameter real VCOCLK_FREQ_MIN = 750.000;
+ parameter integer CLKFBOUT_MULT = 5;
+ parameter real CLKFBOUT_PHASE = 0.000;
parameter real CLKIN_PERIOD = 0.000;
parameter integer CLKOUT0_DIVIDE = 1;
parameter real CLKOUT0_DUTY_CYCLE = 0.500;
@@ -8604,8 +8651,6 @@ module PLLE4_ADV (...);
parameter real CLKOUT1_DUTY_CYCLE = 0.500;
parameter real CLKOUT1_PHASE = 0.000;
parameter CLKOUTPHY_MODE = "VCO_2X";
- parameter real CLKPFD_FREQ_MAX = 667.500;
- parameter real CLKPFD_FREQ_MIN = 70.000;
parameter COMPENSATION = "AUTO";
parameter integer DIVCLK_DIVIDE = 1;
parameter [0:0] IS_CLKFBIN_INVERTED = 1'b0;
@@ -8614,9 +8659,6 @@ module PLLE4_ADV (...);
parameter [0:0] IS_RST_INVERTED = 1'b0;
parameter real REF_JITTER = 0.010;
parameter STARTUP_WAIT = "FALSE";
- parameter real VCOCLK_FREQ_MAX = 1500.000;
- parameter real VCOCLK_FREQ_MIN = 750.000;
- parameter STARTUP_WAIT = "FALSE";
output CLKFBOUT;
output CLKOUT0;
output CLKOUT0B;
@@ -9198,6 +9240,18 @@ module FRAME_ECCE3 (...);
input ICAPTOPCLK;
endmodule
+module FRAME_ECCE4 (...);
+ output CRCERROR;
+ output ECCERRORNOTSINGLE;
+ output ECCERRORSINGLE;
+ output ENDOFFRAME;
+ output ENDOFSCAN;
+ output [26:0] FAR;
+ input [1:0] FARSEL;
+ input ICAPBOTCLK;
+ input ICAPTOPCLK;
+endmodule
+
module USR_ACCESS_VIRTEX4 (...);
output [31:0] DATA;
output DATAVALID;
@@ -9263,6 +9317,7 @@ module EFUSE_USR (...);
output [31:0] EFUSEUSR;
endmodule
+(* keep *)
module SYSMON (...);
parameter [15:0] INIT_40 = 16'h0;
parameter [15:0] INIT_41 = 16'h0;
@@ -9315,6 +9370,7 @@ module SYSMON (...);
input [6:0] DADDR;
endmodule
+(* keep *)
module XADC (...);
parameter [15:0] INIT_40 = 16'h0;
parameter [15:0] INIT_41 = 16'h0;
@@ -9380,6 +9436,7 @@ module XADC (...);
input [6:0] DADDR;
endmodule
+(* keep *)
module SYSMONE1 (...);
parameter [15:0] INIT_40 = 16'h0;
parameter [15:0] INIT_41 = 16'h0;
@@ -9488,6 +9545,7 @@ module SYSMONE1 (...);
input VP;
endmodule
+(* keep *)
module SYSMONE4 (...);
parameter [15:0] COMMON_N_SOURCE = 16'hFFFF;
parameter [15:0] INIT_40 = 16'h0000;
@@ -15129,13 +15187,13 @@ module GTHE3_COMMON (...);
input RCALENB;
endmodule
-module GTHE4_CHANNEL (...);
+module GTYE3_CHANNEL (...);
parameter [0:0] ACJTAG_DEBUG_MODE = 1'b0;
parameter [0:0] ACJTAG_MODE = 1'b0;
parameter [0:0] ACJTAG_RESET = 1'b0;
parameter [15:0] ADAPT_CFG0 = 16'h9200;
parameter [15:0] ADAPT_CFG1 = 16'h801C;
- parameter [15:0] ADAPT_CFG2 = 16'h0000;
+ parameter [15:0] ADAPT_CFG2 = 16'b0000000000000000;
parameter ALIGN_COMMA_DOUBLE = "FALSE";
parameter [9:0] ALIGN_COMMA_ENABLE = 10'b0001111111;
parameter integer ALIGN_COMMA_WORD = 1;
@@ -15143,15 +15201,14 @@ module GTHE4_CHANNEL (...);
parameter [9:0] ALIGN_MCOMMA_VALUE = 10'b1010000011;
parameter ALIGN_PCOMMA_DET = "TRUE";
parameter [9:0] ALIGN_PCOMMA_VALUE = 10'b0101111100;
+ parameter [0:0] AUTO_BW_SEL_BYPASS = 1'b0;
parameter [0:0] A_RXOSCALRESET = 1'b0;
parameter [0:0] A_RXPROGDIVRESET = 1'b0;
- parameter [0:0] A_RXTERMINATION = 1'b1;
parameter [4:0] A_TXDIFFCTRL = 5'b01100;
parameter [0:0] A_TXPROGDIVRESET = 1'b0;
parameter [0:0] CAPBYPASS_FORCE = 1'b0;
parameter CBCC_DATA_SOURCE_SEL = "DECODED";
parameter [0:0] CDR_SWAP_MODE_EN = 1'b0;
- parameter [0:0] CFOK_PWRSVE_EN = 1'b1;
parameter CHAN_BOND_KEEP_ALIGN = "FALSE";
parameter integer CHAN_BOND_MAX_SKEW = 7;
parameter [9:0] CHAN_BOND_SEQ_1_1 = 10'b0101111100;
@@ -15166,7 +15223,7 @@ module GTHE4_CHANNEL (...);
parameter [3:0] CHAN_BOND_SEQ_2_ENABLE = 4'b1111;
parameter CHAN_BOND_SEQ_2_USE = "FALSE";
parameter integer CHAN_BOND_SEQ_LEN = 2;
- parameter [15:0] CH_HSPMUX = 16'h2424;
+ parameter [15:0] CH_HSPMUX = 16'h0000;
parameter [15:0] CKCAL1_CFG_0 = 16'b0000000000000000;
parameter [15:0] CKCAL1_CFG_1 = 16'b0000000000000000;
parameter [15:0] CKCAL1_CFG_2 = 16'b0000000000000000;
@@ -15176,7 +15233,7 @@ module GTHE4_CHANNEL (...);
parameter [15:0] CKCAL2_CFG_2 = 16'b0000000000000000;
parameter [15:0] CKCAL2_CFG_3 = 16'b0000000000000000;
parameter [15:0] CKCAL2_CFG_4 = 16'b0000000000000000;
- parameter [15:0] CKCAL_RSVD0 = 16'h4000;
+ parameter [15:0] CKCAL_RSVD0 = 16'h0000;
parameter [15:0] CKCAL_RSVD1 = 16'h0000;
parameter CLK_CORRECT_USE = "TRUE";
parameter CLK_COR_KEEP_IDLE = "FALSE";
@@ -15196,13 +15253,14 @@ module GTHE4_CHANNEL (...);
parameter [3:0] CLK_COR_SEQ_2_ENABLE = 4'b1111;
parameter CLK_COR_SEQ_2_USE = "FALSE";
parameter integer CLK_COR_SEQ_LEN = 2;
- parameter [15:0] CPLL_CFG0 = 16'h01FA;
- parameter [15:0] CPLL_CFG1 = 16'h24A9;
- parameter [15:0] CPLL_CFG2 = 16'h6807;
- parameter [15:0] CPLL_CFG3 = 16'h0000;
+ parameter [15:0] CPLL_CFG0 = 16'h20F8;
+ parameter [15:0] CPLL_CFG1 = 16'hA494;
+ parameter [15:0] CPLL_CFG2 = 16'hF001;
+ parameter [5:0] CPLL_CFG3 = 6'h00;
parameter integer CPLL_FBDIV = 4;
parameter integer CPLL_FBDIV_45 = 4;
parameter [15:0] CPLL_INIT_CFG0 = 16'h001E;
+ parameter [7:0] CPLL_INIT_CFG1 = 8'h00;
parameter [15:0] CPLL_LOCK_CFG = 16'h01E8;
parameter integer CPLL_REFCLK_DIV = 1;
parameter [2:0] CTLE3_OCAP_EXT_CTRL = 3'b000;
@@ -15212,14 +15270,16 @@ module GTHE4_CHANNEL (...);
parameter DEC_MCOMMA_DETECT = "TRUE";
parameter DEC_PCOMMA_DETECT = "TRUE";
parameter DEC_VALID_COMMA_ONLY = "TRUE";
- parameter [0:0] DELAY_ELEC = 1'b0;
+ parameter [0:0] DFE_D_X_REL_POS = 1'b0;
+ parameter [0:0] DFE_VCM_COMP_EN = 1'b0;
parameter [9:0] DMONITOR_CFG0 = 10'h000;
parameter [7:0] DMONITOR_CFG1 = 8'h00;
parameter [0:0] ES_CLK_PHASE_SEL = 1'b0;
parameter [5:0] ES_CONTROL = 6'b000000;
parameter ES_ERRDET_EN = "FALSE";
parameter ES_EYE_SCAN_EN = "FALSE";
- parameter [11:0] ES_HORZ_OFFSET = 12'h800;
+ parameter [11:0] ES_HORZ_OFFSET = 12'h000;
+ parameter [9:0] ES_PMA_CFG = 10'b0000000000;
parameter [4:0] ES_PRESCALE = 5'b00000;
parameter [15:0] ES_QUALIFIER0 = 16'h0000;
parameter [15:0] ES_QUALIFIER1 = 16'h0000;
@@ -15251,19 +15311,32 @@ module GTHE4_CHANNEL (...);
parameter [15:0] ES_SDATA_MASK7 = 16'h0000;
parameter [15:0] ES_SDATA_MASK8 = 16'h0000;
parameter [15:0] ES_SDATA_MASK9 = 16'h0000;
+ parameter [10:0] EVODD_PHI_CFG = 11'b00000000000;
parameter [0:0] EYE_SCAN_SWAP_EN = 1'b0;
parameter [3:0] FTS_DESKEW_SEQ_ENABLE = 4'b1111;
parameter [3:0] FTS_LANE_DESKEW_CFG = 4'b1111;
parameter FTS_LANE_DESKEW_EN = "FALSE";
parameter [4:0] GEARBOX_MODE = 5'b00000;
+ parameter [0:0] GM_BIAS_SELECT = 1'b0;
parameter [0:0] ISCAN_CK_PH_SEL2 = 1'b0;
parameter [0:0] LOCAL_MASTER = 1'b0;
+ parameter [15:0] LOOP0_CFG = 16'h0000;
+ parameter [15:0] LOOP10_CFG = 16'h0000;
+ parameter [15:0] LOOP11_CFG = 16'h0000;
+ parameter [15:0] LOOP12_CFG = 16'h0000;
+ parameter [15:0] LOOP13_CFG = 16'h0000;
+ parameter [15:0] LOOP1_CFG = 16'h0000;
+ parameter [15:0] LOOP2_CFG = 16'h0000;
+ parameter [15:0] LOOP3_CFG = 16'h0000;
+ parameter [15:0] LOOP4_CFG = 16'h0000;
+ parameter [15:0] LOOP5_CFG = 16'h0000;
+ parameter [15:0] LOOP6_CFG = 16'h0000;
+ parameter [15:0] LOOP7_CFG = 16'h0000;
+ parameter [15:0] LOOP8_CFG = 16'h0000;
+ parameter [15:0] LOOP9_CFG = 16'h0000;
parameter [2:0] LPBK_BIAS_CTRL = 3'b000;
parameter [0:0] LPBK_EN_RCAL_B = 1'b0;
parameter [3:0] LPBK_EXT_RCAL = 4'b0000;
- parameter [2:0] LPBK_IND_CTRL0 = 3'b000;
- parameter [2:0] LPBK_IND_CTRL1 = 3'b000;
- parameter [2:0] LPBK_IND_CTRL2 = 3'b000;
parameter [3:0] LPBK_RG_CTRL = 4'b0000;
parameter [1:0] OOBDIVCTL = 2'b00;
parameter [0:0] OOB_PWRUP = 1'b0;
@@ -15276,32 +15349,25 @@ module GTHE4_CHANNEL (...);
parameter [5:0] PCI3_RX_ELECIDLE_HI_COUNT = 6'b000000;
parameter [0:0] PCI3_RX_ELECIDLE_LP4_DISABLE = 1'b0;
parameter [0:0] PCI3_RX_FIFO_DISABLE = 1'b0;
- parameter [4:0] PCIE3_CLK_COR_EMPTY_THRSH = 5'b00000;
- parameter [5:0] PCIE3_CLK_COR_FULL_THRSH = 6'b010000;
- parameter [4:0] PCIE3_CLK_COR_MAX_LAT = 5'b01000;
- parameter [4:0] PCIE3_CLK_COR_MIN_LAT = 5'b00100;
- parameter [5:0] PCIE3_CLK_COR_THRSH_TIMER = 6'b001000;
parameter [15:0] PCIE_BUFG_DIV_CTRL = 16'h0000;
- parameter [1:0] PCIE_PLL_SEL_MODE_GEN12 = 2'h0;
- parameter [1:0] PCIE_PLL_SEL_MODE_GEN3 = 2'h0;
- parameter [1:0] PCIE_PLL_SEL_MODE_GEN4 = 2'h0;
parameter [15:0] PCIE_RXPCS_CFG_GEN3 = 16'h0000;
parameter [15:0] PCIE_RXPMA_CFG = 16'h0000;
parameter [15:0] PCIE_TXPCS_CFG_GEN3 = 16'h0000;
parameter [15:0] PCIE_TXPMA_CFG = 16'h0000;
parameter PCS_PCIE_EN = "FALSE";
parameter [15:0] PCS_RSVD0 = 16'b0000000000000000;
+ parameter [2:0] PCS_RSVD1 = 3'b000;
parameter [11:0] PD_TRANS_TIME_FROM_P2 = 12'h03C;
parameter [7:0] PD_TRANS_TIME_NONE_P2 = 8'h19;
parameter [7:0] PD_TRANS_TIME_TO_P2 = 8'h64;
+ parameter [1:0] PLL_SEL_MODE_GEN12 = 2'h0;
+ parameter [1:0] PLL_SEL_MODE_GEN3 = 2'h0;
+ parameter [15:0] PMA_RSV0 = 16'h0000;
+ parameter [15:0] PMA_RSV1 = 16'h0000;
parameter integer PREIQ_FREQ_BST = 0;
parameter [2:0] PROCESS_PAR = 3'b010;
parameter [0:0] RATE_SW_USE_DRP = 1'b0;
- parameter [0:0] RCLK_SIPO_DLY_ENB = 1'b0;
- parameter [0:0] RCLK_SIPO_INV_EN = 1'b0;
parameter [0:0] RESET_POWERSAVE_DISABLE = 1'b0;
- parameter [2:0] RTX_BUF_CML_CTRL = 3'b010;
- parameter [1:0] RTX_BUF_TERM_CTRL = 2'b00;
parameter [4:0] RXBUFRESET_TIME = 5'b00001;
parameter RXBUF_ADDR_MODE = "FULL";
parameter [3:0] RXBUF_EIDLE_HI_CNT = 4'b1000;
@@ -15316,48 +15382,37 @@ module GTHE4_CHANNEL (...);
parameter integer RXBUF_THRESH_UNDFLW = 4;
parameter [4:0] RXCDRFREQRESET_TIME = 5'b00001;
parameter [4:0] RXCDRPHRESET_TIME = 5'b00001;
- parameter [15:0] RXCDR_CFG0 = 16'h0003;
- parameter [15:0] RXCDR_CFG0_GEN3 = 16'h0003;
- parameter [15:0] RXCDR_CFG1 = 16'h0000;
- parameter [15:0] RXCDR_CFG1_GEN3 = 16'h0000;
- parameter [15:0] RXCDR_CFG2 = 16'h0164;
- parameter [9:0] RXCDR_CFG2_GEN2 = 10'h164;
- parameter [15:0] RXCDR_CFG2_GEN3 = 16'h0034;
- parameter [15:0] RXCDR_CFG2_GEN4 = 16'h0034;
- parameter [15:0] RXCDR_CFG3 = 16'h0024;
- parameter [5:0] RXCDR_CFG3_GEN2 = 6'h24;
- parameter [15:0] RXCDR_CFG3_GEN3 = 16'h0024;
- parameter [15:0] RXCDR_CFG3_GEN4 = 16'h0024;
- parameter [15:0] RXCDR_CFG4 = 16'h5CF6;
- parameter [15:0] RXCDR_CFG4_GEN3 = 16'h5CF6;
- parameter [15:0] RXCDR_CFG5 = 16'hB46B;
- parameter [15:0] RXCDR_CFG5_GEN3 = 16'h146B;
+ parameter [15:0] RXCDR_CFG0 = 16'h0000;
+ parameter [15:0] RXCDR_CFG0_GEN3 = 16'h0000;
+ parameter [15:0] RXCDR_CFG1 = 16'h0300;
+ parameter [15:0] RXCDR_CFG1_GEN3 = 16'h0300;
+ parameter [15:0] RXCDR_CFG2 = 16'h0060;
+ parameter [15:0] RXCDR_CFG2_GEN3 = 16'h0060;
+ parameter [15:0] RXCDR_CFG3 = 16'h0000;
+ parameter [15:0] RXCDR_CFG3_GEN3 = 16'h0000;
+ parameter [15:0] RXCDR_CFG4 = 16'h0002;
+ parameter [15:0] RXCDR_CFG4_GEN3 = 16'h0002;
+ parameter [15:0] RXCDR_CFG5 = 16'h0000;
+ parameter [15:0] RXCDR_CFG5_GEN3 = 16'h0000;
parameter [0:0] RXCDR_FR_RESET_ON_EIDLE = 1'b0;
parameter [0:0] RXCDR_HOLD_DURING_EIDLE = 1'b0;
- parameter [15:0] RXCDR_LOCK_CFG0 = 16'h0040;
- parameter [15:0] RXCDR_LOCK_CFG1 = 16'h8000;
+ parameter [15:0] RXCDR_LOCK_CFG0 = 16'h0001;
+ parameter [15:0] RXCDR_LOCK_CFG1 = 16'h0000;
parameter [15:0] RXCDR_LOCK_CFG2 = 16'h0000;
parameter [15:0] RXCDR_LOCK_CFG3 = 16'h0000;
- parameter [15:0] RXCDR_LOCK_CFG4 = 16'h0000;
parameter [0:0] RXCDR_PH_RESET_ON_EIDLE = 1'b0;
- parameter [15:0] RXCFOK_CFG0 = 16'h0000;
- parameter [15:0] RXCFOK_CFG1 = 16'h0002;
+ parameter [1:0] RXCFOKDONE_SRC = 2'b00;
+ parameter [15:0] RXCFOK_CFG0 = 16'h3E00;
+ parameter [15:0] RXCFOK_CFG1 = 16'h0042;
parameter [15:0] RXCFOK_CFG2 = 16'h002D;
- parameter [15:0] RXCKCAL1_IQ_LOOP_RST_CFG = 16'h0000;
- parameter [15:0] RXCKCAL1_I_LOOP_RST_CFG = 16'h0000;
- parameter [15:0] RXCKCAL1_Q_LOOP_RST_CFG = 16'h0000;
- parameter [15:0] RXCKCAL2_DX_LOOP_RST_CFG = 16'h0000;
- parameter [15:0] RXCKCAL2_D_LOOP_RST_CFG = 16'h0000;
- parameter [15:0] RXCKCAL2_S_LOOP_RST_CFG = 16'h0000;
- parameter [15:0] RXCKCAL2_X_LOOP_RST_CFG = 16'h0000;
parameter [6:0] RXDFELPMRESET_TIME = 7'b0001111;
parameter [15:0] RXDFELPM_KL_CFG0 = 16'h0000;
parameter [15:0] RXDFELPM_KL_CFG1 = 16'h0022;
parameter [15:0] RXDFELPM_KL_CFG2 = 16'h0100;
- parameter [15:0] RXDFE_CFG0 = 16'h4000;
+ parameter [15:0] RXDFE_CFG0 = 16'h4C00;
parameter [15:0] RXDFE_CFG1 = 16'h0000;
- parameter [15:0] RXDFE_GC_CFG0 = 16'h0000;
- parameter [15:0] RXDFE_GC_CFG1 = 16'h0000;
+ parameter [15:0] RXDFE_GC_CFG0 = 16'h1E00;
+ parameter [15:0] RXDFE_GC_CFG1 = 16'h1900;
parameter [15:0] RXDFE_GC_CFG2 = 16'h0000;
parameter [15:0] RXDFE_H2_CFG0 = 16'h0000;
parameter [15:0] RXDFE_H2_CFG1 = 16'h0002;
@@ -15387,31 +15442,26 @@ module GTHE4_CHANNEL (...);
parameter [15:0] RXDFE_HE_CFG1 = 16'h0002;
parameter [15:0] RXDFE_HF_CFG0 = 16'h0000;
parameter [15:0] RXDFE_HF_CFG1 = 16'h0002;
- parameter [15:0] RXDFE_KH_CFG0 = 16'h0000;
- parameter [15:0] RXDFE_KH_CFG1 = 16'h0000;
- parameter [15:0] RXDFE_KH_CFG2 = 16'h0000;
- parameter [15:0] RXDFE_KH_CFG3 = 16'h0000;
parameter [15:0] RXDFE_OS_CFG0 = 16'h0000;
- parameter [15:0] RXDFE_OS_CFG1 = 16'h0002;
+ parameter [15:0] RXDFE_OS_CFG1 = 16'h0200;
parameter [0:0] RXDFE_PWR_SAVING = 1'b0;
parameter [15:0] RXDFE_UT_CFG0 = 16'h0000;
parameter [15:0] RXDFE_UT_CFG1 = 16'h0002;
- parameter [15:0] RXDFE_UT_CFG2 = 16'h0000;
parameter [15:0] RXDFE_VP_CFG0 = 16'h0000;
parameter [15:0] RXDFE_VP_CFG1 = 16'h0022;
- parameter [15:0] RXDLY_CFG = 16'h0010;
+ parameter [15:0] RXDLY_CFG = 16'h001F;
parameter [15:0] RXDLY_LCFG = 16'h0030;
parameter RXELECIDLE_CFG = "SIGCFG_4";
parameter integer RXGBOX_FIFO_INIT_RD_ADDR = 4;
parameter RXGEARBOX_EN = "FALSE";
parameter [4:0] RXISCANRESET_TIME = 5'b00001;
parameter [15:0] RXLPM_CFG = 16'h0000;
- parameter [15:0] RXLPM_GC_CFG = 16'h1000;
+ parameter [15:0] RXLPM_GC_CFG = 16'h0200;
parameter [15:0] RXLPM_KH_CFG0 = 16'h0000;
parameter [15:0] RXLPM_KH_CFG1 = 16'h0002;
- parameter [15:0] RXLPM_OS_CFG0 = 16'h0000;
+ parameter [15:0] RXLPM_OS_CFG0 = 16'h0400;
parameter [15:0] RXLPM_OS_CFG1 = 16'h0000;
- parameter [8:0] RXOOB_CFG = 9'b000110000;
+ parameter [8:0] RXOOB_CFG = 9'b000000110;
parameter RXOOB_CLK_CFG = "PMA";
parameter [4:0] RXOSCALRESET_TIME = 5'b00011;
parameter integer RXOUT_DIV = 4;
@@ -15422,9 +15472,9 @@ module GTHE4_CHANNEL (...);
parameter [15:0] RXPHSLIP_CFG = 16'h9933;
parameter [4:0] RXPH_MONITOR_SEL = 5'b00000;
parameter [0:0] RXPI_AUTO_BW_SEL_BYPASS = 1'b0;
- parameter [15:0] RXPI_CFG0 = 16'h0002;
- parameter [15:0] RXPI_CFG1 = 16'b0000000000000000;
+ parameter [15:0] RXPI_CFG = 16'h0100;
parameter [0:0] RXPI_LPM = 1'b0;
+ parameter [15:0] RXPI_RSV0 = 16'h0000;
parameter [1:0] RXPI_SEL_LC = 2'b00;
parameter [1:0] RXPI_STARTCODE = 2'b00;
parameter [0:0] RXPI_VREFSEL = 1'b0;
@@ -15432,14 +15482,13 @@ module GTHE4_CHANNEL (...);
parameter [4:0] RXPMARESET_TIME = 5'b00001;
parameter [0:0] RXPRBS_ERR_LOOPBACK = 1'b0;
parameter integer RXPRBS_LINKACQ_CNT = 15;
- parameter [0:0] RXREFCLKDIV2_SEL = 1'b0;
parameter integer RXSLIDE_AUTO_WAIT = 7;
parameter RXSLIDE_MODE = "OFF";
parameter [0:0] RXSYNC_MULTILANE = 1'b0;
parameter [0:0] RXSYNC_OVRD = 1'b0;
parameter [0:0] RXSYNC_SKIP_DA = 1'b0;
parameter [0:0] RX_AFE_CM_EN = 1'b0;
- parameter [15:0] RX_BIAS_CFG0 = 16'h12B0;
+ parameter [15:0] RX_BIAS_CFG0 = 16'h1534;
parameter [5:0] RX_BUFFER_CFG = 6'b000000;
parameter [0:0] RX_CAPFF_SARC_ENB = 1'b0;
parameter integer RX_CLK25_DIV = 8;
@@ -15448,27 +15497,29 @@ module GTHE4_CHANNEL (...);
parameter [3:0] RX_CM_BUF_CFG = 4'b1010;
parameter [0:0] RX_CM_BUF_PD = 1'b0;
parameter integer RX_CM_SEL = 3;
- parameter integer RX_CM_TRIM = 12;
- parameter [7:0] RX_CTLE3_LPF = 8'b00000000;
+ parameter integer RX_CM_TRIM = 10;
+ parameter [0:0] RX_CTLE1_KHKL = 1'b0;
+ parameter [0:0] RX_CTLE2_KHKL = 1'b0;
+ parameter [0:0] RX_CTLE3_AGC = 1'b0;
parameter integer RX_DATA_WIDTH = 20;
parameter [5:0] RX_DDI_SEL = 6'b000000;
parameter RX_DEFER_RESET_BUF_EN = "TRUE";
- parameter [2:0] RX_DEGEN_CTRL = 3'b011;
- parameter integer RX_DFELPM_CFG0 = 0;
- parameter [0:0] RX_DFELPM_CFG1 = 1'b1;
+ parameter [2:0] RX_DEGEN_CTRL = 3'b010;
+ parameter integer RX_DFELPM_CFG0 = 6;
+ parameter [0:0] RX_DFELPM_CFG1 = 1'b0;
parameter [0:0] RX_DFELPM_KLKH_AGC_STUP_EN = 1'b1;
parameter [1:0] RX_DFE_AGC_CFG0 = 2'b00;
parameter integer RX_DFE_AGC_CFG1 = 4;
parameter integer RX_DFE_KL_LPM_KH_CFG0 = 1;
- parameter integer RX_DFE_KL_LPM_KH_CFG1 = 4;
+ parameter integer RX_DFE_KL_LPM_KH_CFG1 = 2;
parameter [1:0] RX_DFE_KL_LPM_KL_CFG0 = 2'b01;
- parameter integer RX_DFE_KL_LPM_KL_CFG1 = 4;
+ parameter [2:0] RX_DFE_KL_LPM_KL_CFG1 = 3'b010;
parameter [0:0] RX_DFE_LPM_HOLD_DURING_EIDLE = 1'b0;
parameter RX_DISPERR_SEQ_MATCH = "TRUE";
parameter [0:0] RX_DIV2_MODE_B = 1'b0;
parameter [4:0] RX_DIVRESET_TIME = 5'b00001;
parameter [0:0] RX_EN_CTLE_RCAL_B = 1'b0;
- parameter [0:0] RX_EN_HI_LR = 1'b1;
+ parameter [0:0] RX_EN_HI_LR = 1'b0;
parameter [8:0] RX_EXT_RL_CTRL = 9'b000000000;
parameter [6:0] RX_EYESCAN_VS_CODE = 7'b0000000;
parameter [0:0] RX_EYESCAN_VS_NEG_DIR = 1'b0;
@@ -15477,7 +15528,6 @@ module GTHE4_CHANNEL (...);
parameter [0:0] RX_FABINT_USRCLK_FLOP = 1'b0;
parameter integer RX_INT_DATAWIDTH = 1;
parameter [0:0] RX_PMA_POWER_SAVE = 1'b0;
- parameter [15:0] RX_PMA_RSV0 = 16'h0000;
parameter real RX_PROGDIV_CFG = 0.0;
parameter [15:0] RX_PROGDIV_RATE = 16'h0001;
parameter [3:0] RX_RESLOAD_CTRL = 4'b0000;
@@ -15485,32 +15535,34 @@ module GTHE4_CHANNEL (...);
parameter [2:0] RX_SAMPLE_PERIOD = 3'b101;
parameter integer RX_SIG_VALID_DLY = 11;
parameter [0:0] RX_SUM_DFETAPREP_EN = 1'b0;
- parameter [3:0] RX_SUM_IREF_TUNE = 4'b1001;
- parameter [3:0] RX_SUM_RESLOAD_CTRL = 4'b0000;
- parameter [3:0] RX_SUM_VCMTUNE = 4'b1010;
+ parameter [3:0] RX_SUM_IREF_TUNE = 4'b0000;
+ parameter [3:0] RX_SUM_VCMTUNE = 4'b1000;
parameter [0:0] RX_SUM_VCM_OVWR = 1'b0;
parameter [2:0] RX_SUM_VREF_TUNE = 3'b100;
parameter [1:0] RX_TUNE_AFE_OS = 2'b00;
parameter [2:0] RX_VREG_CTRL = 3'b101;
parameter [0:0] RX_VREG_PDB = 1'b1;
parameter [1:0] RX_WIDEMODE_CDR = 2'b01;
- parameter [1:0] RX_WIDEMODE_CDR_GEN3 = 2'b01;
- parameter [1:0] RX_WIDEMODE_CDR_GEN4 = 2'b01;
parameter RX_XCLK_SEL = "RXDES";
parameter [0:0] RX_XMODE_SEL = 1'b0;
- parameter [0:0] SAMPLE_CLK_PHASE = 1'b0;
- parameter [0:0] SAS_12G_MODE = 1'b0;
+ parameter integer SAS_MAX_COM = 64;
+ parameter integer SAS_MIN_COM = 36;
parameter [3:0] SATA_BURST_SEQ_LEN = 4'b1111;
parameter [2:0] SATA_BURST_VAL = 3'b100;
parameter SATA_CPLL_CFG = "VCO_3000MHZ";
parameter [2:0] SATA_EIDLE_VAL = 3'b100;
+ parameter integer SATA_MAX_BURST = 8;
+ parameter integer SATA_MAX_INIT = 21;
+ parameter integer SATA_MAX_WAKE = 7;
+ parameter integer SATA_MIN_BURST = 4;
+ parameter integer SATA_MIN_INIT = 12;
+ parameter integer SATA_MIN_WAKE = 4;
parameter SHOW_REALIGN_COMMA = "TRUE";
- parameter SIM_DEVICE = "ULTRASCALE_PLUS";
parameter SIM_MODE = "FAST";
parameter SIM_RECEIVER_DETECT_PASS = "TRUE";
parameter SIM_RESET_SPEEDUP = "TRUE";
- parameter SIM_TX_EIDLE_DRIVE_LEVEL = "Z";
- parameter [0:0] SRSTMODE = 1'b0;
+ parameter [0:0] SIM_TX_EIDLE_DRIVE_LEVEL = 1'b0;
+ parameter integer SIM_VERSION = 2;
parameter [1:0] TAPDLY_SET_TX = 2'h0;
parameter [3:0] TEMPERATURE_PAR = 4'b0010;
parameter [14:0] TERM_RCAL_CFG = 15'b100001000010000;
@@ -15520,20 +15572,18 @@ module GTHE4_CHANNEL (...);
parameter [7:0] TST_RSV1 = 8'h00;
parameter TXBUF_EN = "TRUE";
parameter TXBUF_RESET_ON_RATE_CHANGE = "FALSE";
- parameter [15:0] TXDLY_CFG = 16'h0010;
+ parameter [15:0] TXDLY_CFG = 16'h001F;
parameter [15:0] TXDLY_LCFG = 16'h0030;
- parameter [3:0] TXDRVBIAS_N = 4'b1010;
parameter TXFIFO_ADDR_CFG = "LOW";
parameter integer TXGBOX_FIFO_INIT_RD_ADDR = 4;
parameter TXGEARBOX_EN = "FALSE";
parameter integer TXOUT_DIV = 4;
parameter [4:0] TXPCSRESET_TIME = 5'b00001;
- parameter [15:0] TXPHDLY_CFG0 = 16'h6020;
- parameter [15:0] TXPHDLY_CFG1 = 16'h0002;
+ parameter [15:0] TXPHDLY_CFG0 = 16'h2020;
+ parameter [15:0] TXPHDLY_CFG1 = 16'h0001;
parameter [15:0] TXPH_CFG = 16'h0123;
parameter [15:0] TXPH_CFG2 = 16'h0000;
parameter [4:0] TXPH_MONITOR_SEL = 5'b00000;
- parameter [15:0] TXPI_CFG = 16'h0000;
parameter [1:0] TXPI_CFG0 = 2'b00;
parameter [1:0] TXPI_CFG1 = 2'b00;
parameter [1:0] TXPI_CFG2 = 2'b00;
@@ -15543,29 +15593,30 @@ module GTHE4_CHANNEL (...);
parameter [0:0] TXPI_GRAY_SEL = 1'b0;
parameter [0:0] TXPI_INVSTROBE_SEL = 1'b0;
parameter [0:0] TXPI_LPM = 1'b0;
- parameter [0:0] TXPI_PPM = 1'b0;
parameter TXPI_PPMCLK_SEL = "TXUSRCLK2";
parameter [7:0] TXPI_PPM_CFG = 8'b00000000;
+ parameter [15:0] TXPI_RSV0 = 16'h0000;
parameter [2:0] TXPI_SYNFREQ_PPM = 3'b000;
parameter [0:0] TXPI_VREFSEL = 1'b0;
parameter [4:0] TXPMARESET_TIME = 5'b00001;
- parameter [0:0] TXREFCLKDIV2_SEL = 1'b0;
parameter [0:0] TXSYNC_MULTILANE = 1'b0;
parameter [0:0] TXSYNC_OVRD = 1'b0;
parameter [0:0] TXSYNC_SKIP_DA = 1'b0;
parameter integer TX_CLK25_DIV = 8;
parameter [0:0] TX_CLKMUX_EN = 1'b1;
+ parameter [0:0] TX_CLKREG_PDB = 1'b0;
+ parameter [2:0] TX_CLKREG_SET = 3'b000;
parameter integer TX_DATA_WIDTH = 20;
- parameter [15:0] TX_DCC_LOOP_RST_CFG = 16'h0000;
+ parameter [5:0] TX_DCD_CFG = 6'b000010;
+ parameter [0:0] TX_DCD_EN = 1'b0;
parameter [5:0] TX_DEEMPH0 = 6'b000000;
parameter [5:0] TX_DEEMPH1 = 6'b000000;
- parameter [5:0] TX_DEEMPH2 = 6'b000000;
- parameter [5:0] TX_DEEMPH3 = 6'b000000;
parameter [4:0] TX_DIVRESET_TIME = 5'b00001;
parameter TX_DRIVE_MODE = "DIRECT";
parameter integer TX_DRVMUX_CTRL = 2;
parameter [2:0] TX_EIDLE_ASSERT_DELAY = 3'b110;
parameter [2:0] TX_EIDLE_DEASSERT_DELAY = 3'b100;
+ parameter [0:0] TX_EML_PHI_TUNE = 1'b0;
parameter [0:0] TX_FABINT_USRCLK_FLOP = 1'b0;
parameter [0:0] TX_FIFO_BYP_EN = 1'b0;
parameter [0:0] TX_IDLE_DATA_ZERO = 1'b0;
@@ -15582,75 +15633,44 @@ module GTHE4_CHANNEL (...);
parameter [6:0] TX_MARGIN_LOW_2 = 7'b1000010;
parameter [6:0] TX_MARGIN_LOW_3 = 7'b1000000;
parameter [6:0] TX_MARGIN_LOW_4 = 7'b1000000;
+ parameter [2:0] TX_MODE_SEL = 3'b000;
parameter [15:0] TX_PHICAL_CFG0 = 16'h0000;
- parameter [15:0] TX_PHICAL_CFG1 = 16'h003F;
+ parameter [15:0] TX_PHICAL_CFG1 = 16'h7E00;
parameter [15:0] TX_PHICAL_CFG2 = 16'h0000;
parameter integer TX_PI_BIASSET = 0;
- parameter [1:0] TX_PI_IBIAS_MID = 2'b00;
+ parameter [15:0] TX_PI_CFG0 = 16'h0000;
+ parameter [15:0] TX_PI_CFG1 = 16'h0000;
+ parameter [0:0] TX_PI_DIV2_MODE_B = 1'b0;
+ parameter [0:0] TX_PI_SEL_QPLL0 = 1'b0;
+ parameter [0:0] TX_PI_SEL_QPLL1 = 1'b0;
parameter [0:0] TX_PMADATA_OPT = 1'b0;
parameter [0:0] TX_PMA_POWER_SAVE = 1'b0;
- parameter [15:0] TX_PMA_RSV0 = 16'h0008;
parameter integer TX_PREDRV_CTRL = 2;
parameter TX_PROGCLK_SEL = "POSTPI";
parameter real TX_PROGDIV_CFG = 0.0;
parameter [15:0] TX_PROGDIV_RATE = 16'h0001;
- parameter [0:0] TX_QPI_STATUS_EN = 1'b0;
parameter [13:0] TX_RXDETECT_CFG = 14'h0032;
- parameter integer TX_RXDETECT_REF = 3;
+ parameter integer TX_RXDETECT_REF = 4;
parameter [2:0] TX_SAMPLE_PERIOD = 3'b101;
parameter [0:0] TX_SARC_LPBK_ENB = 1'b0;
- parameter [1:0] TX_SW_MEAS = 2'b00;
- parameter [2:0] TX_VREG_CTRL = 3'b000;
- parameter [0:0] TX_VREG_PDB = 1'b0;
- parameter [1:0] TX_VREG_VREFSEL = 2'b00;
parameter TX_XCLK_SEL = "TXOUT";
- parameter [0:0] USB_BOTH_BURST_IDLE = 1'b0;
- parameter [6:0] USB_BURSTMAX_U3WAKE = 7'b1111111;
- parameter [6:0] USB_BURSTMIN_U3WAKE = 7'b1100011;
- parameter [0:0] USB_CLK_COR_EQ_EN = 1'b0;
- parameter [0:0] USB_EXT_CNTL = 1'b1;
- parameter [9:0] USB_IDLEMAX_POLLING = 10'b1010111011;
- parameter [9:0] USB_IDLEMIN_POLLING = 10'b0100101011;
- parameter [8:0] USB_LFPSPING_BURST = 9'b000000101;
- parameter [8:0] USB_LFPSPOLLING_BURST = 9'b000110001;
- parameter [8:0] USB_LFPSPOLLING_IDLE_MS = 9'b000000100;
- parameter [8:0] USB_LFPSU1EXIT_BURST = 9'b000011101;
- parameter [8:0] USB_LFPSU2LPEXIT_BURST_MS = 9'b001100011;
- parameter [8:0] USB_LFPSU3WAKE_BURST_MS = 9'b111110011;
- parameter [3:0] USB_LFPS_TPERIOD = 4'b0011;
- parameter [0:0] USB_LFPS_TPERIOD_ACCURATE = 1'b1;
- parameter [0:0] USB_MODE = 1'b0;
- parameter [0:0] USB_PCIE_ERR_REP_DIS = 1'b0;
- parameter integer USB_PING_SATA_MAX_INIT = 21;
- parameter integer USB_PING_SATA_MIN_INIT = 12;
- parameter integer USB_POLL_SATA_MAX_BURST = 8;
- parameter integer USB_POLL_SATA_MIN_BURST = 4;
- parameter [0:0] USB_RAW_ELEC = 1'b0;
- parameter [0:0] USB_RXIDLE_P0_CTRL = 1'b1;
- parameter [0:0] USB_TXIDLE_TUNE_ENABLE = 1'b1;
- parameter integer USB_U1_SATA_MAX_WAKE = 7;
- parameter integer USB_U1_SATA_MIN_WAKE = 4;
- parameter integer USB_U2_SAS_MAX_COM = 64;
- parameter integer USB_U2_SAS_MIN_COM = 36;
parameter [0:0] USE_PCS_CLK_PHASE_SEL = 1'b0;
- parameter [0:0] Y_ALL_MODE = 1'b0;
- output BUFGTCE;
+ output [2:0] BUFGTCE;
output [2:0] BUFGTCEMASK;
output [8:0] BUFGTDIV;
- output BUFGTRESET;
+ output [2:0] BUFGTRESET;
output [2:0] BUFGTRSTMASK;
output CPLLFBCLKLOST;
output CPLLLOCK;
output CPLLREFCLKLOST;
- output [15:0] DMONITOROUT;
- output DMONITOROUTCLK;
+ output [16:0] DMONITOROUT;
output [15:0] DRPDO;
output DRPRDY;
output EYESCANDATAERROR;
- output GTHTXN;
- output GTHTXP;
output GTPOWERGOOD;
output GTREFCLKMONITOR;
+ output GTYTXN;
+ output GTYTXP;
output PCIERATEGEN3;
output PCIERATEIDLE;
output [1:0] PCIERATEQPLLPD;
@@ -15661,8 +15681,7 @@ module GTHE4_CHANNEL (...);
output PCIEUSERRATESTART;
output [15:0] PCSRSVDOUT;
output PHYSTATUS;
- output [15:0] PINRSRVDAS;
- output POWERPRESENT;
+ output [7:0] PINRSRVDAS;
output RESETEXCEPTION;
output [2:0] RXBUFSTATUS;
output RXBYTEISALIGNED;
@@ -15690,10 +15709,7 @@ module GTHE4_CHANNEL (...);
output RXELECIDLE;
output [5:0] RXHEADER;
output [1:0] RXHEADERVALID;
- output RXLFPSTRESETDET;
- output RXLFPSU2LPEXITDET;
- output RXLFPSU3WAKEDET;
- output [7:0] RXMONITOROUT;
+ output [6:0] RXMONITOROUT;
output RXOSINTDONE;
output RXOSINTSTARTED;
output RXOSINTSTROBEDONE;
@@ -15707,8 +15723,6 @@ module GTHE4_CHANNEL (...);
output RXPRBSERR;
output RXPRBSLOCKED;
output RXPRGDIVRESETDONE;
- output RXQPISENN;
- output RXQPISENP;
output RXRATEDONE;
output RXRECCLKOUT;
output RXRESETDONE;
@@ -15732,8 +15746,6 @@ module GTHE4_CHANNEL (...);
output TXPHINITDONE;
output TXPMARESETDONE;
output TXPRGDIVRESETDONE;
- output TXQPISENN;
- output TXQPISENP;
output TXRATEDONE;
output TXRESETDONE;
output TXSYNCDONE;
@@ -15744,7 +15756,6 @@ module GTHE4_CHANNEL (...);
input CFGRESET;
input CLKRSVD0;
input CLKRSVD1;
- input CPLLFREQLOCK;
input CPLLLOCKDETCLK;
input CPLLLOCKEN;
input CPLLPD;
@@ -15756,64 +15767,65 @@ module GTHE4_CHANNEL (...);
input DRPCLK;
input [15:0] DRPDI;
input DRPEN;
- input DRPRST;
input DRPWE;
+ input ELPCALDVORWREN;
+ input ELPCALPAORWREN;
+ input EVODDPHICALDONE;
+ input EVODDPHICALSTART;
+ input EVODDPHIDRDEN;
+ input EVODDPHIDWREN;
+ input EVODDPHIXRDEN;
+ input EVODDPHIXWREN;
+ input EYESCANMODE;
input EYESCANRESET;
input EYESCANTRIGGER;
- input FREQOS;
input GTGREFCLK;
- input GTHRXN;
- input GTHRXP;
input GTNORTHREFCLK0;
input GTNORTHREFCLK1;
input GTREFCLK0;
input GTREFCLK1;
+ input GTRESETSEL;
input [15:0] GTRSVD;
input GTRXRESET;
- input GTRXRESETSEL;
input GTSOUTHREFCLK0;
input GTSOUTHREFCLK1;
input GTTXRESET;
- input GTTXRESETSEL;
- input INCPCTRL;
+ input GTYRXN;
+ input GTYRXP;
input [2:0] LOOPBACK;
+ input [15:0] LOOPRSVD;
+ input LPBKRXTXSEREN;
+ input LPBKTXRXSEREN;
input PCIEEQRXEQADAPTDONE;
input PCIERSTIDLE;
input PCIERSTTXSYNCSTART;
input PCIEUSERRATEDONE;
input [15:0] PCSRSVDIN;
+ input [4:0] PCSRSVDIN2;
+ input [4:0] PMARSVDIN;
input QPLL0CLK;
- input QPLL0FREQLOCK;
input QPLL0REFCLK;
input QPLL1CLK;
- input QPLL1FREQLOCK;
input QPLL1REFCLK;
input RESETOVRD;
+ input RSTCLKENTX;
input RX8B10BEN;
- input RXAFECFOKEN;
input RXBUFRESET;
input RXCDRFREQRESET;
input RXCDRHOLD;
input RXCDROVRDEN;
input RXCDRRESET;
+ input RXCDRRESETRSV;
input RXCHBONDEN;
input [4:0] RXCHBONDI;
input [2:0] RXCHBONDLEVEL;
input RXCHBONDMASTER;
input RXCHBONDSLAVE;
input RXCKCALRESET;
- input [6:0] RXCKCALSTART;
input RXCOMMADETEN;
- input [1:0] RXDFEAGCCTRL;
+ input RXDCCFORCESTART;
input RXDFEAGCHOLD;
input RXDFEAGCOVRDEN;
- input [3:0] RXDFECFOKFCNUM;
- input RXDFECFOKFEN;
- input RXDFECFOKFPULSE;
- input RXDFECFOKHOLD;
- input RXDFECFOKOVREN;
- input RXDFEKHHOLD;
- input RXDFEKHOVRDEN;
input RXDFELFHOLD;
input RXDFELFOVRDEN;
input RXDFELPMRESET;
@@ -15849,13 +15861,13 @@ module GTHE4_CHANNEL (...);
input RXDFEUTOVRDEN;
input RXDFEVPHOLD;
input RXDFEVPOVRDEN;
+ input RXDFEVSEN;
input RXDFEXYDEN;
input RXDLYBYPASS;
input RXDLYEN;
input RXDLYOVRDEN;
input RXDLYSRESET;
input [1:0] RXELECIDLEMODE;
- input RXEQTRAINING;
input RXGEARBOXSLIP;
input RXLATCLK;
input RXLPMEN;
@@ -15872,6 +15884,12 @@ module GTHE4_CHANNEL (...);
input RXOOBRESET;
input RXOSCALRESET;
input RXOSHOLD;
+ input [3:0] RXOSINTCFG;
+ input RXOSINTEN;
+ input RXOSINTHOLD;
+ input RXOSINTOVRDEN;
+ input RXOSINTSTROBE;
+ input RXOSINTTESTOVRDEN;
input RXOSOVRDEN;
input [2:0] RXOUTCLKSEL;
input RXPCOMMAALIGNEN;
@@ -15888,7 +15906,6 @@ module GTHE4_CHANNEL (...);
input RXPRBSCNTRESET;
input [3:0] RXPRBSSEL;
input RXPROGDIVRESET;
- input RXQPIEN;
input [2:0] RXRATE;
input RXRATEMODE;
input RXSLIDE;
@@ -15898,7 +15915,6 @@ module GTHE4_CHANNEL (...);
input RXSYNCIN;
input RXSYNCMODE;
input [1:0] RXSYSCLKSEL;
- input RXTERMINATION;
input RXUSERRDY;
input RXUSRCLK;
input RXUSRCLK2;
@@ -15906,6 +15922,7 @@ module GTHE4_CHANNEL (...);
input [19:0] TSTIN;
input [7:0] TX8B10BBYPASS;
input TX8B10BEN;
+ input [2:0] TXBUFDIFFCTRL;
input TXCOMINIT;
input TXCOMSAS;
input TXCOMWAKE;
@@ -15916,9 +15933,10 @@ module GTHE4_CHANNEL (...);
input [7:0] TXDATAEXTENDRSVD;
input TXDCCFORCESTART;
input TXDCCRESET;
- input [1:0] TXDEEMPH;
+ input TXDEEMPH;
input TXDETECTRX;
input [4:0] TXDIFFCTRL;
+ input TXDIFFPD;
input TXDLYBYPASS;
input TXDLYEN;
input TXDLYHOLD;
@@ -15926,17 +15944,12 @@ module GTHE4_CHANNEL (...);
input TXDLYSRESET;
input TXDLYUPDOWN;
input TXELECIDLE;
+ input TXELFORCESTART;
input [5:0] TXHEADER;
input TXINHIBIT;
input TXLATCLK;
- input TXLFPSTRESET;
- input TXLFPSU2LPEXIT;
- input TXLFPSU3WAKE;
input [6:0] TXMAINCURSOR;
input [2:0] TXMARGIN;
- input TXMUXDCDEXHOLD;
- input TXMUXDCDORWREN;
- input TXONESZEROS;
input [2:0] TXOUTCLKSEL;
input TXPCSRESET;
input [1:0] TXPD;
@@ -15962,8 +15975,6 @@ module GTHE4_CHANNEL (...);
input [3:0] TXPRBSSEL;
input [4:0] TXPRECURSOR;
input TXPROGDIVRESET;
- input TXQPIBIASEN;
- input TXQPIWEAKPUP;
input [2:0] TXRATE;
input TXRATEMODE;
input [6:0] TXSEQUENCE;
@@ -15977,34 +15988,28 @@ module GTHE4_CHANNEL (...);
input TXUSRCLK2;
endmodule
-module GTHE4_COMMON (...);
- parameter [0:0] AEN_QPLL0_FBDIV = 1'b1;
- parameter [0:0] AEN_QPLL1_FBDIV = 1'b1;
- parameter [0:0] AEN_SDM0TOGGLE = 1'b0;
- parameter [0:0] AEN_SDM1TOGGLE = 1'b0;
- parameter [0:0] A_SDM0TOGGLE = 1'b0;
- parameter [8:0] A_SDM1DATA_HIGH = 9'b000000000;
- parameter [15:0] A_SDM1DATA_LOW = 16'b0000000000000000;
- parameter [0:0] A_SDM1TOGGLE = 1'b0;
+module GTYE3_COMMON (...);
+ parameter [15:0] A_SDM1DATA1_0 = 16'b0000000000000000;
+ parameter [8:0] A_SDM1DATA1_1 = 9'b000000000;
parameter [15:0] BIAS_CFG0 = 16'h0000;
parameter [15:0] BIAS_CFG1 = 16'h0000;
parameter [15:0] BIAS_CFG2 = 16'h0000;
parameter [15:0] BIAS_CFG3 = 16'h0000;
parameter [15:0] BIAS_CFG4 = 16'h0000;
- parameter [15:0] BIAS_CFG_RSVD = 16'h0000;
+ parameter [9:0] BIAS_CFG_RSVD = 10'b0000000000;
parameter [15:0] COMMON_CFG0 = 16'h0000;
parameter [15:0] COMMON_CFG1 = 16'h0000;
- parameter [15:0] POR_CFG = 16'h0000;
- parameter [15:0] PPF0_CFG = 16'h0F00;
- parameter [15:0] PPF1_CFG = 16'h0F00;
+ parameter [15:0] POR_CFG = 16'h0004;
+ parameter [15:0] PPF0_CFG = 16'h0FFF;
+ parameter [15:0] PPF1_CFG = 16'h0FFF;
parameter QPLL0CLKOUT_RATE = "FULL";
- parameter [15:0] QPLL0_CFG0 = 16'h391C;
+ parameter [15:0] QPLL0_CFG0 = 16'h301C;
parameter [15:0] QPLL0_CFG1 = 16'h0000;
parameter [15:0] QPLL0_CFG1_G3 = 16'h0020;
- parameter [15:0] QPLL0_CFG2 = 16'h0F80;
- parameter [15:0] QPLL0_CFG2_G3 = 16'h0F80;
+ parameter [15:0] QPLL0_CFG2 = 16'h0780;
+ parameter [15:0] QPLL0_CFG2_G3 = 16'h0780;
parameter [15:0] QPLL0_CFG3 = 16'h0120;
- parameter [15:0] QPLL0_CFG4 = 16'h0002;
+ parameter [15:0] QPLL0_CFG4 = 16'h0021;
parameter [9:0] QPLL0_CP = 10'b0000011111;
parameter [9:0] QPLL0_CP_G3 = 10'b0000011111;
parameter integer QPLL0_FBDIV = 66;
@@ -16013,22 +16018,20 @@ module GTHE4_COMMON (...);
parameter [7:0] QPLL0_INIT_CFG1 = 8'h00;
parameter [15:0] QPLL0_LOCK_CFG = 16'h01E8;
parameter [15:0] QPLL0_LOCK_CFG_G3 = 16'h21E8;
- parameter [9:0] QPLL0_LPF = 10'b1011111111;
+ parameter [9:0] QPLL0_LPF = 10'b1111111111;
parameter [9:0] QPLL0_LPF_G3 = 10'b1111111111;
- parameter [0:0] QPLL0_PCI_EN = 1'b0;
- parameter [0:0] QPLL0_RATE_SW_USE_DRP = 1'b0;
- parameter integer QPLL0_REFCLK_DIV = 1;
+ parameter integer QPLL0_REFCLK_DIV = 2;
parameter [15:0] QPLL0_SDM_CFG0 = 16'h0040;
parameter [15:0] QPLL0_SDM_CFG1 = 16'h0000;
parameter [15:0] QPLL0_SDM_CFG2 = 16'h0000;
parameter QPLL1CLKOUT_RATE = "FULL";
- parameter [15:0] QPLL1_CFG0 = 16'h691C;
- parameter [15:0] QPLL1_CFG1 = 16'h0020;
+ parameter [15:0] QPLL1_CFG0 = 16'h301C;
+ parameter [15:0] QPLL1_CFG1 = 16'h0000;
parameter [15:0] QPLL1_CFG1_G3 = 16'h0020;
- parameter [15:0] QPLL1_CFG2 = 16'h0F80;
- parameter [15:0] QPLL1_CFG2_G3 = 16'h0F80;
+ parameter [15:0] QPLL1_CFG2 = 16'h0780;
+ parameter [15:0] QPLL1_CFG2_G3 = 16'h0780;
parameter [15:0] QPLL1_CFG3 = 16'h0120;
- parameter [15:0] QPLL1_CFG4 = 16'h0002;
+ parameter [15:0] QPLL1_CFG4 = 16'h0021;
parameter [9:0] QPLL1_CP = 10'b0000011111;
parameter [9:0] QPLL1_CP_G3 = 10'b0000011111;
parameter integer QPLL1_FBDIV = 66;
@@ -16037,12 +16040,10 @@ module GTHE4_COMMON (...);
parameter [7:0] QPLL1_INIT_CFG1 = 8'h00;
parameter [15:0] QPLL1_LOCK_CFG = 16'h01E8;
parameter [15:0] QPLL1_LOCK_CFG_G3 = 16'h21E8;
- parameter [9:0] QPLL1_LPF = 10'b1011111111;
+ parameter [9:0] QPLL1_LPF = 10'b1111111111;
parameter [9:0] QPLL1_LPF_G3 = 10'b1111111111;
- parameter [0:0] QPLL1_PCI_EN = 1'b0;
- parameter [0:0] QPLL1_RATE_SW_USE_DRP = 1'b0;
- parameter integer QPLL1_REFCLK_DIV = 1;
- parameter [15:0] QPLL1_SDM_CFG0 = 16'h0000;
+ parameter integer QPLL1_REFCLK_DIV = 2;
+ parameter [15:0] QPLL1_SDM_CFG0 = 16'h0040;
parameter [15:0] QPLL1_SDM_CFG1 = 16'h0000;
parameter [15:0] QPLL1_SDM_CFG2 = 16'h0000;
parameter [15:0] RSVD_ATTR0 = 16'h0000;
@@ -16051,15 +16052,15 @@ module GTHE4_COMMON (...);
parameter [15:0] RSVD_ATTR3 = 16'h0000;
parameter [1:0] RXRECCLKOUT0_SEL = 2'b00;
parameter [1:0] RXRECCLKOUT1_SEL = 2'b00;
- parameter [0:0] SARC_ENB = 1'b0;
+ parameter [0:0] SARC_EN = 1'b1;
parameter [0:0] SARC_SEL = 1'b0;
parameter [15:0] SDM0INITSEED0_0 = 16'b0000000000000000;
parameter [8:0] SDM0INITSEED0_1 = 9'b000000000;
parameter [15:0] SDM1INITSEED0_0 = 16'b0000000000000000;
parameter [8:0] SDM1INITSEED0_1 = 9'b000000000;
- parameter SIM_DEVICE = "ULTRASCALE_PLUS";
parameter SIM_MODE = "FAST";
parameter SIM_RESET_SPEEDUP = "TRUE";
+ parameter integer SIM_VERSION = 2;
output [15:0] DRPDO;
output DRPRDY;
output [7:0] PMARSVDOUT0;
@@ -16078,20 +16079,18 @@ module GTHE4_COMMON (...);
output [7:0] QPLLDMONITOR1;
output REFCLKOUTMONITOR0;
output REFCLKOUTMONITOR1;
- output [1:0] RXRECCLK0SEL;
- output [1:0] RXRECCLK1SEL;
+ output [1:0] RXRECCLK0_SEL;
+ output [1:0] RXRECCLK1_SEL;
output [3:0] SDM0FINALOUT;
output [14:0] SDM0TESTDATA;
output [3:0] SDM1FINALOUT;
output [14:0] SDM1TESTDATA;
- output [9:0] TCONGPO;
- output TCONRSVDOUT0;
input BGBYPASSB;
input BGMONITORENB;
input BGPDB;
input [4:0] BGRCALOVRD;
input BGRCALOVRDENB;
- input [15:0] DRPADDR;
+ input [9:0] DRPADDR;
input DRPCLK;
input [15:0] DRPDI;
input DRPEN;
@@ -16110,21 +16109,15 @@ module GTHE4_COMMON (...);
input GTSOUTHREFCLK01;
input GTSOUTHREFCLK10;
input GTSOUTHREFCLK11;
- input [2:0] PCIERATEQPLL0;
- input [2:0] PCIERATEQPLL1;
input [7:0] PMARSVD0;
input [7:0] PMARSVD1;
input QPLL0CLKRSVD0;
- input QPLL0CLKRSVD1;
- input [7:0] QPLL0FBDIV;
input QPLL0LOCKDETCLK;
input QPLL0LOCKEN;
input QPLL0PD;
input [2:0] QPLL0REFCLKSEL;
input QPLL0RESET;
input QPLL1CLKRSVD0;
- input QPLL1CLKRSVD1;
- input [7:0] QPLL1FBDIV;
input QPLL1LOCKDETCLK;
input QPLL1LOCKEN;
input QPLL1PD;
@@ -16137,25 +16130,55 @@ module GTHE4_COMMON (...);
input RCALENB;
input [24:0] SDM0DATA;
input SDM0RESET;
- input SDM0TOGGLE;
input [1:0] SDM0WIDTH;
input [24:0] SDM1DATA;
input SDM1RESET;
- input SDM1TOGGLE;
input [1:0] SDM1WIDTH;
- input [9:0] TCONGPI;
- input TCONPOWERUP;
- input [1:0] TCONRESET;
- input [1:0] TCONRSVDIN1;
endmodule
-module GTYE3_CHANNEL (...);
+module IBUFDS_GTE3 (...);
+ parameter [0:0] REFCLK_EN_TX_PATH = 1'b0;
+ parameter [1:0] REFCLK_HROW_CK_SEL = 2'b00;
+ parameter [1:0] REFCLK_ICNTL_RX = 2'b00;
+ output O;
+ output ODIV2;
+ input CEB;
+ (* iopad_external_pin *)
+ input I;
+ (* iopad_external_pin *)
+ input IB;
+endmodule
+
+module OBUFDS_GTE3 (...);
+ parameter [0:0] REFCLK_EN_TX_PATH = 1'b0;
+ parameter [4:0] REFCLK_ICNTL_TX = 5'b00000;
+ (* iopad_external_pin *)
+ output O;
+ (* iopad_external_pin *)
+ output OB;
+ input CEB;
+ input I;
+endmodule
+
+module OBUFDS_GTE3_ADV (...);
+ parameter [0:0] REFCLK_EN_TX_PATH = 1'b0;
+ parameter [4:0] REFCLK_ICNTL_TX = 5'b00000;
+ (* iopad_external_pin *)
+ output O;
+ (* iopad_external_pin *)
+ output OB;
+ input CEB;
+ input [3:0] I;
+ input [1:0] RXRECCLK_SEL;
+endmodule
+
+module GTHE4_CHANNEL (...);
parameter [0:0] ACJTAG_DEBUG_MODE = 1'b0;
parameter [0:0] ACJTAG_MODE = 1'b0;
parameter [0:0] ACJTAG_RESET = 1'b0;
parameter [15:0] ADAPT_CFG0 = 16'h9200;
parameter [15:0] ADAPT_CFG1 = 16'h801C;
- parameter [15:0] ADAPT_CFG2 = 16'b0000000000000000;
+ parameter [15:0] ADAPT_CFG2 = 16'h0000;
parameter ALIGN_COMMA_DOUBLE = "FALSE";
parameter [9:0] ALIGN_COMMA_ENABLE = 10'b0001111111;
parameter integer ALIGN_COMMA_WORD = 1;
@@ -16163,14 +16186,15 @@ module GTYE3_CHANNEL (...);
parameter [9:0] ALIGN_MCOMMA_VALUE = 10'b1010000011;
parameter ALIGN_PCOMMA_DET = "TRUE";
parameter [9:0] ALIGN_PCOMMA_VALUE = 10'b0101111100;
- parameter [0:0] AUTO_BW_SEL_BYPASS = 1'b0;
parameter [0:0] A_RXOSCALRESET = 1'b0;
parameter [0:0] A_RXPROGDIVRESET = 1'b0;
+ parameter [0:0] A_RXTERMINATION = 1'b1;
parameter [4:0] A_TXDIFFCTRL = 5'b01100;
parameter [0:0] A_TXPROGDIVRESET = 1'b0;
parameter [0:0] CAPBYPASS_FORCE = 1'b0;
parameter CBCC_DATA_SOURCE_SEL = "DECODED";
parameter [0:0] CDR_SWAP_MODE_EN = 1'b0;
+ parameter [0:0] CFOK_PWRSVE_EN = 1'b1;
parameter CHAN_BOND_KEEP_ALIGN = "FALSE";
parameter integer CHAN_BOND_MAX_SKEW = 7;
parameter [9:0] CHAN_BOND_SEQ_1_1 = 10'b0101111100;
@@ -16185,7 +16209,7 @@ module GTYE3_CHANNEL (...);
parameter [3:0] CHAN_BOND_SEQ_2_ENABLE = 4'b1111;
parameter CHAN_BOND_SEQ_2_USE = "FALSE";
parameter integer CHAN_BOND_SEQ_LEN = 2;
- parameter [15:0] CH_HSPMUX = 16'h0000;
+ parameter [15:0] CH_HSPMUX = 16'h2424;
parameter [15:0] CKCAL1_CFG_0 = 16'b0000000000000000;
parameter [15:0] CKCAL1_CFG_1 = 16'b0000000000000000;
parameter [15:0] CKCAL1_CFG_2 = 16'b0000000000000000;
@@ -16195,7 +16219,7 @@ module GTYE3_CHANNEL (...);
parameter [15:0] CKCAL2_CFG_2 = 16'b0000000000000000;
parameter [15:0] CKCAL2_CFG_3 = 16'b0000000000000000;
parameter [15:0] CKCAL2_CFG_4 = 16'b0000000000000000;
- parameter [15:0] CKCAL_RSVD0 = 16'h0000;
+ parameter [15:0] CKCAL_RSVD0 = 16'h4000;
parameter [15:0] CKCAL_RSVD1 = 16'h0000;
parameter CLK_CORRECT_USE = "TRUE";
parameter CLK_COR_KEEP_IDLE = "FALSE";
@@ -16215,14 +16239,13 @@ module GTYE3_CHANNEL (...);
parameter [3:0] CLK_COR_SEQ_2_ENABLE = 4'b1111;
parameter CLK_COR_SEQ_2_USE = "FALSE";
parameter integer CLK_COR_SEQ_LEN = 2;
- parameter [15:0] CPLL_CFG0 = 16'h20F8;
- parameter [15:0] CPLL_CFG1 = 16'hA494;
- parameter [15:0] CPLL_CFG2 = 16'hF001;
- parameter [5:0] CPLL_CFG3 = 6'h00;
+ parameter [15:0] CPLL_CFG0 = 16'h01FA;
+ parameter [15:0] CPLL_CFG1 = 16'h24A9;
+ parameter [15:0] CPLL_CFG2 = 16'h6807;
+ parameter [15:0] CPLL_CFG3 = 16'h0000;
parameter integer CPLL_FBDIV = 4;
parameter integer CPLL_FBDIV_45 = 4;
parameter [15:0] CPLL_INIT_CFG0 = 16'h001E;
- parameter [7:0] CPLL_INIT_CFG1 = 8'h00;
parameter [15:0] CPLL_LOCK_CFG = 16'h01E8;
parameter integer CPLL_REFCLK_DIV = 1;
parameter [2:0] CTLE3_OCAP_EXT_CTRL = 3'b000;
@@ -16232,16 +16255,14 @@ module GTYE3_CHANNEL (...);
parameter DEC_MCOMMA_DETECT = "TRUE";
parameter DEC_PCOMMA_DETECT = "TRUE";
parameter DEC_VALID_COMMA_ONLY = "TRUE";
- parameter [0:0] DFE_D_X_REL_POS = 1'b0;
- parameter [0:0] DFE_VCM_COMP_EN = 1'b0;
+ parameter [0:0] DELAY_ELEC = 1'b0;
parameter [9:0] DMONITOR_CFG0 = 10'h000;
parameter [7:0] DMONITOR_CFG1 = 8'h00;
parameter [0:0] ES_CLK_PHASE_SEL = 1'b0;
parameter [5:0] ES_CONTROL = 6'b000000;
parameter ES_ERRDET_EN = "FALSE";
parameter ES_EYE_SCAN_EN = "FALSE";
- parameter [11:0] ES_HORZ_OFFSET = 12'h000;
- parameter [9:0] ES_PMA_CFG = 10'b0000000000;
+ parameter [11:0] ES_HORZ_OFFSET = 12'h800;
parameter [4:0] ES_PRESCALE = 5'b00000;
parameter [15:0] ES_QUALIFIER0 = 16'h0000;
parameter [15:0] ES_QUALIFIER1 = 16'h0000;
@@ -16273,32 +16294,19 @@ module GTYE3_CHANNEL (...);
parameter [15:0] ES_SDATA_MASK7 = 16'h0000;
parameter [15:0] ES_SDATA_MASK8 = 16'h0000;
parameter [15:0] ES_SDATA_MASK9 = 16'h0000;
- parameter [10:0] EVODD_PHI_CFG = 11'b00000000000;
parameter [0:0] EYE_SCAN_SWAP_EN = 1'b0;
parameter [3:0] FTS_DESKEW_SEQ_ENABLE = 4'b1111;
parameter [3:0] FTS_LANE_DESKEW_CFG = 4'b1111;
parameter FTS_LANE_DESKEW_EN = "FALSE";
parameter [4:0] GEARBOX_MODE = 5'b00000;
- parameter [0:0] GM_BIAS_SELECT = 1'b0;
parameter [0:0] ISCAN_CK_PH_SEL2 = 1'b0;
parameter [0:0] LOCAL_MASTER = 1'b0;
- parameter [15:0] LOOP0_CFG = 16'h0000;
- parameter [15:0] LOOP10_CFG = 16'h0000;
- parameter [15:0] LOOP11_CFG = 16'h0000;
- parameter [15:0] LOOP12_CFG = 16'h0000;
- parameter [15:0] LOOP13_CFG = 16'h0000;
- parameter [15:0] LOOP1_CFG = 16'h0000;
- parameter [15:0] LOOP2_CFG = 16'h0000;
- parameter [15:0] LOOP3_CFG = 16'h0000;
- parameter [15:0] LOOP4_CFG = 16'h0000;
- parameter [15:0] LOOP5_CFG = 16'h0000;
- parameter [15:0] LOOP6_CFG = 16'h0000;
- parameter [15:0] LOOP7_CFG = 16'h0000;
- parameter [15:0] LOOP8_CFG = 16'h0000;
- parameter [15:0] LOOP9_CFG = 16'h0000;
parameter [2:0] LPBK_BIAS_CTRL = 3'b000;
parameter [0:0] LPBK_EN_RCAL_B = 1'b0;
parameter [3:0] LPBK_EXT_RCAL = 4'b0000;
+ parameter [2:0] LPBK_IND_CTRL0 = 3'b000;
+ parameter [2:0] LPBK_IND_CTRL1 = 3'b000;
+ parameter [2:0] LPBK_IND_CTRL2 = 3'b000;
parameter [3:0] LPBK_RG_CTRL = 4'b0000;
parameter [1:0] OOBDIVCTL = 2'b00;
parameter [0:0] OOB_PWRUP = 1'b0;
@@ -16311,25 +16319,32 @@ module GTYE3_CHANNEL (...);
parameter [5:0] PCI3_RX_ELECIDLE_HI_COUNT = 6'b000000;
parameter [0:0] PCI3_RX_ELECIDLE_LP4_DISABLE = 1'b0;
parameter [0:0] PCI3_RX_FIFO_DISABLE = 1'b0;
+ parameter [4:0] PCIE3_CLK_COR_EMPTY_THRSH = 5'b00000;
+ parameter [5:0] PCIE3_CLK_COR_FULL_THRSH = 6'b010000;
+ parameter [4:0] PCIE3_CLK_COR_MAX_LAT = 5'b01000;
+ parameter [4:0] PCIE3_CLK_COR_MIN_LAT = 5'b00100;
+ parameter [5:0] PCIE3_CLK_COR_THRSH_TIMER = 6'b001000;
parameter [15:0] PCIE_BUFG_DIV_CTRL = 16'h0000;
+ parameter [1:0] PCIE_PLL_SEL_MODE_GEN12 = 2'h0;
+ parameter [1:0] PCIE_PLL_SEL_MODE_GEN3 = 2'h0;
+ parameter [1:0] PCIE_PLL_SEL_MODE_GEN4 = 2'h0;
parameter [15:0] PCIE_RXPCS_CFG_GEN3 = 16'h0000;
parameter [15:0] PCIE_RXPMA_CFG = 16'h0000;
parameter [15:0] PCIE_TXPCS_CFG_GEN3 = 16'h0000;
parameter [15:0] PCIE_TXPMA_CFG = 16'h0000;
parameter PCS_PCIE_EN = "FALSE";
parameter [15:0] PCS_RSVD0 = 16'b0000000000000000;
- parameter [2:0] PCS_RSVD1 = 3'b000;
parameter [11:0] PD_TRANS_TIME_FROM_P2 = 12'h03C;
parameter [7:0] PD_TRANS_TIME_NONE_P2 = 8'h19;
parameter [7:0] PD_TRANS_TIME_TO_P2 = 8'h64;
- parameter [1:0] PLL_SEL_MODE_GEN12 = 2'h0;
- parameter [1:0] PLL_SEL_MODE_GEN3 = 2'h0;
- parameter [15:0] PMA_RSV0 = 16'h0000;
- parameter [15:0] PMA_RSV1 = 16'h0000;
parameter integer PREIQ_FREQ_BST = 0;
parameter [2:0] PROCESS_PAR = 3'b010;
parameter [0:0] RATE_SW_USE_DRP = 1'b0;
+ parameter [0:0] RCLK_SIPO_DLY_ENB = 1'b0;
+ parameter [0:0] RCLK_SIPO_INV_EN = 1'b0;
parameter [0:0] RESET_POWERSAVE_DISABLE = 1'b0;
+ parameter [2:0] RTX_BUF_CML_CTRL = 3'b010;
+ parameter [1:0] RTX_BUF_TERM_CTRL = 2'b00;
parameter [4:0] RXBUFRESET_TIME = 5'b00001;
parameter RXBUF_ADDR_MODE = "FULL";
parameter [3:0] RXBUF_EIDLE_HI_CNT = 4'b1000;
@@ -16344,37 +16359,48 @@ module GTYE3_CHANNEL (...);
parameter integer RXBUF_THRESH_UNDFLW = 4;
parameter [4:0] RXCDRFREQRESET_TIME = 5'b00001;
parameter [4:0] RXCDRPHRESET_TIME = 5'b00001;
- parameter [15:0] RXCDR_CFG0 = 16'h0000;
- parameter [15:0] RXCDR_CFG0_GEN3 = 16'h0000;
- parameter [15:0] RXCDR_CFG1 = 16'h0300;
- parameter [15:0] RXCDR_CFG1_GEN3 = 16'h0300;
- parameter [15:0] RXCDR_CFG2 = 16'h0060;
- parameter [15:0] RXCDR_CFG2_GEN3 = 16'h0060;
- parameter [15:0] RXCDR_CFG3 = 16'h0000;
- parameter [15:0] RXCDR_CFG3_GEN3 = 16'h0000;
- parameter [15:0] RXCDR_CFG4 = 16'h0002;
- parameter [15:0] RXCDR_CFG4_GEN3 = 16'h0002;
- parameter [15:0] RXCDR_CFG5 = 16'h0000;
- parameter [15:0] RXCDR_CFG5_GEN3 = 16'h0000;
+ parameter [15:0] RXCDR_CFG0 = 16'h0003;
+ parameter [15:0] RXCDR_CFG0_GEN3 = 16'h0003;
+ parameter [15:0] RXCDR_CFG1 = 16'h0000;
+ parameter [15:0] RXCDR_CFG1_GEN3 = 16'h0000;
+ parameter [15:0] RXCDR_CFG2 = 16'h0164;
+ parameter [9:0] RXCDR_CFG2_GEN2 = 10'h164;
+ parameter [15:0] RXCDR_CFG2_GEN3 = 16'h0034;
+ parameter [15:0] RXCDR_CFG2_GEN4 = 16'h0034;
+ parameter [15:0] RXCDR_CFG3 = 16'h0024;
+ parameter [5:0] RXCDR_CFG3_GEN2 = 6'h24;
+ parameter [15:0] RXCDR_CFG3_GEN3 = 16'h0024;
+ parameter [15:0] RXCDR_CFG3_GEN4 = 16'h0024;
+ parameter [15:0] RXCDR_CFG4 = 16'h5CF6;
+ parameter [15:0] RXCDR_CFG4_GEN3 = 16'h5CF6;
+ parameter [15:0] RXCDR_CFG5 = 16'hB46B;
+ parameter [15:0] RXCDR_CFG5_GEN3 = 16'h146B;
parameter [0:0] RXCDR_FR_RESET_ON_EIDLE = 1'b0;
parameter [0:0] RXCDR_HOLD_DURING_EIDLE = 1'b0;
- parameter [15:0] RXCDR_LOCK_CFG0 = 16'h0001;
- parameter [15:0] RXCDR_LOCK_CFG1 = 16'h0000;
+ parameter [15:0] RXCDR_LOCK_CFG0 = 16'h0040;
+ parameter [15:0] RXCDR_LOCK_CFG1 = 16'h8000;
parameter [15:0] RXCDR_LOCK_CFG2 = 16'h0000;
parameter [15:0] RXCDR_LOCK_CFG3 = 16'h0000;
+ parameter [15:0] RXCDR_LOCK_CFG4 = 16'h0000;
parameter [0:0] RXCDR_PH_RESET_ON_EIDLE = 1'b0;
- parameter [1:0] RXCFOKDONE_SRC = 2'b00;
- parameter [15:0] RXCFOK_CFG0 = 16'h3E00;
- parameter [15:0] RXCFOK_CFG1 = 16'h0042;
+ parameter [15:0] RXCFOK_CFG0 = 16'h0000;
+ parameter [15:0] RXCFOK_CFG1 = 16'h0002;
parameter [15:0] RXCFOK_CFG2 = 16'h002D;
+ parameter [15:0] RXCKCAL1_IQ_LOOP_RST_CFG = 16'h0000;
+ parameter [15:0] RXCKCAL1_I_LOOP_RST_CFG = 16'h0000;
+ parameter [15:0] RXCKCAL1_Q_LOOP_RST_CFG = 16'h0000;
+ parameter [15:0] RXCKCAL2_DX_LOOP_RST_CFG = 16'h0000;
+ parameter [15:0] RXCKCAL2_D_LOOP_RST_CFG = 16'h0000;
+ parameter [15:0] RXCKCAL2_S_LOOP_RST_CFG = 16'h0000;
+ parameter [15:0] RXCKCAL2_X_LOOP_RST_CFG = 16'h0000;
parameter [6:0] RXDFELPMRESET_TIME = 7'b0001111;
parameter [15:0] RXDFELPM_KL_CFG0 = 16'h0000;
parameter [15:0] RXDFELPM_KL_CFG1 = 16'h0022;
parameter [15:0] RXDFELPM_KL_CFG2 = 16'h0100;
- parameter [15:0] RXDFE_CFG0 = 16'h4C00;
+ parameter [15:0] RXDFE_CFG0 = 16'h4000;
parameter [15:0] RXDFE_CFG1 = 16'h0000;
- parameter [15:0] RXDFE_GC_CFG0 = 16'h1E00;
- parameter [15:0] RXDFE_GC_CFG1 = 16'h1900;
+ parameter [15:0] RXDFE_GC_CFG0 = 16'h0000;
+ parameter [15:0] RXDFE_GC_CFG1 = 16'h0000;
parameter [15:0] RXDFE_GC_CFG2 = 16'h0000;
parameter [15:0] RXDFE_H2_CFG0 = 16'h0000;
parameter [15:0] RXDFE_H2_CFG1 = 16'h0002;
@@ -16404,26 +16430,31 @@ module GTYE3_CHANNEL (...);
parameter [15:0] RXDFE_HE_CFG1 = 16'h0002;
parameter [15:0] RXDFE_HF_CFG0 = 16'h0000;
parameter [15:0] RXDFE_HF_CFG1 = 16'h0002;
+ parameter [15:0] RXDFE_KH_CFG0 = 16'h0000;
+ parameter [15:0] RXDFE_KH_CFG1 = 16'h0000;
+ parameter [15:0] RXDFE_KH_CFG2 = 16'h0000;
+ parameter [15:0] RXDFE_KH_CFG3 = 16'h0000;
parameter [15:0] RXDFE_OS_CFG0 = 16'h0000;
- parameter [15:0] RXDFE_OS_CFG1 = 16'h0200;
+ parameter [15:0] RXDFE_OS_CFG1 = 16'h0002;
parameter [0:0] RXDFE_PWR_SAVING = 1'b0;
parameter [15:0] RXDFE_UT_CFG0 = 16'h0000;
parameter [15:0] RXDFE_UT_CFG1 = 16'h0002;
+ parameter [15:0] RXDFE_UT_CFG2 = 16'h0000;
parameter [15:0] RXDFE_VP_CFG0 = 16'h0000;
parameter [15:0] RXDFE_VP_CFG1 = 16'h0022;
- parameter [15:0] RXDLY_CFG = 16'h001F;
+ parameter [15:0] RXDLY_CFG = 16'h0010;
parameter [15:0] RXDLY_LCFG = 16'h0030;
parameter RXELECIDLE_CFG = "SIGCFG_4";
parameter integer RXGBOX_FIFO_INIT_RD_ADDR = 4;
parameter RXGEARBOX_EN = "FALSE";
parameter [4:0] RXISCANRESET_TIME = 5'b00001;
parameter [15:0] RXLPM_CFG = 16'h0000;
- parameter [15:0] RXLPM_GC_CFG = 16'h0200;
+ parameter [15:0] RXLPM_GC_CFG = 16'h1000;
parameter [15:0] RXLPM_KH_CFG0 = 16'h0000;
parameter [15:0] RXLPM_KH_CFG1 = 16'h0002;
- parameter [15:0] RXLPM_OS_CFG0 = 16'h0400;
+ parameter [15:0] RXLPM_OS_CFG0 = 16'h0000;
parameter [15:0] RXLPM_OS_CFG1 = 16'h0000;
- parameter [8:0] RXOOB_CFG = 9'b000000110;
+ parameter [8:0] RXOOB_CFG = 9'b000110000;
parameter RXOOB_CLK_CFG = "PMA";
parameter [4:0] RXOSCALRESET_TIME = 5'b00011;
parameter integer RXOUT_DIV = 4;
@@ -16434,9 +16465,9 @@ module GTYE3_CHANNEL (...);
parameter [15:0] RXPHSLIP_CFG = 16'h9933;
parameter [4:0] RXPH_MONITOR_SEL = 5'b00000;
parameter [0:0] RXPI_AUTO_BW_SEL_BYPASS = 1'b0;
- parameter [15:0] RXPI_CFG = 16'h0100;
+ parameter [15:0] RXPI_CFG0 = 16'h0002;
+ parameter [15:0] RXPI_CFG1 = 16'b0000000000000000;
parameter [0:0] RXPI_LPM = 1'b0;
- parameter [15:0] RXPI_RSV0 = 16'h0000;
parameter [1:0] RXPI_SEL_LC = 2'b00;
parameter [1:0] RXPI_STARTCODE = 2'b00;
parameter [0:0] RXPI_VREFSEL = 1'b0;
@@ -16444,13 +16475,14 @@ module GTYE3_CHANNEL (...);
parameter [4:0] RXPMARESET_TIME = 5'b00001;
parameter [0:0] RXPRBS_ERR_LOOPBACK = 1'b0;
parameter integer RXPRBS_LINKACQ_CNT = 15;
+ parameter [0:0] RXREFCLKDIV2_SEL = 1'b0;
parameter integer RXSLIDE_AUTO_WAIT = 7;
parameter RXSLIDE_MODE = "OFF";
parameter [0:0] RXSYNC_MULTILANE = 1'b0;
parameter [0:0] RXSYNC_OVRD = 1'b0;
parameter [0:0] RXSYNC_SKIP_DA = 1'b0;
parameter [0:0] RX_AFE_CM_EN = 1'b0;
- parameter [15:0] RX_BIAS_CFG0 = 16'h1534;
+ parameter [15:0] RX_BIAS_CFG0 = 16'h12B0;
parameter [5:0] RX_BUFFER_CFG = 6'b000000;
parameter [0:0] RX_CAPFF_SARC_ENB = 1'b0;
parameter integer RX_CLK25_DIV = 8;
@@ -16459,29 +16491,27 @@ module GTYE3_CHANNEL (...);
parameter [3:0] RX_CM_BUF_CFG = 4'b1010;
parameter [0:0] RX_CM_BUF_PD = 1'b0;
parameter integer RX_CM_SEL = 3;
- parameter integer RX_CM_TRIM = 10;
- parameter [0:0] RX_CTLE1_KHKL = 1'b0;
- parameter [0:0] RX_CTLE2_KHKL = 1'b0;
- parameter [0:0] RX_CTLE3_AGC = 1'b0;
+ parameter integer RX_CM_TRIM = 12;
+ parameter [7:0] RX_CTLE3_LPF = 8'b00000000;
parameter integer RX_DATA_WIDTH = 20;
parameter [5:0] RX_DDI_SEL = 6'b000000;
parameter RX_DEFER_RESET_BUF_EN = "TRUE";
- parameter [2:0] RX_DEGEN_CTRL = 3'b010;
- parameter integer RX_DFELPM_CFG0 = 6;
- parameter [0:0] RX_DFELPM_CFG1 = 1'b0;
+ parameter [2:0] RX_DEGEN_CTRL = 3'b011;
+ parameter integer RX_DFELPM_CFG0 = 0;
+ parameter [0:0] RX_DFELPM_CFG1 = 1'b1;
parameter [0:0] RX_DFELPM_KLKH_AGC_STUP_EN = 1'b1;
parameter [1:0] RX_DFE_AGC_CFG0 = 2'b00;
parameter integer RX_DFE_AGC_CFG1 = 4;
parameter integer RX_DFE_KL_LPM_KH_CFG0 = 1;
- parameter integer RX_DFE_KL_LPM_KH_CFG1 = 2;
+ parameter integer RX_DFE_KL_LPM_KH_CFG1 = 4;
parameter [1:0] RX_DFE_KL_LPM_KL_CFG0 = 2'b01;
- parameter [2:0] RX_DFE_KL_LPM_KL_CFG1 = 3'b010;
+ parameter integer RX_DFE_KL_LPM_KL_CFG1 = 4;
parameter [0:0] RX_DFE_LPM_HOLD_DURING_EIDLE = 1'b0;
parameter RX_DISPERR_SEQ_MATCH = "TRUE";
parameter [0:0] RX_DIV2_MODE_B = 1'b0;
parameter [4:0] RX_DIVRESET_TIME = 5'b00001;
parameter [0:0] RX_EN_CTLE_RCAL_B = 1'b0;
- parameter [0:0] RX_EN_HI_LR = 1'b0;
+ parameter [0:0] RX_EN_HI_LR = 1'b1;
parameter [8:0] RX_EXT_RL_CTRL = 9'b000000000;
parameter [6:0] RX_EYESCAN_VS_CODE = 7'b0000000;
parameter [0:0] RX_EYESCAN_VS_NEG_DIR = 1'b0;
@@ -16490,6 +16520,7 @@ module GTYE3_CHANNEL (...);
parameter [0:0] RX_FABINT_USRCLK_FLOP = 1'b0;
parameter integer RX_INT_DATAWIDTH = 1;
parameter [0:0] RX_PMA_POWER_SAVE = 1'b0;
+ parameter [15:0] RX_PMA_RSV0 = 16'h0000;
parameter real RX_PROGDIV_CFG = 0.0;
parameter [15:0] RX_PROGDIV_RATE = 16'h0001;
parameter [3:0] RX_RESLOAD_CTRL = 4'b0000;
@@ -16497,34 +16528,32 @@ module GTYE3_CHANNEL (...);
parameter [2:0] RX_SAMPLE_PERIOD = 3'b101;
parameter integer RX_SIG_VALID_DLY = 11;
parameter [0:0] RX_SUM_DFETAPREP_EN = 1'b0;
- parameter [3:0] RX_SUM_IREF_TUNE = 4'b0000;
- parameter [3:0] RX_SUM_VCMTUNE = 4'b1000;
+ parameter [3:0] RX_SUM_IREF_TUNE = 4'b1001;
+ parameter [3:0] RX_SUM_RESLOAD_CTRL = 4'b0000;
+ parameter [3:0] RX_SUM_VCMTUNE = 4'b1010;
parameter [0:0] RX_SUM_VCM_OVWR = 1'b0;
parameter [2:0] RX_SUM_VREF_TUNE = 3'b100;
parameter [1:0] RX_TUNE_AFE_OS = 2'b00;
parameter [2:0] RX_VREG_CTRL = 3'b101;
parameter [0:0] RX_VREG_PDB = 1'b1;
parameter [1:0] RX_WIDEMODE_CDR = 2'b01;
+ parameter [1:0] RX_WIDEMODE_CDR_GEN3 = 2'b01;
+ parameter [1:0] RX_WIDEMODE_CDR_GEN4 = 2'b01;
parameter RX_XCLK_SEL = "RXDES";
parameter [0:0] RX_XMODE_SEL = 1'b0;
- parameter integer SAS_MAX_COM = 64;
- parameter integer SAS_MIN_COM = 36;
+ parameter [0:0] SAMPLE_CLK_PHASE = 1'b0;
+ parameter [0:0] SAS_12G_MODE = 1'b0;
parameter [3:0] SATA_BURST_SEQ_LEN = 4'b1111;
parameter [2:0] SATA_BURST_VAL = 3'b100;
parameter SATA_CPLL_CFG = "VCO_3000MHZ";
parameter [2:0] SATA_EIDLE_VAL = 3'b100;
- parameter integer SATA_MAX_BURST = 8;
- parameter integer SATA_MAX_INIT = 21;
- parameter integer SATA_MAX_WAKE = 7;
- parameter integer SATA_MIN_BURST = 4;
- parameter integer SATA_MIN_INIT = 12;
- parameter integer SATA_MIN_WAKE = 4;
parameter SHOW_REALIGN_COMMA = "TRUE";
+ parameter SIM_DEVICE = "ULTRASCALE_PLUS";
parameter SIM_MODE = "FAST";
parameter SIM_RECEIVER_DETECT_PASS = "TRUE";
parameter SIM_RESET_SPEEDUP = "TRUE";
- parameter [0:0] SIM_TX_EIDLE_DRIVE_LEVEL = 1'b0;
- parameter integer SIM_VERSION = 2;
+ parameter SIM_TX_EIDLE_DRIVE_LEVEL = "Z";
+ parameter [0:0] SRSTMODE = 1'b0;
parameter [1:0] TAPDLY_SET_TX = 2'h0;
parameter [3:0] TEMPERATURE_PAR = 4'b0010;
parameter [14:0] TERM_RCAL_CFG = 15'b100001000010000;
@@ -16534,18 +16563,20 @@ module GTYE3_CHANNEL (...);
parameter [7:0] TST_RSV1 = 8'h00;
parameter TXBUF_EN = "TRUE";
parameter TXBUF_RESET_ON_RATE_CHANGE = "FALSE";
- parameter [15:0] TXDLY_CFG = 16'h001F;
+ parameter [15:0] TXDLY_CFG = 16'h0010;
parameter [15:0] TXDLY_LCFG = 16'h0030;
+ parameter [3:0] TXDRVBIAS_N = 4'b1010;
parameter TXFIFO_ADDR_CFG = "LOW";
parameter integer TXGBOX_FIFO_INIT_RD_ADDR = 4;
parameter TXGEARBOX_EN = "FALSE";
parameter integer TXOUT_DIV = 4;
parameter [4:0] TXPCSRESET_TIME = 5'b00001;
- parameter [15:0] TXPHDLY_CFG0 = 16'h2020;
- parameter [15:0] TXPHDLY_CFG1 = 16'h0001;
+ parameter [15:0] TXPHDLY_CFG0 = 16'h6020;
+ parameter [15:0] TXPHDLY_CFG1 = 16'h0002;
parameter [15:0] TXPH_CFG = 16'h0123;
parameter [15:0] TXPH_CFG2 = 16'h0000;
parameter [4:0] TXPH_MONITOR_SEL = 5'b00000;
+ parameter [15:0] TXPI_CFG = 16'h0000;
parameter [1:0] TXPI_CFG0 = 2'b00;
parameter [1:0] TXPI_CFG1 = 2'b00;
parameter [1:0] TXPI_CFG2 = 2'b00;
@@ -16555,30 +16586,29 @@ module GTYE3_CHANNEL (...);
parameter [0:0] TXPI_GRAY_SEL = 1'b0;
parameter [0:0] TXPI_INVSTROBE_SEL = 1'b0;
parameter [0:0] TXPI_LPM = 1'b0;
+ parameter [0:0] TXPI_PPM = 1'b0;
parameter TXPI_PPMCLK_SEL = "TXUSRCLK2";
parameter [7:0] TXPI_PPM_CFG = 8'b00000000;
- parameter [15:0] TXPI_RSV0 = 16'h0000;
parameter [2:0] TXPI_SYNFREQ_PPM = 3'b000;
parameter [0:0] TXPI_VREFSEL = 1'b0;
parameter [4:0] TXPMARESET_TIME = 5'b00001;
+ parameter [0:0] TXREFCLKDIV2_SEL = 1'b0;
parameter [0:0] TXSYNC_MULTILANE = 1'b0;
parameter [0:0] TXSYNC_OVRD = 1'b0;
parameter [0:0] TXSYNC_SKIP_DA = 1'b0;
parameter integer TX_CLK25_DIV = 8;
parameter [0:0] TX_CLKMUX_EN = 1'b1;
- parameter [0:0] TX_CLKREG_PDB = 1'b0;
- parameter [2:0] TX_CLKREG_SET = 3'b000;
parameter integer TX_DATA_WIDTH = 20;
- parameter [5:0] TX_DCD_CFG = 6'b000010;
- parameter [0:0] TX_DCD_EN = 1'b0;
+ parameter [15:0] TX_DCC_LOOP_RST_CFG = 16'h0000;
parameter [5:0] TX_DEEMPH0 = 6'b000000;
parameter [5:0] TX_DEEMPH1 = 6'b000000;
+ parameter [5:0] TX_DEEMPH2 = 6'b000000;
+ parameter [5:0] TX_DEEMPH3 = 6'b000000;
parameter [4:0] TX_DIVRESET_TIME = 5'b00001;
parameter TX_DRIVE_MODE = "DIRECT";
parameter integer TX_DRVMUX_CTRL = 2;
parameter [2:0] TX_EIDLE_ASSERT_DELAY = 3'b110;
parameter [2:0] TX_EIDLE_DEASSERT_DELAY = 3'b100;
- parameter [0:0] TX_EML_PHI_TUNE = 1'b0;
parameter [0:0] TX_FABINT_USRCLK_FLOP = 1'b0;
parameter [0:0] TX_FIFO_BYP_EN = 1'b0;
parameter [0:0] TX_IDLE_DATA_ZERO = 1'b0;
@@ -16595,44 +16625,75 @@ module GTYE3_CHANNEL (...);
parameter [6:0] TX_MARGIN_LOW_2 = 7'b1000010;
parameter [6:0] TX_MARGIN_LOW_3 = 7'b1000000;
parameter [6:0] TX_MARGIN_LOW_4 = 7'b1000000;
- parameter [2:0] TX_MODE_SEL = 3'b000;
parameter [15:0] TX_PHICAL_CFG0 = 16'h0000;
- parameter [15:0] TX_PHICAL_CFG1 = 16'h7E00;
+ parameter [15:0] TX_PHICAL_CFG1 = 16'h003F;
parameter [15:0] TX_PHICAL_CFG2 = 16'h0000;
parameter integer TX_PI_BIASSET = 0;
- parameter [15:0] TX_PI_CFG0 = 16'h0000;
- parameter [15:0] TX_PI_CFG1 = 16'h0000;
- parameter [0:0] TX_PI_DIV2_MODE_B = 1'b0;
- parameter [0:0] TX_PI_SEL_QPLL0 = 1'b0;
- parameter [0:0] TX_PI_SEL_QPLL1 = 1'b0;
+ parameter [1:0] TX_PI_IBIAS_MID = 2'b00;
parameter [0:0] TX_PMADATA_OPT = 1'b0;
parameter [0:0] TX_PMA_POWER_SAVE = 1'b0;
+ parameter [15:0] TX_PMA_RSV0 = 16'h0008;
parameter integer TX_PREDRV_CTRL = 2;
parameter TX_PROGCLK_SEL = "POSTPI";
parameter real TX_PROGDIV_CFG = 0.0;
parameter [15:0] TX_PROGDIV_RATE = 16'h0001;
+ parameter [0:0] TX_QPI_STATUS_EN = 1'b0;
parameter [13:0] TX_RXDETECT_CFG = 14'h0032;
- parameter integer TX_RXDETECT_REF = 4;
+ parameter integer TX_RXDETECT_REF = 3;
parameter [2:0] TX_SAMPLE_PERIOD = 3'b101;
parameter [0:0] TX_SARC_LPBK_ENB = 1'b0;
+ parameter [1:0] TX_SW_MEAS = 2'b00;
+ parameter [2:0] TX_VREG_CTRL = 3'b000;
+ parameter [0:0] TX_VREG_PDB = 1'b0;
+ parameter [1:0] TX_VREG_VREFSEL = 2'b00;
parameter TX_XCLK_SEL = "TXOUT";
+ parameter [0:0] USB_BOTH_BURST_IDLE = 1'b0;
+ parameter [6:0] USB_BURSTMAX_U3WAKE = 7'b1111111;
+ parameter [6:0] USB_BURSTMIN_U3WAKE = 7'b1100011;
+ parameter [0:0] USB_CLK_COR_EQ_EN = 1'b0;
+ parameter [0:0] USB_EXT_CNTL = 1'b1;
+ parameter [9:0] USB_IDLEMAX_POLLING = 10'b1010111011;
+ parameter [9:0] USB_IDLEMIN_POLLING = 10'b0100101011;
+ parameter [8:0] USB_LFPSPING_BURST = 9'b000000101;
+ parameter [8:0] USB_LFPSPOLLING_BURST = 9'b000110001;
+ parameter [8:0] USB_LFPSPOLLING_IDLE_MS = 9'b000000100;
+ parameter [8:0] USB_LFPSU1EXIT_BURST = 9'b000011101;
+ parameter [8:0] USB_LFPSU2LPEXIT_BURST_MS = 9'b001100011;
+ parameter [8:0] USB_LFPSU3WAKE_BURST_MS = 9'b111110011;
+ parameter [3:0] USB_LFPS_TPERIOD = 4'b0011;
+ parameter [0:0] USB_LFPS_TPERIOD_ACCURATE = 1'b1;
+ parameter [0:0] USB_MODE = 1'b0;
+ parameter [0:0] USB_PCIE_ERR_REP_DIS = 1'b0;
+ parameter integer USB_PING_SATA_MAX_INIT = 21;
+ parameter integer USB_PING_SATA_MIN_INIT = 12;
+ parameter integer USB_POLL_SATA_MAX_BURST = 8;
+ parameter integer USB_POLL_SATA_MIN_BURST = 4;
+ parameter [0:0] USB_RAW_ELEC = 1'b0;
+ parameter [0:0] USB_RXIDLE_P0_CTRL = 1'b1;
+ parameter [0:0] USB_TXIDLE_TUNE_ENABLE = 1'b1;
+ parameter integer USB_U1_SATA_MAX_WAKE = 7;
+ parameter integer USB_U1_SATA_MIN_WAKE = 4;
+ parameter integer USB_U2_SAS_MAX_COM = 64;
+ parameter integer USB_U2_SAS_MIN_COM = 36;
parameter [0:0] USE_PCS_CLK_PHASE_SEL = 1'b0;
- output [2:0] BUFGTCE;
+ parameter [0:0] Y_ALL_MODE = 1'b0;
+ output BUFGTCE;
output [2:0] BUFGTCEMASK;
output [8:0] BUFGTDIV;
- output [2:0] BUFGTRESET;
+ output BUFGTRESET;
output [2:0] BUFGTRSTMASK;
output CPLLFBCLKLOST;
output CPLLLOCK;
output CPLLREFCLKLOST;
- output [16:0] DMONITOROUT;
+ output [15:0] DMONITOROUT;
+ output DMONITOROUTCLK;
output [15:0] DRPDO;
output DRPRDY;
output EYESCANDATAERROR;
+ output GTHTXN;
+ output GTHTXP;
output GTPOWERGOOD;
output GTREFCLKMONITOR;
- output GTYTXN;
- output GTYTXP;
output PCIERATEGEN3;
output PCIERATEIDLE;
output [1:0] PCIERATEQPLLPD;
@@ -16643,7 +16704,8 @@ module GTYE3_CHANNEL (...);
output PCIEUSERRATESTART;
output [15:0] PCSRSVDOUT;
output PHYSTATUS;
- output [7:0] PINRSRVDAS;
+ output [15:0] PINRSRVDAS;
+ output POWERPRESENT;
output RESETEXCEPTION;
output [2:0] RXBUFSTATUS;
output RXBYTEISALIGNED;
@@ -16671,7 +16733,10 @@ module GTYE3_CHANNEL (...);
output RXELECIDLE;
output [5:0] RXHEADER;
output [1:0] RXHEADERVALID;
- output [6:0] RXMONITOROUT;
+ output RXLFPSTRESETDET;
+ output RXLFPSU2LPEXITDET;
+ output RXLFPSU3WAKEDET;
+ output [7:0] RXMONITOROUT;
output RXOSINTDONE;
output RXOSINTSTARTED;
output RXOSINTSTROBEDONE;
@@ -16685,6 +16750,8 @@ module GTYE3_CHANNEL (...);
output RXPRBSERR;
output RXPRBSLOCKED;
output RXPRGDIVRESETDONE;
+ output RXQPISENN;
+ output RXQPISENP;
output RXRATEDONE;
output RXRECCLKOUT;
output RXRESETDONE;
@@ -16708,6 +16775,8 @@ module GTYE3_CHANNEL (...);
output TXPHINITDONE;
output TXPMARESETDONE;
output TXPRGDIVRESETDONE;
+ output TXQPISENN;
+ output TXQPISENP;
output TXRATEDONE;
output TXRESETDONE;
output TXSYNCDONE;
@@ -16718,6 +16787,7 @@ module GTYE3_CHANNEL (...);
input CFGRESET;
input CLKRSVD0;
input CLKRSVD1;
+ input CPLLFREQLOCK;
input CPLLLOCKDETCLK;
input CPLLLOCKEN;
input CPLLPD;
@@ -16729,65 +16799,64 @@ module GTYE3_CHANNEL (...);
input DRPCLK;
input [15:0] DRPDI;
input DRPEN;
+ input DRPRST;
input DRPWE;
- input ELPCALDVORWREN;
- input ELPCALPAORWREN;
- input EVODDPHICALDONE;
- input EVODDPHICALSTART;
- input EVODDPHIDRDEN;
- input EVODDPHIDWREN;
- input EVODDPHIXRDEN;
- input EVODDPHIXWREN;
- input EYESCANMODE;
input EYESCANRESET;
input EYESCANTRIGGER;
+ input FREQOS;
input GTGREFCLK;
+ input GTHRXN;
+ input GTHRXP;
input GTNORTHREFCLK0;
input GTNORTHREFCLK1;
input GTREFCLK0;
input GTREFCLK1;
- input GTRESETSEL;
input [15:0] GTRSVD;
input GTRXRESET;
+ input GTRXRESETSEL;
input GTSOUTHREFCLK0;
input GTSOUTHREFCLK1;
input GTTXRESET;
- input GTYRXN;
- input GTYRXP;
+ input GTTXRESETSEL;
+ input INCPCTRL;
input [2:0] LOOPBACK;
- input [15:0] LOOPRSVD;
- input LPBKRXTXSEREN;
- input LPBKTXRXSEREN;
input PCIEEQRXEQADAPTDONE;
input PCIERSTIDLE;
input PCIERSTTXSYNCSTART;
input PCIEUSERRATEDONE;
input [15:0] PCSRSVDIN;
- input [4:0] PCSRSVDIN2;
- input [4:0] PMARSVDIN;
input QPLL0CLK;
+ input QPLL0FREQLOCK;
input QPLL0REFCLK;
input QPLL1CLK;
+ input QPLL1FREQLOCK;
input QPLL1REFCLK;
input RESETOVRD;
- input RSTCLKENTX;
input RX8B10BEN;
+ input RXAFECFOKEN;
input RXBUFRESET;
input RXCDRFREQRESET;
input RXCDRHOLD;
input RXCDROVRDEN;
input RXCDRRESET;
- input RXCDRRESETRSV;
input RXCHBONDEN;
input [4:0] RXCHBONDI;
input [2:0] RXCHBONDLEVEL;
input RXCHBONDMASTER;
input RXCHBONDSLAVE;
input RXCKCALRESET;
+ input [6:0] RXCKCALSTART;
input RXCOMMADETEN;
- input RXDCCFORCESTART;
+ input [1:0] RXDFEAGCCTRL;
input RXDFEAGCHOLD;
input RXDFEAGCOVRDEN;
+ input [3:0] RXDFECFOKFCNUM;
+ input RXDFECFOKFEN;
+ input RXDFECFOKFPULSE;
+ input RXDFECFOKHOLD;
+ input RXDFECFOKOVREN;
+ input RXDFEKHHOLD;
+ input RXDFEKHOVRDEN;
input RXDFELFHOLD;
input RXDFELFOVRDEN;
input RXDFELPMRESET;
@@ -16823,13 +16892,13 @@ module GTYE3_CHANNEL (...);
input RXDFEUTOVRDEN;
input RXDFEVPHOLD;
input RXDFEVPOVRDEN;
- input RXDFEVSEN;
input RXDFEXYDEN;
input RXDLYBYPASS;
input RXDLYEN;
input RXDLYOVRDEN;
input RXDLYSRESET;
input [1:0] RXELECIDLEMODE;
+ input RXEQTRAINING;
input RXGEARBOXSLIP;
input RXLATCLK;
input RXLPMEN;
@@ -16846,12 +16915,6 @@ module GTYE3_CHANNEL (...);
input RXOOBRESET;
input RXOSCALRESET;
input RXOSHOLD;
- input [3:0] RXOSINTCFG;
- input RXOSINTEN;
- input RXOSINTHOLD;
- input RXOSINTOVRDEN;
- input RXOSINTSTROBE;
- input RXOSINTTESTOVRDEN;
input RXOSOVRDEN;
input [2:0] RXOUTCLKSEL;
input RXPCOMMAALIGNEN;
@@ -16868,6 +16931,7 @@ module GTYE3_CHANNEL (...);
input RXPRBSCNTRESET;
input [3:0] RXPRBSSEL;
input RXPROGDIVRESET;
+ input RXQPIEN;
input [2:0] RXRATE;
input RXRATEMODE;
input RXSLIDE;
@@ -16877,6 +16941,7 @@ module GTYE3_CHANNEL (...);
input RXSYNCIN;
input RXSYNCMODE;
input [1:0] RXSYSCLKSEL;
+ input RXTERMINATION;
input RXUSERRDY;
input RXUSRCLK;
input RXUSRCLK2;
@@ -16884,7 +16949,6 @@ module GTYE3_CHANNEL (...);
input [19:0] TSTIN;
input [7:0] TX8B10BBYPASS;
input TX8B10BEN;
- input [2:0] TXBUFDIFFCTRL;
input TXCOMINIT;
input TXCOMSAS;
input TXCOMWAKE;
@@ -16895,10 +16959,9 @@ module GTYE3_CHANNEL (...);
input [7:0] TXDATAEXTENDRSVD;
input TXDCCFORCESTART;
input TXDCCRESET;
- input TXDEEMPH;
+ input [1:0] TXDEEMPH;
input TXDETECTRX;
input [4:0] TXDIFFCTRL;
- input TXDIFFPD;
input TXDLYBYPASS;
input TXDLYEN;
input TXDLYHOLD;
@@ -16906,12 +16969,17 @@ module GTYE3_CHANNEL (...);
input TXDLYSRESET;
input TXDLYUPDOWN;
input TXELECIDLE;
- input TXELFORCESTART;
input [5:0] TXHEADER;
input TXINHIBIT;
input TXLATCLK;
+ input TXLFPSTRESET;
+ input TXLFPSU2LPEXIT;
+ input TXLFPSU3WAKE;
input [6:0] TXMAINCURSOR;
input [2:0] TXMARGIN;
+ input TXMUXDCDEXHOLD;
+ input TXMUXDCDORWREN;
+ input TXONESZEROS;
input [2:0] TXOUTCLKSEL;
input TXPCSRESET;
input [1:0] TXPD;
@@ -16937,6 +17005,8 @@ module GTYE3_CHANNEL (...);
input [3:0] TXPRBSSEL;
input [4:0] TXPRECURSOR;
input TXPROGDIVRESET;
+ input TXQPIBIASEN;
+ input TXQPIWEAKPUP;
input [2:0] TXRATE;
input TXRATEMODE;
input [6:0] TXSEQUENCE;
@@ -16950,28 +17020,34 @@ module GTYE3_CHANNEL (...);
input TXUSRCLK2;
endmodule
-module GTYE3_COMMON (...);
- parameter [15:0] A_SDM1DATA1_0 = 16'b0000000000000000;
- parameter [8:0] A_SDM1DATA1_1 = 9'b000000000;
+module GTHE4_COMMON (...);
+ parameter [0:0] AEN_QPLL0_FBDIV = 1'b1;
+ parameter [0:0] AEN_QPLL1_FBDIV = 1'b1;
+ parameter [0:0] AEN_SDM0TOGGLE = 1'b0;
+ parameter [0:0] AEN_SDM1TOGGLE = 1'b0;
+ parameter [0:0] A_SDM0TOGGLE = 1'b0;
+ parameter [8:0] A_SDM1DATA_HIGH = 9'b000000000;
+ parameter [15:0] A_SDM1DATA_LOW = 16'b0000000000000000;
+ parameter [0:0] A_SDM1TOGGLE = 1'b0;
parameter [15:0] BIAS_CFG0 = 16'h0000;
parameter [15:0] BIAS_CFG1 = 16'h0000;
parameter [15:0] BIAS_CFG2 = 16'h0000;
parameter [15:0] BIAS_CFG3 = 16'h0000;
parameter [15:0] BIAS_CFG4 = 16'h0000;
- parameter [9:0] BIAS_CFG_RSVD = 10'b0000000000;
+ parameter [15:0] BIAS_CFG_RSVD = 16'h0000;
parameter [15:0] COMMON_CFG0 = 16'h0000;
parameter [15:0] COMMON_CFG1 = 16'h0000;
- parameter [15:0] POR_CFG = 16'h0004;
- parameter [15:0] PPF0_CFG = 16'h0FFF;
- parameter [15:0] PPF1_CFG = 16'h0FFF;
+ parameter [15:0] POR_CFG = 16'h0000;
+ parameter [15:0] PPF0_CFG = 16'h0F00;
+ parameter [15:0] PPF1_CFG = 16'h0F00;
parameter QPLL0CLKOUT_RATE = "FULL";
- parameter [15:0] QPLL0_CFG0 = 16'h301C;
+ parameter [15:0] QPLL0_CFG0 = 16'h391C;
parameter [15:0] QPLL0_CFG1 = 16'h0000;
parameter [15:0] QPLL0_CFG1_G3 = 16'h0020;
- parameter [15:0] QPLL0_CFG2 = 16'h0780;
- parameter [15:0] QPLL0_CFG2_G3 = 16'h0780;
+ parameter [15:0] QPLL0_CFG2 = 16'h0F80;
+ parameter [15:0] QPLL0_CFG2_G3 = 16'h0F80;
parameter [15:0] QPLL0_CFG3 = 16'h0120;
- parameter [15:0] QPLL0_CFG4 = 16'h0021;
+ parameter [15:0] QPLL0_CFG4 = 16'h0002;
parameter [9:0] QPLL0_CP = 10'b0000011111;
parameter [9:0] QPLL0_CP_G3 = 10'b0000011111;
parameter integer QPLL0_FBDIV = 66;
@@ -16980,20 +17056,22 @@ module GTYE3_COMMON (...);
parameter [7:0] QPLL0_INIT_CFG1 = 8'h00;
parameter [15:0] QPLL0_LOCK_CFG = 16'h01E8;
parameter [15:0] QPLL0_LOCK_CFG_G3 = 16'h21E8;
- parameter [9:0] QPLL0_LPF = 10'b1111111111;
+ parameter [9:0] QPLL0_LPF = 10'b1011111111;
parameter [9:0] QPLL0_LPF_G3 = 10'b1111111111;
- parameter integer QPLL0_REFCLK_DIV = 2;
+ parameter [0:0] QPLL0_PCI_EN = 1'b0;
+ parameter [0:0] QPLL0_RATE_SW_USE_DRP = 1'b0;
+ parameter integer QPLL0_REFCLK_DIV = 1;
parameter [15:0] QPLL0_SDM_CFG0 = 16'h0040;
parameter [15:0] QPLL0_SDM_CFG1 = 16'h0000;
parameter [15:0] QPLL0_SDM_CFG2 = 16'h0000;
parameter QPLL1CLKOUT_RATE = "FULL";
- parameter [15:0] QPLL1_CFG0 = 16'h301C;
- parameter [15:0] QPLL1_CFG1 = 16'h0000;
+ parameter [15:0] QPLL1_CFG0 = 16'h691C;
+ parameter [15:0] QPLL1_CFG1 = 16'h0020;
parameter [15:0] QPLL1_CFG1_G3 = 16'h0020;
- parameter [15:0] QPLL1_CFG2 = 16'h0780;
- parameter [15:0] QPLL1_CFG2_G3 = 16'h0780;
+ parameter [15:0] QPLL1_CFG2 = 16'h0F80;
+ parameter [15:0] QPLL1_CFG2_G3 = 16'h0F80;
parameter [15:0] QPLL1_CFG3 = 16'h0120;
- parameter [15:0] QPLL1_CFG4 = 16'h0021;
+ parameter [15:0] QPLL1_CFG4 = 16'h0002;
parameter [9:0] QPLL1_CP = 10'b0000011111;
parameter [9:0] QPLL1_CP_G3 = 10'b0000011111;
parameter integer QPLL1_FBDIV = 66;
@@ -17002,10 +17080,12 @@ module GTYE3_COMMON (...);
parameter [7:0] QPLL1_INIT_CFG1 = 8'h00;
parameter [15:0] QPLL1_LOCK_CFG = 16'h01E8;
parameter [15:0] QPLL1_LOCK_CFG_G3 = 16'h21E8;
- parameter [9:0] QPLL1_LPF = 10'b1111111111;
+ parameter [9:0] QPLL1_LPF = 10'b1011111111;
parameter [9:0] QPLL1_LPF_G3 = 10'b1111111111;
- parameter integer QPLL1_REFCLK_DIV = 2;
- parameter [15:0] QPLL1_SDM_CFG0 = 16'h0040;
+ parameter [0:0] QPLL1_PCI_EN = 1'b0;
+ parameter [0:0] QPLL1_RATE_SW_USE_DRP = 1'b0;
+ parameter integer QPLL1_REFCLK_DIV = 1;
+ parameter [15:0] QPLL1_SDM_CFG0 = 16'h0000;
parameter [15:0] QPLL1_SDM_CFG1 = 16'h0000;
parameter [15:0] QPLL1_SDM_CFG2 = 16'h0000;
parameter [15:0] RSVD_ATTR0 = 16'h0000;
@@ -17014,15 +17094,15 @@ module GTYE3_COMMON (...);
parameter [15:0] RSVD_ATTR3 = 16'h0000;
parameter [1:0] RXRECCLKOUT0_SEL = 2'b00;
parameter [1:0] RXRECCLKOUT1_SEL = 2'b00;
- parameter [0:0] SARC_EN = 1'b1;
+ parameter [0:0] SARC_ENB = 1'b0;
parameter [0:0] SARC_SEL = 1'b0;
parameter [15:0] SDM0INITSEED0_0 = 16'b0000000000000000;
parameter [8:0] SDM0INITSEED0_1 = 9'b000000000;
parameter [15:0] SDM1INITSEED0_0 = 16'b0000000000000000;
parameter [8:0] SDM1INITSEED0_1 = 9'b000000000;
+ parameter SIM_DEVICE = "ULTRASCALE_PLUS";
parameter SIM_MODE = "FAST";
parameter SIM_RESET_SPEEDUP = "TRUE";
- parameter integer SIM_VERSION = 2;
output [15:0] DRPDO;
output DRPRDY;
output [7:0] PMARSVDOUT0;
@@ -17041,18 +17121,20 @@ module GTYE3_COMMON (...);
output [7:0] QPLLDMONITOR1;
output REFCLKOUTMONITOR0;
output REFCLKOUTMONITOR1;
- output [1:0] RXRECCLK0_SEL;
- output [1:0] RXRECCLK1_SEL;
+ output [1:0] RXRECCLK0SEL;
+ output [1:0] RXRECCLK1SEL;
output [3:0] SDM0FINALOUT;
output [14:0] SDM0TESTDATA;
output [3:0] SDM1FINALOUT;
output [14:0] SDM1TESTDATA;
+ output [9:0] TCONGPO;
+ output TCONRSVDOUT0;
input BGBYPASSB;
input BGMONITORENB;
input BGPDB;
input [4:0] BGRCALOVRD;
input BGRCALOVRDENB;
- input [9:0] DRPADDR;
+ input [15:0] DRPADDR;
input DRPCLK;
input [15:0] DRPDI;
input DRPEN;
@@ -17071,15 +17153,21 @@ module GTYE3_COMMON (...);
input GTSOUTHREFCLK01;
input GTSOUTHREFCLK10;
input GTSOUTHREFCLK11;
+ input [2:0] PCIERATEQPLL0;
+ input [2:0] PCIERATEQPLL1;
input [7:0] PMARSVD0;
input [7:0] PMARSVD1;
input QPLL0CLKRSVD0;
+ input QPLL0CLKRSVD1;
+ input [7:0] QPLL0FBDIV;
input QPLL0LOCKDETCLK;
input QPLL0LOCKEN;
input QPLL0PD;
input [2:0] QPLL0REFCLKSEL;
input QPLL0RESET;
input QPLL1CLKRSVD0;
+ input QPLL1CLKRSVD1;
+ input [7:0] QPLL1FBDIV;
input QPLL1LOCKDETCLK;
input QPLL1LOCKEN;
input QPLL1PD;
@@ -17092,10 +17180,16 @@ module GTYE3_COMMON (...);
input RCALENB;
input [24:0] SDM0DATA;
input SDM0RESET;
+ input SDM0TOGGLE;
input [1:0] SDM0WIDTH;
input [24:0] SDM1DATA;
input SDM1RESET;
+ input SDM1TOGGLE;
input [1:0] SDM1WIDTH;
+ input [9:0] TCONGPI;
+ input TCONPOWERUP;
+ input [1:0] TCONRESET;
+ input [1:0] TCONRSVDIN1;
endmodule
module GTYE4_CHANNEL (...);
@@ -17357,7 +17451,7 @@ module GTYE4_CHANNEL (...);
parameter [15:0] RXDFE_KH_CFG0 = 16'h0000;
parameter [15:0] RXDFE_KH_CFG1 = 16'h0000;
parameter [15:0] RXDFE_KH_CFG2 = 16'h0000;
- parameter [15:0] RXDFE_KH_CFG3 = 16'h0000;
+ parameter [15:0] RXDFE_KH_CFG3 = 16'h2000;
parameter [15:0] RXDFE_OS_CFG0 = 16'h0000;
parameter [15:0] RXDFE_OS_CFG1 = 16'h0000;
parameter [15:0] RXDFE_UT_CFG0 = 16'h0000;
@@ -17408,7 +17502,7 @@ module GTYE4_CHANNEL (...);
parameter [4:0] RX_CLK_SLIP_OVRD = 5'b00000;
parameter [3:0] RX_CM_BUF_CFG = 4'b1010;
parameter [0:0] RX_CM_BUF_PD = 1'b0;
- parameter integer RX_CM_SEL = 3;
+ parameter integer RX_CM_SEL = 2;
parameter integer RX_CM_TRIM = 12;
parameter [0:0] RX_CTLE_PWR_SAVING = 1'b0;
parameter [3:0] RX_CTLE_RES_CTRL = 4'b0000;
@@ -17416,12 +17510,12 @@ module GTYE4_CHANNEL (...);
parameter [5:0] RX_DDI_SEL = 6'b000000;
parameter RX_DEFER_RESET_BUF_EN = "TRUE";
parameter [2:0] RX_DEGEN_CTRL = 3'b100;
- parameter integer RX_DFELPM_CFG0 = 0;
+ parameter integer RX_DFELPM_CFG0 = 10;
parameter [0:0] RX_DFELPM_CFG1 = 1'b1;
parameter [0:0] RX_DFELPM_KLKH_AGC_STUP_EN = 1'b1;
parameter integer RX_DFE_AGC_CFG1 = 4;
parameter integer RX_DFE_KL_LPM_KH_CFG0 = 1;
- parameter integer RX_DFE_KL_LPM_KH_CFG1 = 4;
+ parameter integer RX_DFE_KL_LPM_KH_CFG1 = 2;
parameter [1:0] RX_DFE_KL_LPM_KL_CFG0 = 2'b01;
parameter integer RX_DFE_KL_LPM_KL_CFG1 = 4;
parameter [0:0] RX_DFE_LPM_HOLD_DURING_EIDLE = 1'b0;
@@ -17437,7 +17531,7 @@ module GTYE4_CHANNEL (...);
parameter [0:0] RX_I2V_FILTER_EN = 1'b1;
parameter integer RX_INT_DATAWIDTH = 1;
parameter [0:0] RX_PMA_POWER_SAVE = 1'b0;
- parameter [15:0] RX_PMA_RSV0 = 16'h000F;
+ parameter [15:0] RX_PMA_RSV0 = 16'h002F;
parameter real RX_PROGDIV_CFG = 0.0;
parameter [15:0] RX_PROGDIV_RATE = 16'h0001;
parameter [3:0] RX_RESLOAD_CTRL = 4'b0000;
@@ -17468,11 +17562,11 @@ module GTYE4_CHANNEL (...);
parameter SATA_CPLL_CFG = "VCO_3000MHZ";
parameter [2:0] SATA_EIDLE_VAL = 3'b100;
parameter SHOW_REALIGN_COMMA = "TRUE";
+ parameter SIM_DEVICE = "ULTRASCALE_PLUS";
parameter SIM_MODE = "FAST";
parameter SIM_RECEIVER_DETECT_PASS = "TRUE";
parameter SIM_RESET_SPEEDUP = "TRUE";
parameter SIM_TX_EIDLE_DRIVE_LEVEL = "Z";
- parameter SIM_DEVICE = "ULTRASCALE_PLUS";
parameter [0:0] SRSTMODE = 1'b0;
parameter [1:0] TAPDLY_SET_TX = 2'h0;
parameter [14:0] TERM_RCAL_CFG = 15'b100001000010000;
@@ -18004,9 +18098,9 @@ module GTYE4_COMMON (...);
parameter [8:0] SDM0INITSEED0_1 = 9'b000000000;
parameter [15:0] SDM1INITSEED0_0 = 16'b0000000000000000;
parameter [8:0] SDM1INITSEED0_1 = 9'b000000000;
+ parameter SIM_DEVICE = "ULTRASCALE_PLUS";
parameter SIM_MODE = "FAST";
parameter SIM_RESET_SPEEDUP = "TRUE";
- parameter SIM_DEVICE = "ULTRASCALE_PLUS";
parameter [15:0] UB_CFG0 = 16'h0000;
parameter [15:0] UB_CFG1 = 16'h0000;
parameter [15:0] UB_CFG2 = 16'h0000;
@@ -18120,19 +18214,6 @@ module GTYE4_COMMON (...);
input UBMDMTDI;
endmodule
-module IBUFDS_GTE3 (...);
- parameter [0:0] REFCLK_EN_TX_PATH = 1'b0;
- parameter [1:0] REFCLK_HROW_CK_SEL = 2'b00;
- parameter [1:0] REFCLK_ICNTL_RX = 2'b00;
- output O;
- output ODIV2;
- input CEB;
- (* iopad_external_pin *)
- input I;
- (* iopad_external_pin *)
- input IB;
-endmodule
-
module IBUFDS_GTE4 (...);
parameter [0:0] REFCLK_EN_TX_PATH = 1'b0;
parameter [1:0] REFCLK_HROW_CK_SEL = 2'b00;
@@ -18146,7 +18227,7 @@ module IBUFDS_GTE4 (...);
input IB;
endmodule
-module OBUFDS_GTE3 (...);
+module OBUFDS_GTE4 (...);
parameter [0:0] REFCLK_EN_TX_PATH = 1'b0;
parameter [4:0] REFCLK_ICNTL_TX = 5'b00000;
(* iopad_external_pin *)
@@ -18157,7 +18238,7 @@ module OBUFDS_GTE3 (...);
input I;
endmodule
-module OBUFDS_GTE3_ADV (...);
+module OBUFDS_GTE4_ADV (...);
parameter [0:0] REFCLK_EN_TX_PATH = 1'b0;
parameter [4:0] REFCLK_ICNTL_TX = 5'b00000;
(* iopad_external_pin *)
@@ -18169,9 +18250,669 @@ module OBUFDS_GTE3_ADV (...);
input [1:0] RXRECCLK_SEL;
endmodule
-module OBUFDS_GTE4 (...);
+module GTM_DUAL (...);
+ parameter [15:0] A_CFG = 16'b0000100001000000;
+ parameter [15:0] A_SDM_DATA_CFG0 = 16'b0000000011010000;
+ parameter [15:0] A_SDM_DATA_CFG1 = 16'b0000000011010000;
+ parameter [15:0] BIAS_CFG0 = 16'b0000000000000000;
+ parameter [15:0] BIAS_CFG1 = 16'b0000000000000000;
+ parameter [15:0] BIAS_CFG2 = 16'b0001000000000000;
+ parameter [15:0] BIAS_CFG3 = 16'b0000000000000001;
+ parameter [15:0] BIAS_CFG4 = 16'b0000000000000000;
+ parameter [15:0] BIAS_CFG5 = 16'b0000000000000000;
+ parameter [15:0] BIAS_CFG6 = 16'b0000000010000000;
+ parameter [15:0] BIAS_CFG7 = 16'b0000000000000000;
+ parameter [15:0] CH0_A_CH_CFG0 = 16'b0000000000000011;
+ parameter [15:0] CH0_A_CH_CFG1 = 16'b0000000000000000;
+ parameter [15:0] CH0_A_CH_CFG2 = 16'b0111101111110000;
+ parameter [15:0] CH0_A_CH_CFG3 = 16'b0000000000000000;
+ parameter [15:0] CH0_A_CH_CFG4 = 16'b0000000000000000;
+ parameter [15:0] CH0_A_CH_CFG5 = 16'b0000000000000000;
+ parameter [15:0] CH0_A_CH_CFG6 = 16'b0000000000000000;
+ parameter [15:0] CH0_RST_LP_CFG0 = 16'b0001000000010000;
+ parameter [15:0] CH0_RST_LP_CFG1 = 16'b0011001000010000;
+ parameter [15:0] CH0_RST_LP_CFG2 = 16'b0110010100000100;
+ parameter [15:0] CH0_RST_LP_CFG3 = 16'b0011001000010000;
+ parameter [15:0] CH0_RST_LP_CFG4 = 16'b0000000001000100;
+ parameter [15:0] CH0_RST_LP_ID_CFG0 = 16'b0011000001110000;
+ parameter [15:0] CH0_RST_LP_ID_CFG1 = 16'b0001000000010000;
+ parameter [15:0] CH0_RST_TIME_CFG0 = 16'b0000010000100001;
+ parameter [15:0] CH0_RST_TIME_CFG1 = 16'b0000010000100001;
+ parameter [15:0] CH0_RST_TIME_CFG2 = 16'b0000010000100001;
+ parameter [15:0] CH0_RST_TIME_CFG3 = 16'b0000010000100000;
+ parameter [15:0] CH0_RST_TIME_CFG4 = 16'b0000010000100001;
+ parameter [15:0] CH0_RST_TIME_CFG5 = 16'b0000000000000001;
+ parameter [15:0] CH0_RST_TIME_CFG6 = 16'b0000000000100001;
+ parameter [15:0] CH0_RX_ADC_CFG0 = 16'b0011010010001111;
+ parameter [15:0] CH0_RX_ADC_CFG1 = 16'b0011111001010101;
+ parameter [15:0] CH0_RX_ANA_CFG0 = 16'b1000000000011101;
+ parameter [15:0] CH0_RX_ANA_CFG1 = 16'b1110100010000000;
+ parameter [15:0] CH0_RX_ANA_CFG2 = 16'b0000000010001010;
+ parameter [15:0] CH0_RX_APT_CFG0A = 16'b0000000001110000;
+ parameter [15:0] CH0_RX_APT_CFG0B = 16'b0000000001110000;
+ parameter [15:0] CH0_RX_APT_CFG10A = 16'b0000000001110000;
+ parameter [15:0] CH0_RX_APT_CFG10B = 16'b0000000001010000;
+ parameter [15:0] CH0_RX_APT_CFG11A = 16'b0000000001000000;
+ parameter [15:0] CH0_RX_APT_CFG11B = 16'b0000000001110000;
+ parameter [15:0] CH0_RX_APT_CFG12A = 16'b0000000001010000;
+ parameter [15:0] CH0_RX_APT_CFG12B = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_APT_CFG13A = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_APT_CFG13B = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_APT_CFG14A = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_APT_CFG14B = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_APT_CFG15A = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_APT_CFG15B = 16'b0000100000000000;
+ parameter [15:0] CH0_RX_APT_CFG16A = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_APT_CFG16B = 16'b0010000000000000;
+ parameter [15:0] CH0_RX_APT_CFG17A = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_APT_CFG17B = 16'b0001000001000000;
+ parameter [15:0] CH0_RX_APT_CFG18A = 16'b0000100000100000;
+ parameter [15:0] CH0_RX_APT_CFG18B = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_APT_CFG19A = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_APT_CFG19B = 16'b0000100000000000;
+ parameter [15:0] CH0_RX_APT_CFG1A = 16'b0000000001110000;
+ parameter [15:0] CH0_RX_APT_CFG1B = 16'b0000000001110000;
+ parameter [15:0] CH0_RX_APT_CFG20A = 16'b1110000000100000;
+ parameter [15:0] CH0_RX_APT_CFG20B = 16'b0000000001000000;
+ parameter [15:0] CH0_RX_APT_CFG21A = 16'b0001000000000100;
+ parameter [15:0] CH0_RX_APT_CFG21B = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_APT_CFG22A = 16'b0000000001110000;
+ parameter [15:0] CH0_RX_APT_CFG22B = 16'b0000000001110000;
+ parameter [15:0] CH0_RX_APT_CFG23A = 16'b0000100000000000;
+ parameter [15:0] CH0_RX_APT_CFG23B = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_APT_CFG24A = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_APT_CFG24B = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_APT_CFG25A = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_APT_CFG25B = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_APT_CFG26A = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_APT_CFG26B = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_APT_CFG27A = 16'b0100000000000000;
+ parameter [15:0] CH0_RX_APT_CFG27B = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_APT_CFG28A = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_APT_CFG28B = 16'b1000000000000000;
+ parameter [15:0] CH0_RX_APT_CFG2A = 16'b0000000001110000;
+ parameter [15:0] CH0_RX_APT_CFG2B = 16'b0000000001110000;
+ parameter [15:0] CH0_RX_APT_CFG3A = 16'b0000000001110000;
+ parameter [15:0] CH0_RX_APT_CFG3B = 16'b0000000001110000;
+ parameter [15:0] CH0_RX_APT_CFG4A = 16'b0000000001110000;
+ parameter [15:0] CH0_RX_APT_CFG4B = 16'b0000000001110000;
+ parameter [15:0] CH0_RX_APT_CFG5A = 16'b0000000001110000;
+ parameter [15:0] CH0_RX_APT_CFG5B = 16'b0000000001110000;
+ parameter [15:0] CH0_RX_APT_CFG6A = 16'b0000000001110000;
+ parameter [15:0] CH0_RX_APT_CFG6B = 16'b0000000001110000;
+ parameter [15:0] CH0_RX_APT_CFG7A = 16'b0000000001110000;
+ parameter [15:0] CH0_RX_APT_CFG7B = 16'b0000000001110000;
+ parameter [15:0] CH0_RX_APT_CFG8A = 16'b0000100000000000;
+ parameter [15:0] CH0_RX_APT_CFG8B = 16'b0000100000000000;
+ parameter [15:0] CH0_RX_APT_CFG9A = 16'b0000000001110000;
+ parameter [15:0] CH0_RX_APT_CFG9B = 16'b0000000001110000;
+ parameter [15:0] CH0_RX_APT_CTRL_CFG2 = 16'b0000000000000100;
+ parameter [15:0] CH0_RX_APT_CTRL_CFG3 = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_CAL_CFG0A = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_CAL_CFG0B = 16'b0011001100110000;
+ parameter [15:0] CH0_RX_CAL_CFG1A = 16'b1110111011100001;
+ parameter [15:0] CH0_RX_CAL_CFG1B = 16'b1111111100000100;
+ parameter [15:0] CH0_RX_CAL_CFG2A = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_CAL_CFG2B = 16'b0011000000000000;
+ parameter [15:0] CH0_RX_CDR_CFG0A = 16'b0000000000000011;
+ parameter [15:0] CH0_RX_CDR_CFG0B = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_CDR_CFG1A = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_CDR_CFG1B = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_CDR_CFG2A = 16'b1001000101100100;
+ parameter [15:0] CH0_RX_CDR_CFG2B = 16'b0000000100100100;
+ parameter [15:0] CH0_RX_CDR_CFG3A = 16'b0101110011110110;
+ parameter [15:0] CH0_RX_CDR_CFG3B = 16'b0000000000001011;
+ parameter [15:0] CH0_RX_CDR_CFG4A = 16'b0000000000000110;
+ parameter [15:0] CH0_RX_CDR_CFG4B = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_CLKGN_CFG0 = 16'b1100000000000000;
+ parameter [15:0] CH0_RX_CLKGN_CFG1 = 16'b0000000110000000;
+ parameter [15:0] CH0_RX_CTLE_CFG0 = 16'b0011010010001000;
+ parameter [15:0] CH0_RX_CTLE_CFG1 = 16'b0010000000100010;
+ parameter [15:0] CH0_RX_CTLE_CFG2 = 16'b0000101000000000;
+ parameter [15:0] CH0_RX_CTLE_CFG3 = 16'b1111001001000000;
+ parameter [15:0] CH0_RX_DSP_CFG = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_MON_CFG = 16'b0000000000000000;
+ parameter [15:0] CH0_RX_PAD_CFG0 = 16'b0001111000000000;
+ parameter [15:0] CH0_RX_PAD_CFG1 = 16'b0001100000001010;
+ parameter [15:0] CH0_RX_PCS_CFG0 = 16'b0000000100000000;
+ parameter [15:0] CH0_RX_PCS_CFG1 = 16'b0000000000000000;
+ parameter [15:0] CH0_TX_ANA_CFG0 = 16'b0000001010101111;
+ parameter [15:0] CH0_TX_ANA_CFG1 = 16'b0000000100000000;
+ parameter [15:0] CH0_TX_ANA_CFG2 = 16'b1000000000010100;
+ parameter [15:0] CH0_TX_ANA_CFG3 = 16'b0000101000100010;
+ parameter [15:0] CH0_TX_ANA_CFG4 = 16'b0000000000000000;
+ parameter [15:0] CH0_TX_CAL_CFG0 = 16'b0000000000100000;
+ parameter [15:0] CH0_TX_CAL_CFG1 = 16'b0000000001000000;
+ parameter [15:0] CH0_TX_DRV_CFG0 = 16'b0000000000000000;
+ parameter [15:0] CH0_TX_DRV_CFG1 = 16'b0000000000100111;
+ parameter [15:0] CH0_TX_DRV_CFG2 = 16'b0000000000000000;
+ parameter [15:0] CH0_TX_DRV_CFG3 = 16'b0110110000000000;
+ parameter [15:0] CH0_TX_DRV_CFG4 = 16'b0000000011000101;
+ parameter [15:0] CH0_TX_DRV_CFG5 = 16'b0000000000000000;
+ parameter [15:0] CH0_TX_LPBK_CFG0 = 16'b0000000000000011;
+ parameter [15:0] CH0_TX_LPBK_CFG1 = 16'b0000000000000000;
+ parameter [15:0] CH0_TX_PCS_CFG0 = 16'b0000000101100000;
+ parameter [15:0] CH0_TX_PCS_CFG1 = 16'b0000000000000000;
+ parameter [15:0] CH0_TX_PCS_CFG10 = 16'b0000000000000000;
+ parameter [15:0] CH0_TX_PCS_CFG11 = 16'b0000000000000000;
+ parameter [15:0] CH0_TX_PCS_CFG12 = 16'b0000000000000000;
+ parameter [15:0] CH0_TX_PCS_CFG13 = 16'b0000000000000000;
+ parameter [15:0] CH0_TX_PCS_CFG14 = 16'b0000000000000000;
+ parameter [15:0] CH0_TX_PCS_CFG15 = 16'b0000000000000000;
+ parameter [15:0] CH0_TX_PCS_CFG16 = 16'b0000000000000000;
+ parameter [15:0] CH0_TX_PCS_CFG17 = 16'b0000000000000000;
+ parameter [15:0] CH0_TX_PCS_CFG2 = 16'b0000000000000000;
+ parameter [15:0] CH0_TX_PCS_CFG3 = 16'b0000000000000000;
+ parameter [15:0] CH0_TX_PCS_CFG4 = 16'b0000000000000000;
+ parameter [15:0] CH0_TX_PCS_CFG5 = 16'b0000000000000000;
+ parameter [15:0] CH0_TX_PCS_CFG6 = 16'b0000000000000000;
+ parameter [15:0] CH0_TX_PCS_CFG7 = 16'b0000000000000000;
+ parameter [15:0] CH0_TX_PCS_CFG8 = 16'b0000000000000000;
+ parameter [15:0] CH0_TX_PCS_CFG9 = 16'b0000000000000000;
+ parameter [15:0] CH1_A_CH_CFG0 = 16'b0000000000000011;
+ parameter [15:0] CH1_A_CH_CFG1 = 16'b0000000000000000;
+ parameter [15:0] CH1_A_CH_CFG2 = 16'b0111101111110000;
+ parameter [15:0] CH1_A_CH_CFG3 = 16'b0000000000000000;
+ parameter [15:0] CH1_A_CH_CFG4 = 16'b0000000000000000;
+ parameter [15:0] CH1_A_CH_CFG5 = 16'b0000000000000000;
+ parameter [15:0] CH1_A_CH_CFG6 = 16'b0000000000000000;
+ parameter [15:0] CH1_RST_LP_CFG0 = 16'b0001000000010000;
+ parameter [15:0] CH1_RST_LP_CFG1 = 16'b0011001000010000;
+ parameter [15:0] CH1_RST_LP_CFG2 = 16'b0110010100000100;
+ parameter [15:0] CH1_RST_LP_CFG3 = 16'b0011001000010000;
+ parameter [15:0] CH1_RST_LP_CFG4 = 16'b0000000001000100;
+ parameter [15:0] CH1_RST_LP_ID_CFG0 = 16'b0011000001110000;
+ parameter [15:0] CH1_RST_LP_ID_CFG1 = 16'b0001000000010000;
+ parameter [15:0] CH1_RST_TIME_CFG0 = 16'b0000010000100001;
+ parameter [15:0] CH1_RST_TIME_CFG1 = 16'b0000010000100001;
+ parameter [15:0] CH1_RST_TIME_CFG2 = 16'b0000010000100001;
+ parameter [15:0] CH1_RST_TIME_CFG3 = 16'b0000010000100000;
+ parameter [15:0] CH1_RST_TIME_CFG4 = 16'b0000010000100001;
+ parameter [15:0] CH1_RST_TIME_CFG5 = 16'b0000000000000001;
+ parameter [15:0] CH1_RST_TIME_CFG6 = 16'b0000000000100001;
+ parameter [15:0] CH1_RX_ADC_CFG0 = 16'b0011010010001111;
+ parameter [15:0] CH1_RX_ADC_CFG1 = 16'b0011111001010101;
+ parameter [15:0] CH1_RX_ANA_CFG0 = 16'b1000000000011101;
+ parameter [15:0] CH1_RX_ANA_CFG1 = 16'b1110100010000000;
+ parameter [15:0] CH1_RX_ANA_CFG2 = 16'b0000000010001010;
+ parameter [15:0] CH1_RX_APT_CFG0A = 16'b0000000001110000;
+ parameter [15:0] CH1_RX_APT_CFG0B = 16'b0000000001110000;
+ parameter [15:0] CH1_RX_APT_CFG10A = 16'b0000000001110000;
+ parameter [15:0] CH1_RX_APT_CFG10B = 16'b0000000001010000;
+ parameter [15:0] CH1_RX_APT_CFG11A = 16'b0000000001000000;
+ parameter [15:0] CH1_RX_APT_CFG11B = 16'b0000000001110000;
+ parameter [15:0] CH1_RX_APT_CFG12A = 16'b0000000001010000;
+ parameter [15:0] CH1_RX_APT_CFG12B = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_APT_CFG13A = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_APT_CFG13B = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_APT_CFG14A = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_APT_CFG14B = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_APT_CFG15A = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_APT_CFG15B = 16'b0000100000000000;
+ parameter [15:0] CH1_RX_APT_CFG16A = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_APT_CFG16B = 16'b0010000000000000;
+ parameter [15:0] CH1_RX_APT_CFG17A = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_APT_CFG17B = 16'b0001000001000000;
+ parameter [15:0] CH1_RX_APT_CFG18A = 16'b0000100000100000;
+ parameter [15:0] CH1_RX_APT_CFG18B = 16'b0000100010000000;
+ parameter [15:0] CH1_RX_APT_CFG19A = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_APT_CFG19B = 16'b0000100000000000;
+ parameter [15:0] CH1_RX_APT_CFG1A = 16'b0000000001110000;
+ parameter [15:0] CH1_RX_APT_CFG1B = 16'b0000000001110000;
+ parameter [15:0] CH1_RX_APT_CFG20A = 16'b1110000000100000;
+ parameter [15:0] CH1_RX_APT_CFG20B = 16'b0000000001000000;
+ parameter [15:0] CH1_RX_APT_CFG21A = 16'b0001000000000100;
+ parameter [15:0] CH1_RX_APT_CFG21B = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_APT_CFG22A = 16'b0000000001110000;
+ parameter [15:0] CH1_RX_APT_CFG22B = 16'b0000000001110000;
+ parameter [15:0] CH1_RX_APT_CFG23A = 16'b0000100000000000;
+ parameter [15:0] CH1_RX_APT_CFG23B = 16'b0000100000000000;
+ parameter [15:0] CH1_RX_APT_CFG24A = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_APT_CFG24B = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_APT_CFG25A = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_APT_CFG25B = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_APT_CFG26A = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_APT_CFG26B = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_APT_CFG27A = 16'b0100000000000000;
+ parameter [15:0] CH1_RX_APT_CFG27B = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_APT_CFG28A = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_APT_CFG28B = 16'b1000000000000000;
+ parameter [15:0] CH1_RX_APT_CFG2A = 16'b0000000001110000;
+ parameter [15:0] CH1_RX_APT_CFG2B = 16'b0000000001110000;
+ parameter [15:0] CH1_RX_APT_CFG3A = 16'b0000000001110000;
+ parameter [15:0] CH1_RX_APT_CFG3B = 16'b0000000001110000;
+ parameter [15:0] CH1_RX_APT_CFG4A = 16'b0000000001110000;
+ parameter [15:0] CH1_RX_APT_CFG4B = 16'b0000000001110000;
+ parameter [15:0] CH1_RX_APT_CFG5A = 16'b0000000001110000;
+ parameter [15:0] CH1_RX_APT_CFG5B = 16'b0000000001110000;
+ parameter [15:0] CH1_RX_APT_CFG6A = 16'b0000000001110000;
+ parameter [15:0] CH1_RX_APT_CFG6B = 16'b0000000001110000;
+ parameter [15:0] CH1_RX_APT_CFG7A = 16'b0000000001110000;
+ parameter [15:0] CH1_RX_APT_CFG7B = 16'b0000000001110000;
+ parameter [15:0] CH1_RX_APT_CFG8A = 16'b0000100000000000;
+ parameter [15:0] CH1_RX_APT_CFG8B = 16'b0000100000000000;
+ parameter [15:0] CH1_RX_APT_CFG9A = 16'b0000000001110000;
+ parameter [15:0] CH1_RX_APT_CFG9B = 16'b0000000001110000;
+ parameter [15:0] CH1_RX_APT_CTRL_CFG2 = 16'b0000000000000100;
+ parameter [15:0] CH1_RX_APT_CTRL_CFG3 = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_CAL_CFG0A = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_CAL_CFG0B = 16'b0011001100110000;
+ parameter [15:0] CH1_RX_CAL_CFG1A = 16'b1110111011100001;
+ parameter [15:0] CH1_RX_CAL_CFG1B = 16'b1111111100000100;
+ parameter [15:0] CH1_RX_CAL_CFG2A = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_CAL_CFG2B = 16'b0011000000000000;
+ parameter [15:0] CH1_RX_CDR_CFG0A = 16'b0000000000000011;
+ parameter [15:0] CH1_RX_CDR_CFG0B = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_CDR_CFG1A = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_CDR_CFG1B = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_CDR_CFG2A = 16'b1001000101100100;
+ parameter [15:0] CH1_RX_CDR_CFG2B = 16'b0000000100100100;
+ parameter [15:0] CH1_RX_CDR_CFG3A = 16'b0101110011110110;
+ parameter [15:0] CH1_RX_CDR_CFG3B = 16'b0000000000001011;
+ parameter [15:0] CH1_RX_CDR_CFG4A = 16'b0000000000000110;
+ parameter [15:0] CH1_RX_CDR_CFG4B = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_CLKGN_CFG0 = 16'b1100000000000000;
+ parameter [15:0] CH1_RX_CLKGN_CFG1 = 16'b0000000110000000;
+ parameter [15:0] CH1_RX_CTLE_CFG0 = 16'b0011010010001000;
+ parameter [15:0] CH1_RX_CTLE_CFG1 = 16'b0010000000100010;
+ parameter [15:0] CH1_RX_CTLE_CFG2 = 16'b0000101000000000;
+ parameter [15:0] CH1_RX_CTLE_CFG3 = 16'b1111001001000000;
+ parameter [15:0] CH1_RX_DSP_CFG = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_MON_CFG = 16'b0000000000000000;
+ parameter [15:0] CH1_RX_PAD_CFG0 = 16'b0001111000000000;
+ parameter [15:0] CH1_RX_PAD_CFG1 = 16'b0001100000001010;
+ parameter [15:0] CH1_RX_PCS_CFG0 = 16'b0000000100000000;
+ parameter [15:0] CH1_RX_PCS_CFG1 = 16'b0000000000000000;
+ parameter [15:0] CH1_TX_ANA_CFG0 = 16'b0000001010101111;
+ parameter [15:0] CH1_TX_ANA_CFG1 = 16'b0000000100000000;
+ parameter [15:0] CH1_TX_ANA_CFG2 = 16'b1000000000010100;
+ parameter [15:0] CH1_TX_ANA_CFG3 = 16'b0000101000100010;
+ parameter [15:0] CH1_TX_ANA_CFG4 = 16'b0000000000000000;
+ parameter [15:0] CH1_TX_CAL_CFG0 = 16'b0000000000100000;
+ parameter [15:0] CH1_TX_CAL_CFG1 = 16'b0000000001000000;
+ parameter [15:0] CH1_TX_DRV_CFG0 = 16'b0000000000000000;
+ parameter [15:0] CH1_TX_DRV_CFG1 = 16'b0000000000100111;
+ parameter [15:0] CH1_TX_DRV_CFG2 = 16'b0000000000000000;
+ parameter [15:0] CH1_TX_DRV_CFG3 = 16'b0110110000000000;
+ parameter [15:0] CH1_TX_DRV_CFG4 = 16'b0000000011000101;
+ parameter [15:0] CH1_TX_DRV_CFG5 = 16'b0000000000000000;
+ parameter [15:0] CH1_TX_LPBK_CFG0 = 16'b0000000000000011;
+ parameter [15:0] CH1_TX_LPBK_CFG1 = 16'b0000000000000000;
+ parameter [15:0] CH1_TX_PCS_CFG0 = 16'b0000000101100000;
+ parameter [15:0] CH1_TX_PCS_CFG1 = 16'b0000000000000000;
+ parameter [15:0] CH1_TX_PCS_CFG10 = 16'b0000000000000000;
+ parameter [15:0] CH1_TX_PCS_CFG11 = 16'b0000000000000000;
+ parameter [15:0] CH1_TX_PCS_CFG12 = 16'b0000000000000000;
+ parameter [15:0] CH1_TX_PCS_CFG13 = 16'b0000000000000000;
+ parameter [15:0] CH1_TX_PCS_CFG14 = 16'b0000000000000000;
+ parameter [15:0] CH1_TX_PCS_CFG15 = 16'b0000000000000000;
+ parameter [15:0] CH1_TX_PCS_CFG16 = 16'b0000000000000000;
+ parameter [15:0] CH1_TX_PCS_CFG17 = 16'b0000000000000000;
+ parameter [15:0] CH1_TX_PCS_CFG2 = 16'b0000000000000000;
+ parameter [15:0] CH1_TX_PCS_CFG3 = 16'b0000000000000000;
+ parameter [15:0] CH1_TX_PCS_CFG4 = 16'b0000000000000000;
+ parameter [15:0] CH1_TX_PCS_CFG5 = 16'b0000000000000000;
+ parameter [15:0] CH1_TX_PCS_CFG6 = 16'b0000000000000000;
+ parameter [15:0] CH1_TX_PCS_CFG7 = 16'b0000000000000000;
+ parameter [15:0] CH1_TX_PCS_CFG8 = 16'b0000000000000000;
+ parameter [15:0] CH1_TX_PCS_CFG9 = 16'b0000000000000000;
+ parameter real DATARATE = 10.000;
+ parameter [15:0] DRPEN_CFG = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG0 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG1 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG10 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG11 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG12 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG13 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG14 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG15 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG16 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG17 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG18 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG19 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG2 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG20 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG21 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG22 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG23 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG24 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG25 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG26 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG27 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG3 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG4 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG5 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG6 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG7 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG8 = 16'b0000000000000000;
+ parameter [15:0] FEC_CFG9 = 16'b0000000000000000;
+ parameter FEC_MODE = "BYPASS";
+ parameter real INS_LOSS_NYQ = 20.000;
+ parameter integer INTERFACE_WIDTH = 64;
+ parameter MODULATION_MODE = "NRZ";
+ parameter [15:0] PLL_CFG0 = 16'b0001100111110000;
+ parameter [15:0] PLL_CFG1 = 16'b0000111101110000;
+ parameter [15:0] PLL_CFG2 = 16'b1000000111101000;
+ parameter [15:0] PLL_CFG3 = 16'b0100000000000000;
+ parameter [15:0] PLL_CFG4 = 16'b0111111111101010;
+ parameter [15:0] PLL_CFG5 = 16'b0100101100111000;
+ parameter [15:0] PLL_CFG6 = 16'b0000000000100101;
+ parameter [15:0] PLL_CRS_CTRL_CFG0 = 16'b0000101100100000;
+ parameter [15:0] PLL_CRS_CTRL_CFG1 = 16'b1100010111010100;
+ parameter [0:0] PLL_IPS_PIN_EN = 1'b1;
+ parameter integer PLL_IPS_REFCLK_SEL = 0;
+ parameter [0:0] RCALSAP_TESTEN = 1'b0;
+ parameter [0:0] RCAL_APROBE = 1'b0;
+ parameter [15:0] RST_CFG = 16'b0000000000000010;
+ parameter [15:0] RST_PLL_CFG0 = 16'b0111011000010100;
+ parameter [15:0] SAP_CFG0 = 16'b0000000000000000;
+ parameter [15:0] SDM_CFG0 = 16'b0001100001000000;
+ parameter [15:0] SDM_CFG1 = 16'b0000000000000000;
+ parameter [15:0] SDM_CFG2 = 16'b0000000000000000;
+ parameter [15:0] SDM_SEED_CFG0 = 16'b0000000000000000;
+ parameter [15:0] SDM_SEED_CFG1 = 16'b0000000000000000;
+ parameter SIM_DEVICE = "ULTRASCALE_PLUS_ES1";
+ parameter SIM_RESET_SPEEDUP = "TRUE";
+ parameter integer TX_AMPLITUDE_SWING = 250;
+ output [27:0] CH0_AXISTDATA;
+ output CH0_AXISTLAST;
+ output CH0_AXISTVALID;
+ output [31:0] CH0_DMONITOROUT;
+ output CH0_DMONITOROUTCLK;
+ output CH0_GTMTXN;
+ output CH0_GTMTXP;
+ output [15:0] CH0_PCSRSVDOUT;
+ output [15:0] CH0_PMARSVDOUT;
+ output CH0_RESETEXCEPTION;
+ output [2:0] CH0_RXBUFSTATUS;
+ output [255:0] CH0_RXDATA;
+ output [3:0] CH0_RXDATAFLAGS;
+ output CH0_RXDATAISAM;
+ output CH0_RXDATASTART;
+ output CH0_RXOUTCLK;
+ output CH0_RXPMARESETDONE;
+ output CH0_RXPRBSERR;
+ output CH0_RXPRBSLOCKED;
+ output CH0_RXPRGDIVRESETDONE;
+ output CH0_RXPROGDIVCLK;
+ output CH0_RXRESETDONE;
+ output [1:0] CH0_TXBUFSTATUS;
+ output CH0_TXOUTCLK;
+ output CH0_TXPMARESETDONE;
+ output CH0_TXPRGDIVRESETDONE;
+ output CH0_TXPROGDIVCLK;
+ output CH0_TXRESETDONE;
+ output [27:0] CH1_AXISTDATA;
+ output CH1_AXISTLAST;
+ output CH1_AXISTVALID;
+ output [31:0] CH1_DMONITOROUT;
+ output CH1_DMONITOROUTCLK;
+ output CH1_GTMTXN;
+ output CH1_GTMTXP;
+ output [15:0] CH1_PCSRSVDOUT;
+ output [15:0] CH1_PMARSVDOUT;
+ output CH1_RESETEXCEPTION;
+ output [2:0] CH1_RXBUFSTATUS;
+ output [255:0] CH1_RXDATA;
+ output [3:0] CH1_RXDATAFLAGS;
+ output CH1_RXDATAISAM;
+ output CH1_RXDATASTART;
+ output CH1_RXOUTCLK;
+ output CH1_RXPMARESETDONE;
+ output CH1_RXPRBSERR;
+ output CH1_RXPRBSLOCKED;
+ output CH1_RXPRGDIVRESETDONE;
+ output CH1_RXPROGDIVCLK;
+ output CH1_RXRESETDONE;
+ output [1:0] CH1_TXBUFSTATUS;
+ output CH1_TXOUTCLK;
+ output CH1_TXPMARESETDONE;
+ output CH1_TXPRGDIVRESETDONE;
+ output CH1_TXPROGDIVCLK;
+ output CH1_TXRESETDONE;
+ output CLKTESTSIG2PAD;
+ output DMONITOROUTPLLCLK;
+ output [15:0] DRPDO;
+ output DRPRDY;
+ output FECRX0ALIGNED;
+ output FECRX0CORRCWINC;
+ output FECRX0CWINC;
+ output FECRX0UNCORRCWINC;
+ output FECRX1ALIGNED;
+ output FECRX1CORRCWINC;
+ output FECRX1CWINC;
+ output FECRX1UNCORRCWINC;
+ output [7:0] FECRXLN0BITERR0TO1INC;
+ output [7:0] FECRXLN0BITERR1TO0INC;
+ output [14:0] FECRXLN0DLY;
+ output [3:0] FECRXLN0ERRCNTINC;
+ output [1:0] FECRXLN0MAPPING;
+ output [7:0] FECRXLN1BITERR0TO1INC;
+ output [7:0] FECRXLN1BITERR1TO0INC;
+ output [14:0] FECRXLN1DLY;
+ output [3:0] FECRXLN1ERRCNTINC;
+ output [1:0] FECRXLN1MAPPING;
+ output [7:0] FECRXLN2BITERR0TO1INC;
+ output [7:0] FECRXLN2BITERR1TO0INC;
+ output [14:0] FECRXLN2DLY;
+ output [3:0] FECRXLN2ERRCNTINC;
+ output [1:0] FECRXLN2MAPPING;
+ output [7:0] FECRXLN3BITERR0TO1INC;
+ output [7:0] FECRXLN3BITERR1TO0INC;
+ output [14:0] FECRXLN3DLY;
+ output [3:0] FECRXLN3ERRCNTINC;
+ output [1:0] FECRXLN3MAPPING;
+ output FECTRXLN0LOCK;
+ output FECTRXLN1LOCK;
+ output FECTRXLN2LOCK;
+ output FECTRXLN3LOCK;
+ output GTPOWERGOOD;
+ output PLLFBCLKLOST;
+ output PLLLOCK;
+ output PLLREFCLKLOST;
+ output PLLREFCLKMONITOR;
+ output PLLRESETDONE;
+ output [15:0] PLLRSVDOUT;
+ output RCALCMP;
+ output [4:0] RCALOUT;
+ output RXRECCLK0;
+ output RXRECCLK1;
+ input BGBYPASSB;
+ input BGMONITORENB;
+ input BGPDB;
+ input [4:0] BGRCALOVRD;
+ input BGRCALOVRDENB;
+ input CH0_AXISEN;
+ input CH0_AXISRST;
+ input CH0_AXISTRDY;
+ input CH0_CFGRESET;
+ input CH0_DMONFIFORESET;
+ input CH0_DMONITORCLK;
+ input CH0_GTMRXN;
+ input CH0_GTMRXP;
+ input CH0_GTRXRESET;
+ input CH0_GTTXRESET;
+ input [2:0] CH0_LOOPBACK;
+ input [15:0] CH0_PCSRSVDIN;
+ input [15:0] CH0_PMARSVDIN;
+ input CH0_RESETOVRD;
+ input CH0_RXADAPTRESET;
+ input CH0_RXADCCALRESET;
+ input CH0_RXADCCLKGENRESET;
+ input CH0_RXBUFRESET;
+ input CH0_RXCDRFREQOS;
+ input CH0_RXCDRFRRESET;
+ input CH0_RXCDRHOLD;
+ input CH0_RXCDRINCPCTRL;
+ input CH0_RXCDROVRDEN;
+ input CH0_RXCDRPHRESET;
+ input CH0_RXDFERESET;
+ input CH0_RXDSPRESET;
+ input CH0_RXEQTRAINING;
+ input CH0_RXEYESCANRESET;
+ input CH0_RXFECRESET;
+ input [2:0] CH0_RXOUTCLKSEL;
+ input CH0_RXPCSRESET;
+ input [3:0] CH0_RXPCSRESETMASK;
+ input CH0_RXPMARESET;
+ input [7:0] CH0_RXPMARESETMASK;
+ input CH0_RXPOLARITY;
+ input CH0_RXPRBSCNTSTOP;
+ input CH0_RXPRBSCSCNTRST;
+ input [3:0] CH0_RXPRBSPTN;
+ input CH0_RXPROGDIVRESET;
+ input CH0_RXQPRBSEN;
+ input [1:0] CH0_RXRESETMODE;
+ input CH0_RXSPCSEQADV;
+ input CH0_RXUSRCLK;
+ input CH0_RXUSRCLK2;
+ input CH0_RXUSRRDY;
+ input CH0_RXUSRSTART;
+ input CH0_RXUSRSTOP;
+ input CH0_TXCKALRESET;
+ input [5:0] CH0_TXCTLFIRDAT;
+ input [255:0] CH0_TXDATA;
+ input CH0_TXDATASTART;
+ input [4:0] CH0_TXDRVAMP;
+ input [5:0] CH0_TXEMPMAIN;
+ input [4:0] CH0_TXEMPPOST;
+ input [4:0] CH0_TXEMPPRE;
+ input [3:0] CH0_TXEMPPRE2;
+ input CH0_TXFECRESET;
+ input CH0_TXINHIBIT;
+ input CH0_TXMUXDCDEXHOLD;
+ input CH0_TXMUXDCDORWREN;
+ input [2:0] CH0_TXOUTCLKSEL;
+ input CH0_TXPCSRESET;
+ input [1:0] CH0_TXPCSRESETMASK;
+ input CH0_TXPMARESET;
+ input [1:0] CH0_TXPMARESETMASK;
+ input CH0_TXPOLARITY;
+ input CH0_TXPRBSINERR;
+ input [3:0] CH0_TXPRBSPTN;
+ input CH0_TXPROGDIVRESET;
+ input CH0_TXQPRBSEN;
+ input [1:0] CH0_TXRESETMODE;
+ input CH0_TXSPCSEQADV;
+ input CH0_TXUSRCLK;
+ input CH0_TXUSRCLK2;
+ input CH0_TXUSRRDY;
+ input CH1_AXISEN;
+ input CH1_AXISRST;
+ input CH1_AXISTRDY;
+ input CH1_CFGRESET;
+ input CH1_DMONFIFORESET;
+ input CH1_DMONITORCLK;
+ input CH1_GTMRXN;
+ input CH1_GTMRXP;
+ input CH1_GTRXRESET;
+ input CH1_GTTXRESET;
+ input [2:0] CH1_LOOPBACK;
+ input [15:0] CH1_PCSRSVDIN;
+ input [15:0] CH1_PMARSVDIN;
+ input CH1_RESETOVRD;
+ input CH1_RXADAPTRESET;
+ input CH1_RXADCCALRESET;
+ input CH1_RXADCCLKGENRESET;
+ input CH1_RXBUFRESET;
+ input CH1_RXCDRFREQOS;
+ input CH1_RXCDRFRRESET;
+ input CH1_RXCDRHOLD;
+ input CH1_RXCDRINCPCTRL;
+ input CH1_RXCDROVRDEN;
+ input CH1_RXCDRPHRESET;
+ input CH1_RXDFERESET;
+ input CH1_RXDSPRESET;
+ input CH1_RXEQTRAINING;
+ input CH1_RXEYESCANRESET;
+ input CH1_RXFECRESET;
+ input [2:0] CH1_RXOUTCLKSEL;
+ input CH1_RXPCSRESET;
+ input [3:0] CH1_RXPCSRESETMASK;
+ input CH1_RXPMARESET;
+ input [7:0] CH1_RXPMARESETMASK;
+ input CH1_RXPOLARITY;
+ input CH1_RXPRBSCNTSTOP;
+ input CH1_RXPRBSCSCNTRST;
+ input [3:0] CH1_RXPRBSPTN;
+ input CH1_RXPROGDIVRESET;
+ input CH1_RXQPRBSEN;
+ input [1:0] CH1_RXRESETMODE;
+ input CH1_RXSPCSEQADV;
+ input CH1_RXUSRCLK;
+ input CH1_RXUSRCLK2;
+ input CH1_RXUSRRDY;
+ input CH1_RXUSRSTART;
+ input CH1_RXUSRSTOP;
+ input CH1_TXCKALRESET;
+ input [5:0] CH1_TXCTLFIRDAT;
+ input [255:0] CH1_TXDATA;
+ input CH1_TXDATASTART;
+ input [4:0] CH1_TXDRVAMP;
+ input [5:0] CH1_TXEMPMAIN;
+ input [4:0] CH1_TXEMPPOST;
+ input [4:0] CH1_TXEMPPRE;
+ input [3:0] CH1_TXEMPPRE2;
+ input CH1_TXFECRESET;
+ input CH1_TXINHIBIT;
+ input CH1_TXMUXDCDEXHOLD;
+ input CH1_TXMUXDCDORWREN;
+ input [2:0] CH1_TXOUTCLKSEL;
+ input CH1_TXPCSRESET;
+ input [1:0] CH1_TXPCSRESETMASK;
+ input CH1_TXPMARESET;
+ input [1:0] CH1_TXPMARESETMASK;
+ input CH1_TXPOLARITY;
+ input CH1_TXPRBSINERR;
+ input [3:0] CH1_TXPRBSPTN;
+ input CH1_TXPROGDIVRESET;
+ input CH1_TXQPRBSEN;
+ input [1:0] CH1_TXRESETMODE;
+ input CH1_TXSPCSEQADV;
+ input CH1_TXUSRCLK;
+ input CH1_TXUSRCLK2;
+ input CH1_TXUSRRDY;
+ input [10:0] DRPADDR;
+ input DRPCLK;
+ input [15:0] DRPDI;
+ input DRPEN;
+ input DRPRST;
+ input DRPWE;
+ input FECCTRLRX0BITSLIPFS;
+ input FECCTRLRX1BITSLIPFS;
+ input GTGREFCLK2PLL;
+ input GTNORTHREFCLK;
+ input GTREFCLK;
+ input GTSOUTHREFCLK;
+ input [7:0] PLLFBDIV;
+ input PLLMONCLK;
+ input PLLPD;
+ input [2:0] PLLREFCLKSEL;
+ input PLLRESET;
+ input PLLRESETBYPASSMODE;
+ input [1:0] PLLRESETMASK;
+ input [15:0] PLLRSVDIN;
+ input RCALENB;
+ input [25:0] SDMDATA;
+ input SDMTOGGLE;
+endmodule
+
+module IBUFDS_GTM (...);
parameter [0:0] REFCLK_EN_TX_PATH = 1'b0;
- parameter [4:0] REFCLK_ICNTL_TX = 5'b00000;
+ parameter integer REFCLK_HROW_CK_SEL = 0;
+ parameter integer REFCLK_ICNTL_RX = 0;
+ output O;
+ output ODIV2;
+ input CEB;
+ (* iopad_external_pin *)
+ input I;
+ (* iopad_external_pin *)
+ input IB;
+endmodule
+
+module OBUFDS_GTM (...);
+ parameter [0:0] REFCLK_EN_TX_PATH = 1'b0;
+ parameter integer REFCLK_ICNTL_TX = 0;
(* iopad_external_pin *)
output O;
(* iopad_external_pin *)
@@ -18180,16 +18921,259 @@ module OBUFDS_GTE4 (...);
input I;
endmodule
-module OBUFDS_GTE4_ADV (...);
+module OBUFDS_GTM_ADV (...);
parameter [0:0] REFCLK_EN_TX_PATH = 1'b0;
- parameter [4:0] REFCLK_ICNTL_TX = 5'b00000;
+ parameter integer REFCLK_ICNTL_TX = 0;
+ parameter [1:0] RXRECCLK_SEL = 2'b00;
(* iopad_external_pin *)
output O;
(* iopad_external_pin *)
output OB;
input CEB;
input [3:0] I;
- input [1:0] RXRECCLK_SEL;
+endmodule
+
+module HSDAC (...);
+ parameter SIM_DEVICE = "ULTRASCALE_PLUS";
+ parameter integer XPA_CFG0 = 0;
+ parameter integer XPA_CFG1 = 0;
+ parameter integer XPA_NUM_DACS = 0;
+ parameter integer XPA_NUM_DUCS = 0;
+ parameter XPA_PLL_USED = "No";
+ parameter integer XPA_SAMPLE_RATE_MSPS = 0;
+ output CLK_DAC;
+ output [15:0] DOUT;
+ output DRDY;
+ output PLL_DMON_OUT;
+ output PLL_REFCLK_OUT;
+ output [15:0] STATUS_COMMON;
+ output [15:0] STATUS_DAC0;
+ output [15:0] STATUS_DAC1;
+ output [15:0] STATUS_DAC2;
+ output [15:0] STATUS_DAC3;
+ output SYSREF_OUT_NORTH;
+ output SYSREF_OUT_SOUTH;
+ output VOUT0_N;
+ output VOUT0_P;
+ output VOUT1_N;
+ output VOUT1_P;
+ output VOUT2_N;
+ output VOUT2_P;
+ output VOUT3_N;
+ output VOUT3_P;
+ input CLK_FIFO_LM;
+ input [15:0] CONTROL_COMMON;
+ input [15:0] CONTROL_DAC0;
+ input [15:0] CONTROL_DAC1;
+ input [15:0] CONTROL_DAC2;
+ input [15:0] CONTROL_DAC3;
+ input DAC_CLK_N;
+ input DAC_CLK_P;
+ input [11:0] DADDR;
+ input [255:0] DATA_DAC0;
+ input [255:0] DATA_DAC1;
+ input [255:0] DATA_DAC2;
+ input [255:0] DATA_DAC3;
+ input DCLK;
+ input DEN;
+ input [15:0] DI;
+ input DWE;
+ input FABRIC_CLK;
+ input PLL_MONCLK;
+ input PLL_REFCLK_IN;
+ input SYSREF_IN_NORTH;
+ input SYSREF_IN_SOUTH;
+ input SYSREF_N;
+ input SYSREF_P;
+endmodule
+
+module HSADC (...);
+ parameter SIM_DEVICE = "ULTRASCALE_PLUS";
+ parameter integer XPA_CFG0 = 0;
+ parameter integer XPA_CFG1 = 0;
+ parameter XPA_NUM_ADCS = "0";
+ parameter integer XPA_NUM_DDCS = 0;
+ parameter XPA_PLL_USED = "No";
+ parameter integer XPA_SAMPLE_RATE_MSPS = 0;
+ output CLK_ADC;
+ output [127:0] DATA_ADC0;
+ output [127:0] DATA_ADC1;
+ output [127:0] DATA_ADC2;
+ output [127:0] DATA_ADC3;
+ output [15:0] DOUT;
+ output DRDY;
+ output PLL_DMON_OUT;
+ output PLL_REFCLK_OUT;
+ output [15:0] STATUS_ADC0;
+ output [15:0] STATUS_ADC1;
+ output [15:0] STATUS_ADC2;
+ output [15:0] STATUS_ADC3;
+ output [15:0] STATUS_COMMON;
+ output SYSREF_OUT_NORTH;
+ output SYSREF_OUT_SOUTH;
+ input ADC_CLK_N;
+ input ADC_CLK_P;
+ input CLK_FIFO_LM;
+ input [15:0] CONTROL_ADC0;
+ input [15:0] CONTROL_ADC1;
+ input [15:0] CONTROL_ADC2;
+ input [15:0] CONTROL_ADC3;
+ input [15:0] CONTROL_COMMON;
+ input [11:0] DADDR;
+ input DCLK;
+ input DEN;
+ input [15:0] DI;
+ input DWE;
+ input FABRIC_CLK;
+ input PLL_MONCLK;
+ input PLL_REFCLK_IN;
+ input SYSREF_IN_NORTH;
+ input SYSREF_IN_SOUTH;
+ input SYSREF_N;
+ input SYSREF_P;
+ input VIN0_N;
+ input VIN0_P;
+ input VIN1_N;
+ input VIN1_P;
+ input VIN2_N;
+ input VIN2_P;
+ input VIN3_N;
+ input VIN3_P;
+ input VIN_I01_N;
+ input VIN_I01_P;
+ input VIN_I23_N;
+ input VIN_I23_P;
+endmodule
+
+module RFDAC (...);
+ parameter integer OPT_CLK_DIST = 0;
+ parameter SIM_DEVICE = "ULTRASCALE_PLUS";
+ parameter integer XPA_ACTIVE_DUTYCYCLE = 100;
+ parameter integer XPA_CFG0 = 0;
+ parameter integer XPA_CFG1 = 0;
+ parameter integer XPA_CFG2 = 0;
+ parameter integer XPA_NUM_DACS = 0;
+ parameter integer XPA_NUM_DUCS = 0;
+ parameter XPA_PLL_USED = "EXTERNAL";
+ parameter integer XPA_SAMPLE_RATE_MSPS = 0;
+ output CLK_DAC;
+ output CLK_DIST_OUT_NORTH;
+ output CLK_DIST_OUT_SOUTH;
+ output [15:0] DOUT;
+ output DRDY;
+ output PLL_DMON_OUT;
+ output PLL_REFCLK_OUT;
+ output [23:0] STATUS_COMMON;
+ output [23:0] STATUS_DAC0;
+ output [23:0] STATUS_DAC1;
+ output [23:0] STATUS_DAC2;
+ output [23:0] STATUS_DAC3;
+ output SYSREF_OUT_NORTH;
+ output SYSREF_OUT_SOUTH;
+ output T1_ALLOWED_SOUTH;
+ output VOUT0_N;
+ output VOUT0_P;
+ output VOUT1_N;
+ output VOUT1_P;
+ output VOUT2_N;
+ output VOUT2_P;
+ output VOUT3_N;
+ output VOUT3_P;
+ input CLK_DIST_IN_NORTH;
+ input CLK_DIST_IN_SOUTH;
+ input CLK_FIFO_LM;
+ input [15:0] CONTROL_COMMON;
+ input [15:0] CONTROL_DAC0;
+ input [15:0] CONTROL_DAC1;
+ input [15:0] CONTROL_DAC2;
+ input [15:0] CONTROL_DAC3;
+ input DAC_CLK_N;
+ input DAC_CLK_P;
+ input [11:0] DADDR;
+ input [255:0] DATA_DAC0;
+ input [255:0] DATA_DAC1;
+ input [255:0] DATA_DAC2;
+ input [255:0] DATA_DAC3;
+ input DCLK;
+ input DEN;
+ input [15:0] DI;
+ input DWE;
+ input FABRIC_CLK;
+ input PLL_MONCLK;
+ input PLL_REFCLK_IN;
+ input SYSREF_IN_NORTH;
+ input SYSREF_IN_SOUTH;
+ input SYSREF_N;
+ input SYSREF_P;
+ input T1_ALLOWED_NORTH;
+endmodule
+
+module RFADC (...);
+ parameter integer OPT_ANALOG = 0;
+ parameter integer OPT_CLK_DIST = 0;
+ parameter SIM_DEVICE = "ULTRASCALE_PLUS";
+ parameter integer XPA_ACTIVE_DUTYCYCLE = 100;
+ parameter integer XPA_CFG0 = 0;
+ parameter integer XPA_CFG1 = 0;
+ parameter integer XPA_CFG2 = 0;
+ parameter XPA_NUM_ADCS = "0";
+ parameter integer XPA_NUM_DDCS = 0;
+ parameter XPA_PLL_USED = "EXTERNAL";
+ parameter integer XPA_SAMPLE_RATE_MSPS = 0;
+ output CLK_ADC;
+ output CLK_DIST_OUT_NORTH;
+ output CLK_DIST_OUT_SOUTH;
+ output [191:0] DATA_ADC0;
+ output [191:0] DATA_ADC1;
+ output [191:0] DATA_ADC2;
+ output [191:0] DATA_ADC3;
+ output [15:0] DOUT;
+ output DRDY;
+ output PLL_DMON_OUT;
+ output PLL_REFCLK_OUT;
+ output [23:0] STATUS_ADC0;
+ output [23:0] STATUS_ADC1;
+ output [23:0] STATUS_ADC2;
+ output [23:0] STATUS_ADC3;
+ output [23:0] STATUS_COMMON;
+ output SYSREF_OUT_NORTH;
+ output SYSREF_OUT_SOUTH;
+ output T1_ALLOWED_SOUTH;
+ input ADC_CLK_N;
+ input ADC_CLK_P;
+ input CLK_DIST_IN_NORTH;
+ input CLK_DIST_IN_SOUTH;
+ input CLK_FIFO_LM;
+ input [15:0] CONTROL_ADC0;
+ input [15:0] CONTROL_ADC1;
+ input [15:0] CONTROL_ADC2;
+ input [15:0] CONTROL_ADC3;
+ input [15:0] CONTROL_COMMON;
+ input [11:0] DADDR;
+ input DCLK;
+ input DEN;
+ input [15:0] DI;
+ input DWE;
+ input FABRIC_CLK;
+ input PLL_MONCLK;
+ input PLL_REFCLK_IN;
+ input SYSREF_IN_NORTH;
+ input SYSREF_IN_SOUTH;
+ input SYSREF_N;
+ input SYSREF_P;
+ input T1_ALLOWED_NORTH;
+ input VIN0_N;
+ input VIN0_P;
+ input VIN1_N;
+ input VIN1_P;
+ input VIN2_N;
+ input VIN2_P;
+ input VIN3_N;
+ input VIN3_P;
+ input VIN_I01_N;
+ input VIN_I01_P;
+ input VIN_I23_N;
+ input VIN_I23_P;
endmodule
module PCIE_A1 (...);
@@ -23569,6 +24553,1312 @@ module PCIE40E4 (...);
input [31:0] USERSPAREIN;
endmodule
+module PCIE4CE4 (...);
+ parameter ARI_CAP_ENABLE = "FALSE";
+ parameter AUTO_FLR_RESPONSE = "FALSE";
+ parameter [7:0] AXISTEN_IF_CCIX_RX_CREDIT_LIMIT = 8'h08;
+ parameter [7:0] AXISTEN_IF_CCIX_TX_CREDIT_LIMIT = 8'h08;
+ parameter AXISTEN_IF_CCIX_TX_REGISTERED_TREADY = "FALSE";
+ parameter [1:0] AXISTEN_IF_CC_ALIGNMENT_MODE = 2'h0;
+ parameter [23:0] AXISTEN_IF_COMPL_TIMEOUT_REG0 = 24'hBEBC20;
+ parameter [27:0] AXISTEN_IF_COMPL_TIMEOUT_REG1 = 28'h2FAF080;
+ parameter [1:0] AXISTEN_IF_CQ_ALIGNMENT_MODE = 2'h0;
+ parameter AXISTEN_IF_CQ_EN_POISONED_MEM_WR = "FALSE";
+ parameter AXISTEN_IF_ENABLE_256_TAGS = "FALSE";
+ parameter AXISTEN_IF_ENABLE_CLIENT_TAG = "FALSE";
+ parameter AXISTEN_IF_ENABLE_INTERNAL_MSIX_TABLE = "FALSE";
+ parameter AXISTEN_IF_ENABLE_MESSAGE_RID_CHECK = "TRUE";
+ parameter [17:0] AXISTEN_IF_ENABLE_MSG_ROUTE = 18'h00000;
+ parameter AXISTEN_IF_ENABLE_RX_MSG_INTFC = "FALSE";
+ parameter AXISTEN_IF_EXT_512 = "FALSE";
+ parameter AXISTEN_IF_EXT_512_CC_STRADDLE = "FALSE";
+ parameter AXISTEN_IF_EXT_512_CQ_STRADDLE = "FALSE";
+ parameter AXISTEN_IF_EXT_512_RC_STRADDLE = "FALSE";
+ parameter AXISTEN_IF_EXT_512_RQ_STRADDLE = "FALSE";
+ parameter AXISTEN_IF_LEGACY_MODE_ENABLE = "FALSE";
+ parameter AXISTEN_IF_MSIX_FROM_RAM_PIPELINE = "FALSE";
+ parameter AXISTEN_IF_MSIX_RX_PARITY_EN = "TRUE";
+ parameter AXISTEN_IF_MSIX_TO_RAM_PIPELINE = "FALSE";
+ parameter [1:0] AXISTEN_IF_RC_ALIGNMENT_MODE = 2'h0;
+ parameter AXISTEN_IF_RC_STRADDLE = "FALSE";
+ parameter [1:0] AXISTEN_IF_RQ_ALIGNMENT_MODE = 2'h0;
+ parameter AXISTEN_IF_RX_PARITY_EN = "TRUE";
+ parameter AXISTEN_IF_SIM_SHORT_CPL_TIMEOUT = "FALSE";
+ parameter AXISTEN_IF_TX_PARITY_EN = "TRUE";
+ parameter [1:0] AXISTEN_IF_WIDTH = 2'h2;
+ parameter CCIX_DIRECT_ATTACH_MODE = "FALSE";
+ parameter CCIX_ENABLE = "FALSE";
+ parameter [15:0] CCIX_VENDOR_ID = 16'h0000;
+ parameter CFG_BYPASS_MODE_ENABLE = "FALSE";
+ parameter CRM_CORE_CLK_FREQ_500 = "TRUE";
+ parameter [1:0] CRM_USER_CLK_FREQ = 2'h2;
+ parameter [15:0] DEBUG_AXI4ST_SPARE = 16'h0000;
+ parameter [7:0] DEBUG_AXIST_DISABLE_FEATURE_BIT = 8'h00;
+ parameter [3:0] DEBUG_CAR_SPARE = 4'h0;
+ parameter [15:0] DEBUG_CFG_SPARE = 16'h0000;
+ parameter [15:0] DEBUG_LL_SPARE = 16'h0000;
+ parameter DEBUG_PL_DISABLE_LES_UPDATE_ON_DEFRAMER_ERROR = "FALSE";
+ parameter DEBUG_PL_DISABLE_LES_UPDATE_ON_SKP_ERROR = "FALSE";
+ parameter DEBUG_PL_DISABLE_LES_UPDATE_ON_SKP_PARITY_ERROR = "FALSE";
+ parameter DEBUG_PL_DISABLE_REC_ENTRY_ON_DYNAMIC_DSKEW_FAIL = "FALSE";
+ parameter DEBUG_PL_DISABLE_REC_ENTRY_ON_RX_BUFFER_UNDER_OVER_FLOW = "FALSE";
+ parameter DEBUG_PL_DISABLE_SCRAMBLING = "FALSE";
+ parameter DEBUG_PL_SIM_RESET_LFSR = "FALSE";
+ parameter [15:0] DEBUG_PL_SPARE = 16'h0000;
+ parameter DEBUG_TL_DISABLE_FC_TIMEOUT = "FALSE";
+ parameter DEBUG_TL_DISABLE_RX_TLP_ORDER_CHECKS = "FALSE";
+ parameter [15:0] DEBUG_TL_SPARE = 16'h0000;
+ parameter [7:0] DNSTREAM_LINK_NUM = 8'h00;
+ parameter DSN_CAP_ENABLE = "FALSE";
+ parameter EXTENDED_CFG_EXTEND_INTERFACE_ENABLE = "FALSE";
+ parameter HEADER_TYPE_OVERRIDE = "FALSE";
+ parameter IS_SWITCH_PORT = "FALSE";
+ parameter LEGACY_CFG_EXTEND_INTERFACE_ENABLE = "FALSE";
+ parameter [8:0] LL_ACK_TIMEOUT = 9'h000;
+ parameter LL_ACK_TIMEOUT_EN = "FALSE";
+ parameter integer LL_ACK_TIMEOUT_FUNC = 0;
+ parameter LL_DISABLE_SCHED_TX_NAK = "FALSE";
+ parameter LL_REPLAY_FROM_RAM_PIPELINE = "FALSE";
+ parameter [8:0] LL_REPLAY_TIMEOUT = 9'h000;
+ parameter LL_REPLAY_TIMEOUT_EN = "FALSE";
+ parameter integer LL_REPLAY_TIMEOUT_FUNC = 0;
+ parameter LL_REPLAY_TO_RAM_PIPELINE = "FALSE";
+ parameter LL_RX_TLP_PARITY_GEN = "TRUE";
+ parameter LL_TX_TLP_PARITY_CHK = "TRUE";
+ parameter [15:0] LL_USER_SPARE = 16'h0000;
+ parameter [9:0] LTR_TX_MESSAGE_MINIMUM_INTERVAL = 10'h250;
+ parameter LTR_TX_MESSAGE_ON_FUNC_POWER_STATE_CHANGE = "FALSE";
+ parameter LTR_TX_MESSAGE_ON_LTR_ENABLE = "FALSE";
+ parameter [11:0] MCAP_CAP_NEXTPTR = 12'h000;
+ parameter MCAP_CONFIGURE_OVERRIDE = "FALSE";
+ parameter MCAP_ENABLE = "FALSE";
+ parameter MCAP_EOS_DESIGN_SWITCH = "FALSE";
+ parameter [31:0] MCAP_FPGA_BITSTREAM_VERSION = 32'h00000000;
+ parameter MCAP_GATE_IO_ENABLE_DESIGN_SWITCH = "FALSE";
+ parameter MCAP_GATE_MEM_ENABLE_DESIGN_SWITCH = "FALSE";
+ parameter MCAP_INPUT_GATE_DESIGN_SWITCH = "FALSE";
+ parameter MCAP_INTERRUPT_ON_MCAP_EOS = "FALSE";
+ parameter MCAP_INTERRUPT_ON_MCAP_ERROR = "FALSE";
+ parameter [15:0] MCAP_VSEC_ID = 16'h0000;
+ parameter [11:0] MCAP_VSEC_LEN = 12'h02C;
+ parameter [3:0] MCAP_VSEC_REV = 4'h0;
+ parameter PF0_AER_CAP_ECRC_GEN_AND_CHECK_CAPABLE = "FALSE";
+ parameter [11:0] PF0_AER_CAP_NEXTPTR = 12'h000;
+ parameter [11:0] PF0_ARI_CAP_NEXTPTR = 12'h000;
+ parameter [7:0] PF0_ARI_CAP_NEXT_FUNC = 8'h00;
+ parameter [3:0] PF0_ARI_CAP_VER = 4'h1;
+ parameter [4:0] PF0_ATS_CAP_INV_QUEUE_DEPTH = 5'h00;
+ parameter [11:0] PF0_ATS_CAP_NEXTPTR = 12'h000;
+ parameter PF0_ATS_CAP_ON = "FALSE";
+ parameter [5:0] PF0_BAR0_APERTURE_SIZE = 6'h03;
+ parameter [2:0] PF0_BAR0_CONTROL = 3'h4;
+ parameter [4:0] PF0_BAR1_APERTURE_SIZE = 5'h00;
+ parameter [2:0] PF0_BAR1_CONTROL = 3'h0;
+ parameter [5:0] PF0_BAR2_APERTURE_SIZE = 6'h03;
+ parameter [2:0] PF0_BAR2_CONTROL = 3'h4;
+ parameter [4:0] PF0_BAR3_APERTURE_SIZE = 5'h03;
+ parameter [2:0] PF0_BAR3_CONTROL = 3'h0;
+ parameter [5:0] PF0_BAR4_APERTURE_SIZE = 6'h03;
+ parameter [2:0] PF0_BAR4_CONTROL = 3'h4;
+ parameter [4:0] PF0_BAR5_APERTURE_SIZE = 5'h03;
+ parameter [2:0] PF0_BAR5_CONTROL = 3'h0;
+ parameter [7:0] PF0_CAPABILITY_POINTER = 8'h80;
+ parameter [23:0] PF0_CLASS_CODE = 24'h000000;
+ parameter PF0_DEV_CAP2_128B_CAS_ATOMIC_COMPLETER_SUPPORT = "TRUE";
+ parameter PF0_DEV_CAP2_32B_ATOMIC_COMPLETER_SUPPORT = "TRUE";
+ parameter PF0_DEV_CAP2_64B_ATOMIC_COMPLETER_SUPPORT = "TRUE";
+ parameter PF0_DEV_CAP2_ARI_FORWARD_ENABLE = "FALSE";
+ parameter PF0_DEV_CAP2_CPL_TIMEOUT_DISABLE = "TRUE";
+ parameter PF0_DEV_CAP2_LTR_SUPPORT = "TRUE";
+ parameter [1:0] PF0_DEV_CAP2_OBFF_SUPPORT = 2'h0;
+ parameter PF0_DEV_CAP2_TPH_COMPLETER_SUPPORT = "FALSE";
+ parameter integer PF0_DEV_CAP_ENDPOINT_L0S_LATENCY = 0;
+ parameter integer PF0_DEV_CAP_ENDPOINT_L1_LATENCY = 0;
+ parameter PF0_DEV_CAP_EXT_TAG_SUPPORTED = "TRUE";
+ parameter PF0_DEV_CAP_FUNCTION_LEVEL_RESET_CAPABLE = "TRUE";
+ parameter [2:0] PF0_DEV_CAP_MAX_PAYLOAD_SIZE = 3'h3;
+ parameter [11:0] PF0_DSN_CAP_NEXTPTR = 12'h10C;
+ parameter [4:0] PF0_EXPANSION_ROM_APERTURE_SIZE = 5'h03;
+ parameter PF0_EXPANSION_ROM_ENABLE = "FALSE";
+ parameter [2:0] PF0_INTERRUPT_PIN = 3'h1;
+ parameter integer PF0_LINK_CAP_ASPM_SUPPORT = 0;
+ parameter integer PF0_LINK_CAP_L0S_EXIT_LATENCY_COMCLK_GEN1 = 7;
+ parameter integer PF0_LINK_CAP_L0S_EXIT_LATENCY_COMCLK_GEN2 = 7;
+ parameter integer PF0_LINK_CAP_L0S_EXIT_LATENCY_COMCLK_GEN3 = 7;
+ parameter integer PF0_LINK_CAP_L0S_EXIT_LATENCY_COMCLK_GEN4 = 7;
+ parameter integer PF0_LINK_CAP_L0S_EXIT_LATENCY_GEN1 = 7;
+ parameter integer PF0_LINK_CAP_L0S_EXIT_LATENCY_GEN2 = 7;
+ parameter integer PF0_LINK_CAP_L0S_EXIT_LATENCY_GEN3 = 7;
+ parameter integer PF0_LINK_CAP_L0S_EXIT_LATENCY_GEN4 = 7;
+ parameter integer PF0_LINK_CAP_L1_EXIT_LATENCY_COMCLK_GEN1 = 7;
+ parameter integer PF0_LINK_CAP_L1_EXIT_LATENCY_COMCLK_GEN2 = 7;
+ parameter integer PF0_LINK_CAP_L1_EXIT_LATENCY_COMCLK_GEN3 = 7;
+ parameter integer PF0_LINK_CAP_L1_EXIT_LATENCY_COMCLK_GEN4 = 7;
+ parameter integer PF0_LINK_CAP_L1_EXIT_LATENCY_GEN1 = 7;
+ parameter integer PF0_LINK_CAP_L1_EXIT_LATENCY_GEN2 = 7;
+ parameter integer PF0_LINK_CAP_L1_EXIT_LATENCY_GEN3 = 7;
+ parameter integer PF0_LINK_CAP_L1_EXIT_LATENCY_GEN4 = 7;
+ parameter [0:0] PF0_LINK_CONTROL_RCB = 1'h0;
+ parameter PF0_LINK_STATUS_SLOT_CLOCK_CONFIG = "TRUE";
+ parameter [9:0] PF0_LTR_CAP_MAX_NOSNOOP_LAT = 10'h000;
+ parameter [9:0] PF0_LTR_CAP_MAX_SNOOP_LAT = 10'h000;
+ parameter [11:0] PF0_LTR_CAP_NEXTPTR = 12'h000;
+ parameter [3:0] PF0_LTR_CAP_VER = 4'h1;
+ parameter [7:0] PF0_MSIX_CAP_NEXTPTR = 8'h00;
+ parameter integer PF0_MSIX_CAP_PBA_BIR = 0;
+ parameter [28:0] PF0_MSIX_CAP_PBA_OFFSET = 29'h00000050;
+ parameter integer PF0_MSIX_CAP_TABLE_BIR = 0;
+ parameter [28:0] PF0_MSIX_CAP_TABLE_OFFSET = 29'h00000040;
+ parameter [10:0] PF0_MSIX_CAP_TABLE_SIZE = 11'h000;
+ parameter [5:0] PF0_MSIX_VECTOR_COUNT = 6'h04;
+ parameter integer PF0_MSI_CAP_MULTIMSGCAP = 0;
+ parameter [7:0] PF0_MSI_CAP_NEXTPTR = 8'h00;
+ parameter PF0_MSI_CAP_PERVECMASKCAP = "FALSE";
+ parameter [7:0] PF0_PCIE_CAP_NEXTPTR = 8'h00;
+ parameter [7:0] PF0_PM_CAP_ID = 8'h01;
+ parameter [7:0] PF0_PM_CAP_NEXTPTR = 8'h00;
+ parameter PF0_PM_CAP_PMESUPPORT_D0 = "TRUE";
+ parameter PF0_PM_CAP_PMESUPPORT_D1 = "TRUE";
+ parameter PF0_PM_CAP_PMESUPPORT_D3HOT = "TRUE";
+ parameter PF0_PM_CAP_SUPP_D1_STATE = "TRUE";
+ parameter [2:0] PF0_PM_CAP_VER_ID = 3'h3;
+ parameter PF0_PM_CSR_NOSOFTRESET = "TRUE";
+ parameter [11:0] PF0_PRI_CAP_NEXTPTR = 12'h000;
+ parameter PF0_PRI_CAP_ON = "FALSE";
+ parameter [31:0] PF0_PRI_OST_PR_CAPACITY = 32'h00000000;
+ parameter [11:0] PF0_SECONDARY_PCIE_CAP_NEXTPTR = 12'h000;
+ parameter PF0_SRIOV_ARI_CAPBL_HIER_PRESERVED = "FALSE";
+ parameter [5:0] PF0_SRIOV_BAR0_APERTURE_SIZE = 6'h03;
+ parameter [2:0] PF0_SRIOV_BAR0_CONTROL = 3'h4;
+ parameter [4:0] PF0_SRIOV_BAR1_APERTURE_SIZE = 5'h00;
+ parameter [2:0] PF0_SRIOV_BAR1_CONTROL = 3'h0;
+ parameter [5:0] PF0_SRIOV_BAR2_APERTURE_SIZE = 6'h03;
+ parameter [2:0] PF0_SRIOV_BAR2_CONTROL = 3'h4;
+ parameter [4:0] PF0_SRIOV_BAR3_APERTURE_SIZE = 5'h03;
+ parameter [2:0] PF0_SRIOV_BAR3_CONTROL = 3'h0;
+ parameter [5:0] PF0_SRIOV_BAR4_APERTURE_SIZE = 6'h03;
+ parameter [2:0] PF0_SRIOV_BAR4_CONTROL = 3'h4;
+ parameter [4:0] PF0_SRIOV_BAR5_APERTURE_SIZE = 5'h03;
+ parameter [2:0] PF0_SRIOV_BAR5_CONTROL = 3'h0;
+ parameter [15:0] PF0_SRIOV_CAP_INITIAL_VF = 16'h0000;
+ parameter [11:0] PF0_SRIOV_CAP_NEXTPTR = 12'h000;
+ parameter [15:0] PF0_SRIOV_CAP_TOTAL_VF = 16'h0000;
+ parameter [3:0] PF0_SRIOV_CAP_VER = 4'h1;
+ parameter [15:0] PF0_SRIOV_FIRST_VF_OFFSET = 16'h0000;
+ parameter [15:0] PF0_SRIOV_FUNC_DEP_LINK = 16'h0000;
+ parameter [31:0] PF0_SRIOV_SUPPORTED_PAGE_SIZE = 32'h00000000;
+ parameter [15:0] PF0_SRIOV_VF_DEVICE_ID = 16'h0000;
+ parameter PF0_TPHR_CAP_DEV_SPECIFIC_MODE = "TRUE";
+ parameter PF0_TPHR_CAP_ENABLE = "FALSE";
+ parameter PF0_TPHR_CAP_INT_VEC_MODE = "TRUE";
+ parameter [11:0] PF0_TPHR_CAP_NEXTPTR = 12'h000;
+ parameter [2:0] PF0_TPHR_CAP_ST_MODE_SEL = 3'h0;
+ parameter [1:0] PF0_TPHR_CAP_ST_TABLE_LOC = 2'h0;
+ parameter [10:0] PF0_TPHR_CAP_ST_TABLE_SIZE = 11'h000;
+ parameter [3:0] PF0_TPHR_CAP_VER = 4'h1;
+ parameter [3:0] PF0_VC_ARB_CAPABILITY = 4'h0;
+ parameter [7:0] PF0_VC_ARB_TBL_OFFSET = 8'h00;
+ parameter PF0_VC_CAP_ENABLE = "FALSE";
+ parameter [11:0] PF0_VC_CAP_NEXTPTR = 12'h000;
+ parameter [3:0] PF0_VC_CAP_VER = 4'h1;
+ parameter PF0_VC_EXTENDED_COUNT = "FALSE";
+ parameter PF0_VC_LOW_PRIORITY_EXTENDED_COUNT = "FALSE";
+ parameter [11:0] PF1_AER_CAP_NEXTPTR = 12'h000;
+ parameter [11:0] PF1_ARI_CAP_NEXTPTR = 12'h000;
+ parameter [7:0] PF1_ARI_CAP_NEXT_FUNC = 8'h00;
+ parameter [4:0] PF1_ATS_CAP_INV_QUEUE_DEPTH = 5'h00;
+ parameter [11:0] PF1_ATS_CAP_NEXTPTR = 12'h000;
+ parameter PF1_ATS_CAP_ON = "FALSE";
+ parameter [5:0] PF1_BAR0_APERTURE_SIZE = 6'h03;
+ parameter [2:0] PF1_BAR0_CONTROL = 3'h4;
+ parameter [4:0] PF1_BAR1_APERTURE_SIZE = 5'h00;
+ parameter [2:0] PF1_BAR1_CONTROL = 3'h0;
+ parameter [5:0] PF1_BAR2_APERTURE_SIZE = 6'h03;
+ parameter [2:0] PF1_BAR2_CONTROL = 3'h4;
+ parameter [4:0] PF1_BAR3_APERTURE_SIZE = 5'h03;
+ parameter [2:0] PF1_BAR3_CONTROL = 3'h0;
+ parameter [5:0] PF1_BAR4_APERTURE_SIZE = 6'h03;
+ parameter [2:0] PF1_BAR4_CONTROL = 3'h4;
+ parameter [4:0] PF1_BAR5_APERTURE_SIZE = 5'h03;
+ parameter [2:0] PF1_BAR5_CONTROL = 3'h0;
+ parameter [7:0] PF1_CAPABILITY_POINTER = 8'h80;
+ parameter [23:0] PF1_CLASS_CODE = 24'h000000;
+ parameter [2:0] PF1_DEV_CAP_MAX_PAYLOAD_SIZE = 3'h3;
+ parameter [11:0] PF1_DSN_CAP_NEXTPTR = 12'h10C;
+ parameter [4:0] PF1_EXPANSION_ROM_APERTURE_SIZE = 5'h03;
+ parameter PF1_EXPANSION_ROM_ENABLE = "FALSE";
+ parameter [2:0] PF1_INTERRUPT_PIN = 3'h1;
+ parameter [7:0] PF1_MSIX_CAP_NEXTPTR = 8'h00;
+ parameter integer PF1_MSIX_CAP_PBA_BIR = 0;
+ parameter [28:0] PF1_MSIX_CAP_PBA_OFFSET = 29'h00000050;
+ parameter integer PF1_MSIX_CAP_TABLE_BIR = 0;
+ parameter [28:0] PF1_MSIX_CAP_TABLE_OFFSET = 29'h00000040;
+ parameter [10:0] PF1_MSIX_CAP_TABLE_SIZE = 11'h000;
+ parameter integer PF1_MSI_CAP_MULTIMSGCAP = 0;
+ parameter [7:0] PF1_MSI_CAP_NEXTPTR = 8'h00;
+ parameter PF1_MSI_CAP_PERVECMASKCAP = "FALSE";
+ parameter [7:0] PF1_PCIE_CAP_NEXTPTR = 8'h00;
+ parameter [7:0] PF1_PM_CAP_NEXTPTR = 8'h00;
+ parameter [11:0] PF1_PRI_CAP_NEXTPTR = 12'h000;
+ parameter PF1_PRI_CAP_ON = "FALSE";
+ parameter [31:0] PF1_PRI_OST_PR_CAPACITY = 32'h00000000;
+ parameter PF1_SRIOV_ARI_CAPBL_HIER_PRESERVED = "FALSE";
+ parameter [5:0] PF1_SRIOV_BAR0_APERTURE_SIZE = 6'h03;
+ parameter [2:0] PF1_SRIOV_BAR0_CONTROL = 3'h4;
+ parameter [4:0] PF1_SRIOV_BAR1_APERTURE_SIZE = 5'h00;
+ parameter [2:0] PF1_SRIOV_BAR1_CONTROL = 3'h0;
+ parameter [5:0] PF1_SRIOV_BAR2_APERTURE_SIZE = 6'h03;
+ parameter [2:0] PF1_SRIOV_BAR2_CONTROL = 3'h4;
+ parameter [4:0] PF1_SRIOV_BAR3_APERTURE_SIZE = 5'h03;
+ parameter [2:0] PF1_SRIOV_BAR3_CONTROL = 3'h0;
+ parameter [5:0] PF1_SRIOV_BAR4_APERTURE_SIZE = 6'h03;
+ parameter [2:0] PF1_SRIOV_BAR4_CONTROL = 3'h4;
+ parameter [4:0] PF1_SRIOV_BAR5_APERTURE_SIZE = 5'h03;
+ parameter [2:0] PF1_SRIOV_BAR5_CONTROL = 3'h0;
+ parameter [15:0] PF1_SRIOV_CAP_INITIAL_VF = 16'h0000;
+ parameter [11:0] PF1_SRIOV_CAP_NEXTPTR = 12'h000;
+ parameter [15:0] PF1_SRIOV_CAP_TOTAL_VF = 16'h0000;
+ parameter [3:0] PF1_SRIOV_CAP_VER = 4'h1;
+ parameter [15:0] PF1_SRIOV_FIRST_VF_OFFSET = 16'h0000;
+ parameter [15:0] PF1_SRIOV_FUNC_DEP_LINK = 16'h0000;
+ parameter [31:0] PF1_SRIOV_SUPPORTED_PAGE_SIZE = 32'h00000000;
+ parameter [15:0] PF1_SRIOV_VF_DEVICE_ID = 16'h0000;
+ parameter [11:0] PF1_TPHR_CAP_NEXTPTR = 12'h000;
+ parameter [2:0] PF1_TPHR_CAP_ST_MODE_SEL = 3'h0;
+ parameter [11:0] PF2_AER_CAP_NEXTPTR = 12'h000;
+ parameter [11:0] PF2_ARI_CAP_NEXTPTR = 12'h000;
+ parameter [7:0] PF2_ARI_CAP_NEXT_FUNC = 8'h00;
+ parameter [4:0] PF2_ATS_CAP_INV_QUEUE_DEPTH = 5'h00;
+ parameter [11:0] PF2_ATS_CAP_NEXTPTR = 12'h000;
+ parameter PF2_ATS_CAP_ON = "FALSE";
+ parameter [5:0] PF2_BAR0_APERTURE_SIZE = 6'h03;
+ parameter [2:0] PF2_BAR0_CONTROL = 3'h4;
+ parameter [4:0] PF2_BAR1_APERTURE_SIZE = 5'h00;
+ parameter [2:0] PF2_BAR1_CONTROL = 3'h0;
+ parameter [5:0] PF2_BAR2_APERTURE_SIZE = 6'h03;
+ parameter [2:0] PF2_BAR2_CONTROL = 3'h4;
+ parameter [4:0] PF2_BAR3_APERTURE_SIZE = 5'h03;
+ parameter [2:0] PF2_BAR3_CONTROL = 3'h0;
+ parameter [5:0] PF2_BAR4_APERTURE_SIZE = 6'h03;
+ parameter [2:0] PF2_BAR4_CONTROL = 3'h4;
+ parameter [4:0] PF2_BAR5_APERTURE_SIZE = 5'h03;
+ parameter [2:0] PF2_BAR5_CONTROL = 3'h0;
+ parameter [7:0] PF2_CAPABILITY_POINTER = 8'h80;
+ parameter [23:0] PF2_CLASS_CODE = 24'h000000;
+ parameter [2:0] PF2_DEV_CAP_MAX_PAYLOAD_SIZE = 3'h3;
+ parameter [11:0] PF2_DSN_CAP_NEXTPTR = 12'h10C;
+ parameter [4:0] PF2_EXPANSION_ROM_APERTURE_SIZE = 5'h03;
+ parameter PF2_EXPANSION_ROM_ENABLE = "FALSE";
+ parameter [2:0] PF2_INTERRUPT_PIN = 3'h1;
+ parameter [7:0] PF2_MSIX_CAP_NEXTPTR = 8'h00;
+ parameter integer PF2_MSIX_CAP_PBA_BIR = 0;
+ parameter [28:0] PF2_MSIX_CAP_PBA_OFFSET = 29'h00000050;
+ parameter integer PF2_MSIX_CAP_TABLE_BIR = 0;
+ parameter [28:0] PF2_MSIX_CAP_TABLE_OFFSET = 29'h00000040;
+ parameter [10:0] PF2_MSIX_CAP_TABLE_SIZE = 11'h000;
+ parameter integer PF2_MSI_CAP_MULTIMSGCAP = 0;
+ parameter [7:0] PF2_MSI_CAP_NEXTPTR = 8'h00;
+ parameter PF2_MSI_CAP_PERVECMASKCAP = "FALSE";
+ parameter [7:0] PF2_PCIE_CAP_NEXTPTR = 8'h00;
+ parameter [7:0] PF2_PM_CAP_NEXTPTR = 8'h00;
+ parameter [11:0] PF2_PRI_CAP_NEXTPTR = 12'h000;
+ parameter PF2_PRI_CAP_ON = "FALSE";
+ parameter [31:0] PF2_PRI_OST_PR_CAPACITY = 32'h00000000;
+ parameter PF2_SRIOV_ARI_CAPBL_HIER_PRESERVED = "FALSE";
+ parameter [5:0] PF2_SRIOV_BAR0_APERTURE_SIZE = 6'h03;
+ parameter [2:0] PF2_SRIOV_BAR0_CONTROL = 3'h4;
+ parameter [4:0] PF2_SRIOV_BAR1_APERTURE_SIZE = 5'h00;
+ parameter [2:0] PF2_SRIOV_BAR1_CONTROL = 3'h0;
+ parameter [5:0] PF2_SRIOV_BAR2_APERTURE_SIZE = 6'h03;
+ parameter [2:0] PF2_SRIOV_BAR2_CONTROL = 3'h4;
+ parameter [4:0] PF2_SRIOV_BAR3_APERTURE_SIZE = 5'h03;
+ parameter [2:0] PF2_SRIOV_BAR3_CONTROL = 3'h0;
+ parameter [5:0] PF2_SRIOV_BAR4_APERTURE_SIZE = 6'h03;
+ parameter [2:0] PF2_SRIOV_BAR4_CONTROL = 3'h4;
+ parameter [4:0] PF2_SRIOV_BAR5_APERTURE_SIZE = 5'h03;
+ parameter [2:0] PF2_SRIOV_BAR5_CONTROL = 3'h0;
+ parameter [15:0] PF2_SRIOV_CAP_INITIAL_VF = 16'h0000;
+ parameter [11:0] PF2_SRIOV_CAP_NEXTPTR = 12'h000;
+ parameter [15:0] PF2_SRIOV_CAP_TOTAL_VF = 16'h0000;
+ parameter [3:0] PF2_SRIOV_CAP_VER = 4'h1;
+ parameter [15:0] PF2_SRIOV_FIRST_VF_OFFSET = 16'h0000;
+ parameter [15:0] PF2_SRIOV_FUNC_DEP_LINK = 16'h0000;
+ parameter [31:0] PF2_SRIOV_SUPPORTED_PAGE_SIZE = 32'h00000000;
+ parameter [15:0] PF2_SRIOV_VF_DEVICE_ID = 16'h0000;
+ parameter [11:0] PF2_TPHR_CAP_NEXTPTR = 12'h000;
+ parameter [2:0] PF2_TPHR_CAP_ST_MODE_SEL = 3'h0;
+ parameter [11:0] PF3_AER_CAP_NEXTPTR = 12'h000;
+ parameter [11:0] PF3_ARI_CAP_NEXTPTR = 12'h000;
+ parameter [7:0] PF3_ARI_CAP_NEXT_FUNC = 8'h00;
+ parameter [4:0] PF3_ATS_CAP_INV_QUEUE_DEPTH = 5'h00;
+ parameter [11:0] PF3_ATS_CAP_NEXTPTR = 12'h000;
+ parameter PF3_ATS_CAP_ON = "FALSE";
+ parameter [5:0] PF3_BAR0_APERTURE_SIZE = 6'h03;
+ parameter [2:0] PF3_BAR0_CONTROL = 3'h4;
+ parameter [4:0] PF3_BAR1_APERTURE_SIZE = 5'h00;
+ parameter [2:0] PF3_BAR1_CONTROL = 3'h0;
+ parameter [5:0] PF3_BAR2_APERTURE_SIZE = 6'h03;
+ parameter [2:0] PF3_BAR2_CONTROL = 3'h4;
+ parameter [4:0] PF3_BAR3_APERTURE_SIZE = 5'h03;
+ parameter [2:0] PF3_BAR3_CONTROL = 3'h0;
+ parameter [5:0] PF3_BAR4_APERTURE_SIZE = 6'h03;
+ parameter [2:0] PF3_BAR4_CONTROL = 3'h4;
+ parameter [4:0] PF3_BAR5_APERTURE_SIZE = 5'h03;
+ parameter [2:0] PF3_BAR5_CONTROL = 3'h0;
+ parameter [7:0] PF3_CAPABILITY_POINTER = 8'h80;
+ parameter [23:0] PF3_CLASS_CODE = 24'h000000;
+ parameter [2:0] PF3_DEV_CAP_MAX_PAYLOAD_SIZE = 3'h3;
+ parameter [11:0] PF3_DSN_CAP_NEXTPTR = 12'h10C;
+ parameter [4:0] PF3_EXPANSION_ROM_APERTURE_SIZE = 5'h03;
+ parameter PF3_EXPANSION_ROM_ENABLE = "FALSE";
+ parameter [2:0] PF3_INTERRUPT_PIN = 3'h1;
+ parameter [7:0] PF3_MSIX_CAP_NEXTPTR = 8'h00;
+ parameter integer PF3_MSIX_CAP_PBA_BIR = 0;
+ parameter [28:0] PF3_MSIX_CAP_PBA_OFFSET = 29'h00000050;
+ parameter integer PF3_MSIX_CAP_TABLE_BIR = 0;
+ parameter [28:0] PF3_MSIX_CAP_TABLE_OFFSET = 29'h00000040;
+ parameter [10:0] PF3_MSIX_CAP_TABLE_SIZE = 11'h000;
+ parameter integer PF3_MSI_CAP_MULTIMSGCAP = 0;
+ parameter [7:0] PF3_MSI_CAP_NEXTPTR = 8'h00;
+ parameter PF3_MSI_CAP_PERVECMASKCAP = "FALSE";
+ parameter [7:0] PF3_PCIE_CAP_NEXTPTR = 8'h00;
+ parameter [7:0] PF3_PM_CAP_NEXTPTR = 8'h00;
+ parameter [11:0] PF3_PRI_CAP_NEXTPTR = 12'h000;
+ parameter PF3_PRI_CAP_ON = "FALSE";
+ parameter [31:0] PF3_PRI_OST_PR_CAPACITY = 32'h00000000;
+ parameter PF3_SRIOV_ARI_CAPBL_HIER_PRESERVED = "FALSE";
+ parameter [5:0] PF3_SRIOV_BAR0_APERTURE_SIZE = 6'h03;
+ parameter [2:0] PF3_SRIOV_BAR0_CONTROL = 3'h4;
+ parameter [4:0] PF3_SRIOV_BAR1_APERTURE_SIZE = 5'h00;
+ parameter [2:0] PF3_SRIOV_BAR1_CONTROL = 3'h0;
+ parameter [5:0] PF3_SRIOV_BAR2_APERTURE_SIZE = 6'h03;
+ parameter [2:0] PF3_SRIOV_BAR2_CONTROL = 3'h4;
+ parameter [4:0] PF3_SRIOV_BAR3_APERTURE_SIZE = 5'h03;
+ parameter [2:0] PF3_SRIOV_BAR3_CONTROL = 3'h0;
+ parameter [5:0] PF3_SRIOV_BAR4_APERTURE_SIZE = 6'h03;
+ parameter [2:0] PF3_SRIOV_BAR4_CONTROL = 3'h4;
+ parameter [4:0] PF3_SRIOV_BAR5_APERTURE_SIZE = 5'h03;
+ parameter [2:0] PF3_SRIOV_BAR5_CONTROL = 3'h0;
+ parameter [15:0] PF3_SRIOV_CAP_INITIAL_VF = 16'h0000;
+ parameter [11:0] PF3_SRIOV_CAP_NEXTPTR = 12'h000;
+ parameter [15:0] PF3_SRIOV_CAP_TOTAL_VF = 16'h0000;
+ parameter [3:0] PF3_SRIOV_CAP_VER = 4'h1;
+ parameter [15:0] PF3_SRIOV_FIRST_VF_OFFSET = 16'h0000;
+ parameter [15:0] PF3_SRIOV_FUNC_DEP_LINK = 16'h0000;
+ parameter [31:0] PF3_SRIOV_SUPPORTED_PAGE_SIZE = 32'h00000000;
+ parameter [15:0] PF3_SRIOV_VF_DEVICE_ID = 16'h0000;
+ parameter [11:0] PF3_TPHR_CAP_NEXTPTR = 12'h000;
+ parameter [2:0] PF3_TPHR_CAP_ST_MODE_SEL = 3'h0;
+ parameter PL_CFG_STATE_ROBUSTNESS_ENABLE = "TRUE";
+ parameter PL_CTRL_SKP_GEN_ENABLE = "FALSE";
+ parameter PL_CTRL_SKP_PARITY_AND_CRC_CHECK_DISABLE = "TRUE";
+ parameter PL_DEEMPH_SOURCE_SELECT = "TRUE";
+ parameter PL_DESKEW_ON_SKIP_IN_GEN12 = "FALSE";
+ parameter PL_DISABLE_AUTO_EQ_SPEED_CHANGE_TO_GEN3 = "FALSE";
+ parameter PL_DISABLE_AUTO_EQ_SPEED_CHANGE_TO_GEN4 = "FALSE";
+ parameter PL_DISABLE_AUTO_SPEED_CHANGE_TO_GEN2 = "FALSE";
+ parameter PL_DISABLE_DC_BALANCE = "FALSE";
+ parameter PL_DISABLE_EI_INFER_IN_L0 = "FALSE";
+ parameter PL_DISABLE_LANE_REVERSAL = "FALSE";
+ parameter [1:0] PL_DISABLE_LFSR_UPDATE_ON_SKP = 2'h0;
+ parameter PL_DISABLE_RETRAIN_ON_EB_ERROR = "FALSE";
+ parameter PL_DISABLE_RETRAIN_ON_FRAMING_ERROR = "FALSE";
+ parameter [15:0] PL_DISABLE_RETRAIN_ON_SPECIFIC_FRAMING_ERROR = 16'h0000;
+ parameter PL_DISABLE_UPCONFIG_CAPABLE = "FALSE";
+ parameter [1:0] PL_EQ_ADAPT_DISABLE_COEFF_CHECK = 2'h0;
+ parameter [1:0] PL_EQ_ADAPT_DISABLE_PRESET_CHECK = 2'h0;
+ parameter [4:0] PL_EQ_ADAPT_ITER_COUNT = 5'h02;
+ parameter [1:0] PL_EQ_ADAPT_REJECT_RETRY_COUNT = 2'h1;
+ parameter [1:0] PL_EQ_BYPASS_PHASE23 = 2'h0;
+ parameter [5:0] PL_EQ_DEFAULT_RX_PRESET_HINT = 6'h33;
+ parameter [7:0] PL_EQ_DEFAULT_TX_PRESET = 8'h44;
+ parameter PL_EQ_DISABLE_MISMATCH_CHECK = "TRUE";
+ parameter [1:0] PL_EQ_RX_ADAPT_EQ_PHASE0 = 2'h0;
+ parameter [1:0] PL_EQ_RX_ADAPT_EQ_PHASE1 = 2'h0;
+ parameter PL_EQ_SHORT_ADAPT_PHASE = "FALSE";
+ parameter PL_EQ_TX_8G_EQ_TS2_ENABLE = "FALSE";
+ parameter PL_EXIT_LOOPBACK_ON_EI_ENTRY = "TRUE";
+ parameter PL_INFER_EI_DISABLE_LPBK_ACTIVE = "TRUE";
+ parameter PL_INFER_EI_DISABLE_REC_RC = "FALSE";
+ parameter PL_INFER_EI_DISABLE_REC_SPD = "FALSE";
+ parameter [31:0] PL_LANE0_EQ_CONTROL = 32'h00003F00;
+ parameter [31:0] PL_LANE10_EQ_CONTROL = 32'h00003F00;
+ parameter [31:0] PL_LANE11_EQ_CONTROL = 32'h00003F00;
+ parameter [31:0] PL_LANE12_EQ_CONTROL = 32'h00003F00;
+ parameter [31:0] PL_LANE13_EQ_CONTROL = 32'h00003F00;
+ parameter [31:0] PL_LANE14_EQ_CONTROL = 32'h00003F00;
+ parameter [31:0] PL_LANE15_EQ_CONTROL = 32'h00003F00;
+ parameter [31:0] PL_LANE1_EQ_CONTROL = 32'h00003F00;
+ parameter [31:0] PL_LANE2_EQ_CONTROL = 32'h00003F00;
+ parameter [31:0] PL_LANE3_EQ_CONTROL = 32'h00003F00;
+ parameter [31:0] PL_LANE4_EQ_CONTROL = 32'h00003F00;
+ parameter [31:0] PL_LANE5_EQ_CONTROL = 32'h00003F00;
+ parameter [31:0] PL_LANE6_EQ_CONTROL = 32'h00003F00;
+ parameter [31:0] PL_LANE7_EQ_CONTROL = 32'h00003F00;
+ parameter [31:0] PL_LANE8_EQ_CONTROL = 32'h00003F00;
+ parameter [31:0] PL_LANE9_EQ_CONTROL = 32'h00003F00;
+ parameter [3:0] PL_LINK_CAP_MAX_LINK_SPEED = 4'h4;
+ parameter [4:0] PL_LINK_CAP_MAX_LINK_WIDTH = 5'h08;
+ parameter integer PL_N_FTS = 255;
+ parameter PL_QUIESCE_GUARANTEE_DISABLE = "FALSE";
+ parameter PL_REDO_EQ_SOURCE_SELECT = "TRUE";
+ parameter [7:0] PL_REPORT_ALL_PHY_ERRORS = 8'h00;
+ parameter [1:0] PL_RX_ADAPT_TIMER_CLWS_CLOBBER_TX_TS = 2'h0;
+ parameter [3:0] PL_RX_ADAPT_TIMER_CLWS_GEN3 = 4'h0;
+ parameter [3:0] PL_RX_ADAPT_TIMER_CLWS_GEN4 = 4'h0;
+ parameter [1:0] PL_RX_ADAPT_TIMER_RRL_CLOBBER_TX_TS = 2'h0;
+ parameter [3:0] PL_RX_ADAPT_TIMER_RRL_GEN3 = 4'h0;
+ parameter [3:0] PL_RX_ADAPT_TIMER_RRL_GEN4 = 4'h0;
+ parameter [1:0] PL_RX_L0S_EXIT_TO_RECOVERY = 2'h0;
+ parameter [1:0] PL_SIM_FAST_LINK_TRAINING = 2'h0;
+ parameter PL_SRIS_ENABLE = "FALSE";
+ parameter [6:0] PL_SRIS_SKPOS_GEN_SPD_VEC = 7'h00;
+ parameter [6:0] PL_SRIS_SKPOS_REC_SPD_VEC = 7'h00;
+ parameter PL_UPSTREAM_FACING = "TRUE";
+ parameter [15:0] PL_USER_SPARE = 16'h0000;
+ parameter [15:0] PL_USER_SPARE2 = 16'h0000;
+ parameter [15:0] PM_ASPML0S_TIMEOUT = 16'h1500;
+ parameter [19:0] PM_ASPML1_ENTRY_DELAY = 20'h003E8;
+ parameter PM_ENABLE_L23_ENTRY = "FALSE";
+ parameter PM_ENABLE_SLOT_POWER_CAPTURE = "TRUE";
+ parameter [31:0] PM_L1_REENTRY_DELAY = 32'h00000100;
+ parameter [19:0] PM_PME_SERVICE_TIMEOUT_DELAY = 20'h00000;
+ parameter [15:0] PM_PME_TURNOFF_ACK_DELAY = 16'h0100;
+ parameter SIM_DEVICE = "ULTRASCALE_PLUS";
+ parameter [31:0] SIM_JTAG_IDCODE = 32'h00000000;
+ parameter SIM_VERSION = "1.0";
+ parameter SPARE_BIT0 = "FALSE";
+ parameter integer SPARE_BIT1 = 0;
+ parameter integer SPARE_BIT2 = 0;
+ parameter SPARE_BIT3 = "FALSE";
+ parameter integer SPARE_BIT4 = 0;
+ parameter integer SPARE_BIT5 = 0;
+ parameter integer SPARE_BIT6 = 0;
+ parameter integer SPARE_BIT7 = 0;
+ parameter integer SPARE_BIT8 = 0;
+ parameter [7:0] SPARE_BYTE0 = 8'h00;
+ parameter [7:0] SPARE_BYTE1 = 8'h00;
+ parameter [7:0] SPARE_BYTE2 = 8'h00;
+ parameter [7:0] SPARE_BYTE3 = 8'h00;
+ parameter [31:0] SPARE_WORD0 = 32'h00000000;
+ parameter [31:0] SPARE_WORD1 = 32'h00000000;
+ parameter [31:0] SPARE_WORD2 = 32'h00000000;
+ parameter [31:0] SPARE_WORD3 = 32'h00000000;
+ parameter [3:0] SRIOV_CAP_ENABLE = 4'h0;
+ parameter TL2CFG_IF_PARITY_CHK = "TRUE";
+ parameter [1:0] TL_COMPLETION_RAM_NUM_TLPS = 2'h0;
+ parameter [1:0] TL_COMPLETION_RAM_SIZE = 2'h1;
+ parameter [11:0] TL_CREDITS_CD = 12'h000;
+ parameter [11:0] TL_CREDITS_CD_VC1 = 12'h000;
+ parameter [7:0] TL_CREDITS_CH = 8'h00;
+ parameter [7:0] TL_CREDITS_CH_VC1 = 8'h00;
+ parameter [11:0] TL_CREDITS_NPD = 12'h004;
+ parameter [11:0] TL_CREDITS_NPD_VC1 = 12'h000;
+ parameter [7:0] TL_CREDITS_NPH = 8'h20;
+ parameter [7:0] TL_CREDITS_NPH_VC1 = 8'h01;
+ parameter [11:0] TL_CREDITS_PD = 12'h0E0;
+ parameter [11:0] TL_CREDITS_PD_VC1 = 12'h3E0;
+ parameter [7:0] TL_CREDITS_PH = 8'h20;
+ parameter [7:0] TL_CREDITS_PH_VC1 = 8'h20;
+ parameter [4:0] TL_FC_UPDATE_MIN_INTERVAL_TIME = 5'h02;
+ parameter [4:0] TL_FC_UPDATE_MIN_INTERVAL_TIME_VC1 = 5'h02;
+ parameter [4:0] TL_FC_UPDATE_MIN_INTERVAL_TLP_COUNT = 5'h08;
+ parameter [4:0] TL_FC_UPDATE_MIN_INTERVAL_TLP_COUNT_VC1 = 5'h08;
+ parameter TL_FEATURE_ENABLE_FC_SCALING = "FALSE";
+ parameter [1:0] TL_PF_ENABLE_REG = 2'h0;
+ parameter [0:0] TL_POSTED_RAM_SIZE = 1'h0;
+ parameter TL_RX_COMPLETION_FROM_RAM_READ_PIPELINE = "FALSE";
+ parameter TL_RX_COMPLETION_TO_RAM_READ_PIPELINE = "FALSE";
+ parameter TL_RX_COMPLETION_TO_RAM_WRITE_PIPELINE = "FALSE";
+ parameter TL_RX_POSTED_FROM_RAM_READ_PIPELINE = "FALSE";
+ parameter TL_RX_POSTED_TO_RAM_READ_PIPELINE = "FALSE";
+ parameter TL_RX_POSTED_TO_RAM_WRITE_PIPELINE = "FALSE";
+ parameter TL_TX_MUX_STRICT_PRIORITY = "TRUE";
+ parameter TL_TX_TLP_STRADDLE_ENABLE = "FALSE";
+ parameter TL_TX_TLP_TERMINATE_PARITY = "FALSE";
+ parameter [15:0] TL_USER_SPARE = 16'h0000;
+ parameter TPH_FROM_RAM_PIPELINE = "FALSE";
+ parameter TPH_TO_RAM_PIPELINE = "FALSE";
+ parameter [7:0] VF0_CAPABILITY_POINTER = 8'h80;
+ parameter [11:0] VFG0_ARI_CAP_NEXTPTR = 12'h000;
+ parameter [4:0] VFG0_ATS_CAP_INV_QUEUE_DEPTH = 5'h00;
+ parameter [11:0] VFG0_ATS_CAP_NEXTPTR = 12'h000;
+ parameter VFG0_ATS_CAP_ON = "FALSE";
+ parameter [7:0] VFG0_MSIX_CAP_NEXTPTR = 8'h00;
+ parameter integer VFG0_MSIX_CAP_PBA_BIR = 0;
+ parameter [28:0] VFG0_MSIX_CAP_PBA_OFFSET = 29'h00000050;
+ parameter integer VFG0_MSIX_CAP_TABLE_BIR = 0;
+ parameter [28:0] VFG0_MSIX_CAP_TABLE_OFFSET = 29'h00000040;
+ parameter [10:0] VFG0_MSIX_CAP_TABLE_SIZE = 11'h000;
+ parameter [7:0] VFG0_PCIE_CAP_NEXTPTR = 8'h00;
+ parameter [11:0] VFG0_TPHR_CAP_NEXTPTR = 12'h000;
+ parameter [2:0] VFG0_TPHR_CAP_ST_MODE_SEL = 3'h0;
+ parameter [11:0] VFG1_ARI_CAP_NEXTPTR = 12'h000;
+ parameter [4:0] VFG1_ATS_CAP_INV_QUEUE_DEPTH = 5'h00;
+ parameter [11:0] VFG1_ATS_CAP_NEXTPTR = 12'h000;
+ parameter VFG1_ATS_CAP_ON = "FALSE";
+ parameter [7:0] VFG1_MSIX_CAP_NEXTPTR = 8'h00;
+ parameter integer VFG1_MSIX_CAP_PBA_BIR = 0;
+ parameter [28:0] VFG1_MSIX_CAP_PBA_OFFSET = 29'h00000050;
+ parameter integer VFG1_MSIX_CAP_TABLE_BIR = 0;
+ parameter [28:0] VFG1_MSIX_CAP_TABLE_OFFSET = 29'h00000040;
+ parameter [10:0] VFG1_MSIX_CAP_TABLE_SIZE = 11'h000;
+ parameter [7:0] VFG1_PCIE_CAP_NEXTPTR = 8'h00;
+ parameter [11:0] VFG1_TPHR_CAP_NEXTPTR = 12'h000;
+ parameter [2:0] VFG1_TPHR_CAP_ST_MODE_SEL = 3'h0;
+ parameter [11:0] VFG2_ARI_CAP_NEXTPTR = 12'h000;
+ parameter [4:0] VFG2_ATS_CAP_INV_QUEUE_DEPTH = 5'h00;
+ parameter [11:0] VFG2_ATS_CAP_NEXTPTR = 12'h000;
+ parameter VFG2_ATS_CAP_ON = "FALSE";
+ parameter [7:0] VFG2_MSIX_CAP_NEXTPTR = 8'h00;
+ parameter integer VFG2_MSIX_CAP_PBA_BIR = 0;
+ parameter [28:0] VFG2_MSIX_CAP_PBA_OFFSET = 29'h00000050;
+ parameter integer VFG2_MSIX_CAP_TABLE_BIR = 0;
+ parameter [28:0] VFG2_MSIX_CAP_TABLE_OFFSET = 29'h00000040;
+ parameter [10:0] VFG2_MSIX_CAP_TABLE_SIZE = 11'h000;
+ parameter [7:0] VFG2_PCIE_CAP_NEXTPTR = 8'h00;
+ parameter [11:0] VFG2_TPHR_CAP_NEXTPTR = 12'h000;
+ parameter [2:0] VFG2_TPHR_CAP_ST_MODE_SEL = 3'h0;
+ parameter [11:0] VFG3_ARI_CAP_NEXTPTR = 12'h000;
+ parameter [4:0] VFG3_ATS_CAP_INV_QUEUE_DEPTH = 5'h00;
+ parameter [11:0] VFG3_ATS_CAP_NEXTPTR = 12'h000;
+ parameter VFG3_ATS_CAP_ON = "FALSE";
+ parameter [7:0] VFG3_MSIX_CAP_NEXTPTR = 8'h00;
+ parameter integer VFG3_MSIX_CAP_PBA_BIR = 0;
+ parameter [28:0] VFG3_MSIX_CAP_PBA_OFFSET = 29'h00000050;
+ parameter integer VFG3_MSIX_CAP_TABLE_BIR = 0;
+ parameter [28:0] VFG3_MSIX_CAP_TABLE_OFFSET = 29'h00000040;
+ parameter [10:0] VFG3_MSIX_CAP_TABLE_SIZE = 11'h000;
+ parameter [7:0] VFG3_PCIE_CAP_NEXTPTR = 8'h00;
+ parameter [11:0] VFG3_TPHR_CAP_NEXTPTR = 12'h000;
+ parameter [2:0] VFG3_TPHR_CAP_ST_MODE_SEL = 3'h0;
+ output [7:0] AXIUSEROUT;
+ output CCIXTXCREDIT;
+ output [7:0] CFGBUSNUMBER;
+ output [1:0] CFGCURRENTSPEED;
+ output CFGERRCOROUT;
+ output CFGERRFATALOUT;
+ output CFGERRNONFATALOUT;
+ output [7:0] CFGEXTFUNCTIONNUMBER;
+ output CFGEXTREADRECEIVED;
+ output [9:0] CFGEXTREGISTERNUMBER;
+ output [3:0] CFGEXTWRITEBYTEENABLE;
+ output [31:0] CFGEXTWRITEDATA;
+ output CFGEXTWRITERECEIVED;
+ output [11:0] CFGFCCPLD;
+ output [7:0] CFGFCCPLH;
+ output [11:0] CFGFCNPD;
+ output [7:0] CFGFCNPH;
+ output [11:0] CFGFCPD;
+ output [7:0] CFGFCPH;
+ output [3:0] CFGFLRINPROCESS;
+ output [11:0] CFGFUNCTIONPOWERSTATE;
+ output [15:0] CFGFUNCTIONSTATUS;
+ output CFGHOTRESETOUT;
+ output [31:0] CFGINTERRUPTMSIDATA;
+ output [3:0] CFGINTERRUPTMSIENABLE;
+ output CFGINTERRUPTMSIFAIL;
+ output CFGINTERRUPTMSIMASKUPDATE;
+ output [11:0] CFGINTERRUPTMSIMMENABLE;
+ output CFGINTERRUPTMSISENT;
+ output [3:0] CFGINTERRUPTMSIXENABLE;
+ output [3:0] CFGINTERRUPTMSIXMASK;
+ output CFGINTERRUPTMSIXVECPENDINGSTATUS;
+ output CFGINTERRUPTSENT;
+ output [1:0] CFGLINKPOWERSTATE;
+ output [4:0] CFGLOCALERROROUT;
+ output CFGLOCALERRORVALID;
+ output CFGLTRENABLE;
+ output [5:0] CFGLTSSMSTATE;
+ output [1:0] CFGMAXPAYLOAD;
+ output [2:0] CFGMAXREADREQ;
+ output [31:0] CFGMGMTREADDATA;
+ output CFGMGMTREADWRITEDONE;
+ output CFGMSGRECEIVED;
+ output [7:0] CFGMSGRECEIVEDDATA;
+ output [4:0] CFGMSGRECEIVEDTYPE;
+ output CFGMSGTRANSMITDONE;
+ output [12:0] CFGMSIXRAMADDRESS;
+ output CFGMSIXRAMREADENABLE;
+ output [3:0] CFGMSIXRAMWRITEBYTEENABLE;
+ output [35:0] CFGMSIXRAMWRITEDATA;
+ output [2:0] CFGNEGOTIATEDWIDTH;
+ output [1:0] CFGOBFFENABLE;
+ output CFGPHYLINKDOWN;
+ output [1:0] CFGPHYLINKSTATUS;
+ output CFGPLSTATUSCHANGE;
+ output CFGPOWERSTATECHANGEINTERRUPT;
+ output [3:0] CFGRCBSTATUS;
+ output [1:0] CFGRXPMSTATE;
+ output [11:0] CFGTPHRAMADDRESS;
+ output CFGTPHRAMREADENABLE;
+ output [3:0] CFGTPHRAMWRITEBYTEENABLE;
+ output [35:0] CFGTPHRAMWRITEDATA;
+ output [3:0] CFGTPHREQUESTERENABLE;
+ output [11:0] CFGTPHSTMODE;
+ output [1:0] CFGTXPMSTATE;
+ output CFGVC1ENABLE;
+ output CFGVC1NEGOTIATIONPENDING;
+ output CONFMCAPDESIGNSWITCH;
+ output CONFMCAPEOS;
+ output CONFMCAPINUSEBYPCIE;
+ output CONFREQREADY;
+ output [31:0] CONFRESPRDATA;
+ output CONFRESPVALID;
+ output [129:0] DBGCCIXOUT;
+ output [31:0] DBGCTRL0OUT;
+ output [31:0] DBGCTRL1OUT;
+ output [255:0] DBGDATA0OUT;
+ output [255:0] DBGDATA1OUT;
+ output [15:0] DRPDO;
+ output DRPRDY;
+ output [45:0] MAXISCCIXRXTUSER;
+ output MAXISCCIXRXTVALID;
+ output [255:0] MAXISCQTDATA;
+ output [7:0] MAXISCQTKEEP;
+ output MAXISCQTLAST;
+ output [87:0] MAXISCQTUSER;
+ output MAXISCQTVALID;
+ output [255:0] MAXISRCTDATA;
+ output [7:0] MAXISRCTKEEP;
+ output MAXISRCTLAST;
+ output [74:0] MAXISRCTUSER;
+ output MAXISRCTVALID;
+ output [8:0] MIREPLAYRAMADDRESS0;
+ output [8:0] MIREPLAYRAMADDRESS1;
+ output MIREPLAYRAMREADENABLE0;
+ output MIREPLAYRAMREADENABLE1;
+ output [127:0] MIREPLAYRAMWRITEDATA0;
+ output [127:0] MIREPLAYRAMWRITEDATA1;
+ output MIREPLAYRAMWRITEENABLE0;
+ output MIREPLAYRAMWRITEENABLE1;
+ output [8:0] MIRXCOMPLETIONRAMREADADDRESS0;
+ output [8:0] MIRXCOMPLETIONRAMREADADDRESS1;
+ output [1:0] MIRXCOMPLETIONRAMREADENABLE0;
+ output [1:0] MIRXCOMPLETIONRAMREADENABLE1;
+ output [8:0] MIRXCOMPLETIONRAMWRITEADDRESS0;
+ output [8:0] MIRXCOMPLETIONRAMWRITEADDRESS1;
+ output [143:0] MIRXCOMPLETIONRAMWRITEDATA0;
+ output [143:0] MIRXCOMPLETIONRAMWRITEDATA1;
+ output [1:0] MIRXCOMPLETIONRAMWRITEENABLE0;
+ output [1:0] MIRXCOMPLETIONRAMWRITEENABLE1;
+ output [8:0] MIRXPOSTEDREQUESTRAMREADADDRESS0;
+ output [8:0] MIRXPOSTEDREQUESTRAMREADADDRESS1;
+ output MIRXPOSTEDREQUESTRAMREADENABLE0;
+ output MIRXPOSTEDREQUESTRAMREADENABLE1;
+ output [8:0] MIRXPOSTEDREQUESTRAMWRITEADDRESS0;
+ output [8:0] MIRXPOSTEDREQUESTRAMWRITEADDRESS1;
+ output [143:0] MIRXPOSTEDREQUESTRAMWRITEDATA0;
+ output [143:0] MIRXPOSTEDREQUESTRAMWRITEDATA1;
+ output MIRXPOSTEDREQUESTRAMWRITEENABLE0;
+ output MIRXPOSTEDREQUESTRAMWRITEENABLE1;
+ output [5:0] PCIECQNPREQCOUNT;
+ output PCIEPERST0B;
+ output PCIEPERST1B;
+ output [5:0] PCIERQSEQNUM0;
+ output [5:0] PCIERQSEQNUM1;
+ output PCIERQSEQNUMVLD0;
+ output PCIERQSEQNUMVLD1;
+ output [7:0] PCIERQTAG0;
+ output [7:0] PCIERQTAG1;
+ output [3:0] PCIERQTAGAV;
+ output PCIERQTAGVLD0;
+ output PCIERQTAGVLD1;
+ output [3:0] PCIETFCNPDAV;
+ output [3:0] PCIETFCNPHAV;
+ output [1:0] PIPERX00EQCONTROL;
+ output PIPERX00POLARITY;
+ output [1:0] PIPERX01EQCONTROL;
+ output PIPERX01POLARITY;
+ output [1:0] PIPERX02EQCONTROL;
+ output PIPERX02POLARITY;
+ output [1:0] PIPERX03EQCONTROL;
+ output PIPERX03POLARITY;
+ output [1:0] PIPERX04EQCONTROL;
+ output PIPERX04POLARITY;
+ output [1:0] PIPERX05EQCONTROL;
+ output PIPERX05POLARITY;
+ output [1:0] PIPERX06EQCONTROL;
+ output PIPERX06POLARITY;
+ output [1:0] PIPERX07EQCONTROL;
+ output PIPERX07POLARITY;
+ output [1:0] PIPERX08EQCONTROL;
+ output PIPERX08POLARITY;
+ output [1:0] PIPERX09EQCONTROL;
+ output PIPERX09POLARITY;
+ output [1:0] PIPERX10EQCONTROL;
+ output PIPERX10POLARITY;
+ output [1:0] PIPERX11EQCONTROL;
+ output PIPERX11POLARITY;
+ output [1:0] PIPERX12EQCONTROL;
+ output PIPERX12POLARITY;
+ output [1:0] PIPERX13EQCONTROL;
+ output PIPERX13POLARITY;
+ output [1:0] PIPERX14EQCONTROL;
+ output PIPERX14POLARITY;
+ output [1:0] PIPERX15EQCONTROL;
+ output PIPERX15POLARITY;
+ output [5:0] PIPERXEQLPLFFS;
+ output [3:0] PIPERXEQLPTXPRESET;
+ output [1:0] PIPETX00CHARISK;
+ output PIPETX00COMPLIANCE;
+ output [31:0] PIPETX00DATA;
+ output PIPETX00DATAVALID;
+ output PIPETX00ELECIDLE;
+ output [1:0] PIPETX00EQCONTROL;
+ output [5:0] PIPETX00EQDEEMPH;
+ output [1:0] PIPETX00POWERDOWN;
+ output PIPETX00STARTBLOCK;
+ output [1:0] PIPETX00SYNCHEADER;
+ output [1:0] PIPETX01CHARISK;
+ output PIPETX01COMPLIANCE;
+ output [31:0] PIPETX01DATA;
+ output PIPETX01DATAVALID;
+ output PIPETX01ELECIDLE;
+ output [1:0] PIPETX01EQCONTROL;
+ output [5:0] PIPETX01EQDEEMPH;
+ output [1:0] PIPETX01POWERDOWN;
+ output PIPETX01STARTBLOCK;
+ output [1:0] PIPETX01SYNCHEADER;
+ output [1:0] PIPETX02CHARISK;
+ output PIPETX02COMPLIANCE;
+ output [31:0] PIPETX02DATA;
+ output PIPETX02DATAVALID;
+ output PIPETX02ELECIDLE;
+ output [1:0] PIPETX02EQCONTROL;
+ output [5:0] PIPETX02EQDEEMPH;
+ output [1:0] PIPETX02POWERDOWN;
+ output PIPETX02STARTBLOCK;
+ output [1:0] PIPETX02SYNCHEADER;
+ output [1:0] PIPETX03CHARISK;
+ output PIPETX03COMPLIANCE;
+ output [31:0] PIPETX03DATA;
+ output PIPETX03DATAVALID;
+ output PIPETX03ELECIDLE;
+ output [1:0] PIPETX03EQCONTROL;
+ output [5:0] PIPETX03EQDEEMPH;
+ output [1:0] PIPETX03POWERDOWN;
+ output PIPETX03STARTBLOCK;
+ output [1:0] PIPETX03SYNCHEADER;
+ output [1:0] PIPETX04CHARISK;
+ output PIPETX04COMPLIANCE;
+ output [31:0] PIPETX04DATA;
+ output PIPETX04DATAVALID;
+ output PIPETX04ELECIDLE;
+ output [1:0] PIPETX04EQCONTROL;
+ output [5:0] PIPETX04EQDEEMPH;
+ output [1:0] PIPETX04POWERDOWN;
+ output PIPETX04STARTBLOCK;
+ output [1:0] PIPETX04SYNCHEADER;
+ output [1:0] PIPETX05CHARISK;
+ output PIPETX05COMPLIANCE;
+ output [31:0] PIPETX05DATA;
+ output PIPETX05DATAVALID;
+ output PIPETX05ELECIDLE;
+ output [1:0] PIPETX05EQCONTROL;
+ output [5:0] PIPETX05EQDEEMPH;
+ output [1:0] PIPETX05POWERDOWN;
+ output PIPETX05STARTBLOCK;
+ output [1:0] PIPETX05SYNCHEADER;
+ output [1:0] PIPETX06CHARISK;
+ output PIPETX06COMPLIANCE;
+ output [31:0] PIPETX06DATA;
+ output PIPETX06DATAVALID;
+ output PIPETX06ELECIDLE;
+ output [1:0] PIPETX06EQCONTROL;
+ output [5:0] PIPETX06EQDEEMPH;
+ output [1:0] PIPETX06POWERDOWN;
+ output PIPETX06STARTBLOCK;
+ output [1:0] PIPETX06SYNCHEADER;
+ output [1:0] PIPETX07CHARISK;
+ output PIPETX07COMPLIANCE;
+ output [31:0] PIPETX07DATA;
+ output PIPETX07DATAVALID;
+ output PIPETX07ELECIDLE;
+ output [1:0] PIPETX07EQCONTROL;
+ output [5:0] PIPETX07EQDEEMPH;
+ output [1:0] PIPETX07POWERDOWN;
+ output PIPETX07STARTBLOCK;
+ output [1:0] PIPETX07SYNCHEADER;
+ output [1:0] PIPETX08CHARISK;
+ output PIPETX08COMPLIANCE;
+ output [31:0] PIPETX08DATA;
+ output PIPETX08DATAVALID;
+ output PIPETX08ELECIDLE;
+ output [1:0] PIPETX08EQCONTROL;
+ output [5:0] PIPETX08EQDEEMPH;
+ output [1:0] PIPETX08POWERDOWN;
+ output PIPETX08STARTBLOCK;
+ output [1:0] PIPETX08SYNCHEADER;
+ output [1:0] PIPETX09CHARISK;
+ output PIPETX09COMPLIANCE;
+ output [31:0] PIPETX09DATA;
+ output PIPETX09DATAVALID;
+ output PIPETX09ELECIDLE;
+ output [1:0] PIPETX09EQCONTROL;
+ output [5:0] PIPETX09EQDEEMPH;
+ output [1:0] PIPETX09POWERDOWN;
+ output PIPETX09STARTBLOCK;
+ output [1:0] PIPETX09SYNCHEADER;
+ output [1:0] PIPETX10CHARISK;
+ output PIPETX10COMPLIANCE;
+ output [31:0] PIPETX10DATA;
+ output PIPETX10DATAVALID;
+ output PIPETX10ELECIDLE;
+ output [1:0] PIPETX10EQCONTROL;
+ output [5:0] PIPETX10EQDEEMPH;
+ output [1:0] PIPETX10POWERDOWN;
+ output PIPETX10STARTBLOCK;
+ output [1:0] PIPETX10SYNCHEADER;
+ output [1:0] PIPETX11CHARISK;
+ output PIPETX11COMPLIANCE;
+ output [31:0] PIPETX11DATA;
+ output PIPETX11DATAVALID;
+ output PIPETX11ELECIDLE;
+ output [1:0] PIPETX11EQCONTROL;
+ output [5:0] PIPETX11EQDEEMPH;
+ output [1:0] PIPETX11POWERDOWN;
+ output PIPETX11STARTBLOCK;
+ output [1:0] PIPETX11SYNCHEADER;
+ output [1:0] PIPETX12CHARISK;
+ output PIPETX12COMPLIANCE;
+ output [31:0] PIPETX12DATA;
+ output PIPETX12DATAVALID;
+ output PIPETX12ELECIDLE;
+ output [1:0] PIPETX12EQCONTROL;
+ output [5:0] PIPETX12EQDEEMPH;
+ output [1:0] PIPETX12POWERDOWN;
+ output PIPETX12STARTBLOCK;
+ output [1:0] PIPETX12SYNCHEADER;
+ output [1:0] PIPETX13CHARISK;
+ output PIPETX13COMPLIANCE;
+ output [31:0] PIPETX13DATA;
+ output PIPETX13DATAVALID;
+ output PIPETX13ELECIDLE;
+ output [1:0] PIPETX13EQCONTROL;
+ output [5:0] PIPETX13EQDEEMPH;
+ output [1:0] PIPETX13POWERDOWN;
+ output PIPETX13STARTBLOCK;
+ output [1:0] PIPETX13SYNCHEADER;
+ output [1:0] PIPETX14CHARISK;
+ output PIPETX14COMPLIANCE;
+ output [31:0] PIPETX14DATA;
+ output PIPETX14DATAVALID;
+ output PIPETX14ELECIDLE;
+ output [1:0] PIPETX14EQCONTROL;
+ output [5:0] PIPETX14EQDEEMPH;
+ output [1:0] PIPETX14POWERDOWN;
+ output PIPETX14STARTBLOCK;
+ output [1:0] PIPETX14SYNCHEADER;
+ output [1:0] PIPETX15CHARISK;
+ output PIPETX15COMPLIANCE;
+ output [31:0] PIPETX15DATA;
+ output PIPETX15DATAVALID;
+ output PIPETX15ELECIDLE;
+ output [1:0] PIPETX15EQCONTROL;
+ output [5:0] PIPETX15EQDEEMPH;
+ output [1:0] PIPETX15POWERDOWN;
+ output PIPETX15STARTBLOCK;
+ output [1:0] PIPETX15SYNCHEADER;
+ output PIPETXDEEMPH;
+ output [2:0] PIPETXMARGIN;
+ output [1:0] PIPETXRATE;
+ output PIPETXRCVRDET;
+ output PIPETXRESET;
+ output PIPETXSWING;
+ output PLEQINPROGRESS;
+ output [1:0] PLEQPHASE;
+ output PLGEN34EQMISMATCH;
+ output [3:0] SAXISCCTREADY;
+ output [3:0] SAXISRQTREADY;
+ output [23:0] USERSPAREOUT;
+ input [7:0] AXIUSERIN;
+ input CCIXOPTIMIZEDTLPTXANDRXENABLE;
+ input CCIXRXCORRECTABLEERRORDETECTED;
+ input CCIXRXFIFOOVERFLOW;
+ input CCIXRXTLPFORWARDED0;
+ input CCIXRXTLPFORWARDED1;
+ input [5:0] CCIXRXTLPFORWARDEDLENGTH0;
+ input [5:0] CCIXRXTLPFORWARDEDLENGTH1;
+ input CCIXRXUNCORRECTABLEERRORDETECTED;
+ input CFGCONFIGSPACEENABLE;
+ input [15:0] CFGDEVIDPF0;
+ input [15:0] CFGDEVIDPF1;
+ input [15:0] CFGDEVIDPF2;
+ input [15:0] CFGDEVIDPF3;
+ input [7:0] CFGDSBUSNUMBER;
+ input [4:0] CFGDSDEVICENUMBER;
+ input [2:0] CFGDSFUNCTIONNUMBER;
+ input [63:0] CFGDSN;
+ input [7:0] CFGDSPORTNUMBER;
+ input CFGERRCORIN;
+ input CFGERRUNCORIN;
+ input [31:0] CFGEXTREADDATA;
+ input CFGEXTREADDATAVALID;
+ input [2:0] CFGFCSEL;
+ input CFGFCVCSEL;
+ input [3:0] CFGFLRDONE;
+ input CFGHOTRESETIN;
+ input [3:0] CFGINTERRUPTINT;
+ input [2:0] CFGINTERRUPTMSIATTR;
+ input [7:0] CFGINTERRUPTMSIFUNCTIONNUMBER;
+ input [31:0] CFGINTERRUPTMSIINT;
+ input [31:0] CFGINTERRUPTMSIPENDINGSTATUS;
+ input CFGINTERRUPTMSIPENDINGSTATUSDATAENABLE;
+ input [1:0] CFGINTERRUPTMSIPENDINGSTATUSFUNCTIONNUM;
+ input [1:0] CFGINTERRUPTMSISELECT;
+ input CFGINTERRUPTMSITPHPRESENT;
+ input [7:0] CFGINTERRUPTMSITPHSTTAG;
+ input [1:0] CFGINTERRUPTMSITPHTYPE;
+ input [63:0] CFGINTERRUPTMSIXADDRESS;
+ input [31:0] CFGINTERRUPTMSIXDATA;
+ input CFGINTERRUPTMSIXINT;
+ input [1:0] CFGINTERRUPTMSIXVECPENDING;
+ input [3:0] CFGINTERRUPTPENDING;
+ input CFGLINKTRAININGENABLE;
+ input [9:0] CFGMGMTADDR;
+ input [3:0] CFGMGMTBYTEENABLE;
+ input CFGMGMTDEBUGACCESS;
+ input [7:0] CFGMGMTFUNCTIONNUMBER;
+ input CFGMGMTREAD;
+ input CFGMGMTWRITE;
+ input [31:0] CFGMGMTWRITEDATA;
+ input CFGMSGTRANSMIT;
+ input [31:0] CFGMSGTRANSMITDATA;
+ input [2:0] CFGMSGTRANSMITTYPE;
+ input [35:0] CFGMSIXRAMREADDATA;
+ input CFGPMASPML1ENTRYREJECT;
+ input CFGPMASPMTXL0SENTRYDISABLE;
+ input CFGPOWERSTATECHANGEACK;
+ input CFGREQPMTRANSITIONL23READY;
+ input [7:0] CFGREVIDPF0;
+ input [7:0] CFGREVIDPF1;
+ input [7:0] CFGREVIDPF2;
+ input [7:0] CFGREVIDPF3;
+ input [15:0] CFGSUBSYSIDPF0;
+ input [15:0] CFGSUBSYSIDPF1;
+ input [15:0] CFGSUBSYSIDPF2;
+ input [15:0] CFGSUBSYSIDPF3;
+ input [15:0] CFGSUBSYSVENDID;
+ input [35:0] CFGTPHRAMREADDATA;
+ input [15:0] CFGVENDID;
+ input CFGVFFLRDONE;
+ input [7:0] CFGVFFLRFUNCNUM;
+ input CONFMCAPREQUESTBYCONF;
+ input [31:0] CONFREQDATA;
+ input [3:0] CONFREQREGNUM;
+ input [1:0] CONFREQTYPE;
+ input CONFREQVALID;
+ input CORECLK;
+ input CORECLKCCIX;
+ input CORECLKMIREPLAYRAM0;
+ input CORECLKMIREPLAYRAM1;
+ input CORECLKMIRXCOMPLETIONRAM0;
+ input CORECLKMIRXCOMPLETIONRAM1;
+ input CORECLKMIRXPOSTEDREQUESTRAM0;
+ input CORECLKMIRXPOSTEDREQUESTRAM1;
+ input [5:0] DBGSEL0;
+ input [5:0] DBGSEL1;
+ input [9:0] DRPADDR;
+ input DRPCLK;
+ input [15:0] DRPDI;
+ input DRPEN;
+ input DRPWE;
+ input [21:0] MAXISCQTREADY;
+ input [21:0] MAXISRCTREADY;
+ input MCAPCLK;
+ input MCAPPERST0B;
+ input MCAPPERST1B;
+ input MGMTRESETN;
+ input MGMTSTICKYRESETN;
+ input [5:0] MIREPLAYRAMERRCOR;
+ input [5:0] MIREPLAYRAMERRUNCOR;
+ input [127:0] MIREPLAYRAMREADDATA0;
+ input [127:0] MIREPLAYRAMREADDATA1;
+ input [11:0] MIRXCOMPLETIONRAMERRCOR;
+ input [11:0] MIRXCOMPLETIONRAMERRUNCOR;
+ input [143:0] MIRXCOMPLETIONRAMREADDATA0;
+ input [143:0] MIRXCOMPLETIONRAMREADDATA1;
+ input [5:0] MIRXPOSTEDREQUESTRAMERRCOR;
+ input [5:0] MIRXPOSTEDREQUESTRAMERRUNCOR;
+ input [143:0] MIRXPOSTEDREQUESTRAMREADDATA0;
+ input [143:0] MIRXPOSTEDREQUESTRAMREADDATA1;
+ input [1:0] PCIECOMPLDELIVERED;
+ input [7:0] PCIECOMPLDELIVEREDTAG0;
+ input [7:0] PCIECOMPLDELIVEREDTAG1;
+ input [1:0] PCIECQNPREQ;
+ input PCIECQNPUSERCREDITRCVD;
+ input PCIECQPIPELINEEMPTY;
+ input PCIEPOSTEDREQDELIVERED;
+ input PIPECLK;
+ input PIPECLKEN;
+ input [5:0] PIPEEQFS;
+ input [5:0] PIPEEQLF;
+ input PIPERESETN;
+ input [1:0] PIPERX00CHARISK;
+ input [31:0] PIPERX00DATA;
+ input PIPERX00DATAVALID;
+ input PIPERX00ELECIDLE;
+ input PIPERX00EQDONE;
+ input PIPERX00EQLPADAPTDONE;
+ input PIPERX00EQLPLFFSSEL;
+ input [17:0] PIPERX00EQLPNEWTXCOEFFORPRESET;
+ input PIPERX00PHYSTATUS;
+ input [1:0] PIPERX00STARTBLOCK;
+ input [2:0] PIPERX00STATUS;
+ input [1:0] PIPERX00SYNCHEADER;
+ input PIPERX00VALID;
+ input [1:0] PIPERX01CHARISK;
+ input [31:0] PIPERX01DATA;
+ input PIPERX01DATAVALID;
+ input PIPERX01ELECIDLE;
+ input PIPERX01EQDONE;
+ input PIPERX01EQLPADAPTDONE;
+ input PIPERX01EQLPLFFSSEL;
+ input [17:0] PIPERX01EQLPNEWTXCOEFFORPRESET;
+ input PIPERX01PHYSTATUS;
+ input [1:0] PIPERX01STARTBLOCK;
+ input [2:0] PIPERX01STATUS;
+ input [1:0] PIPERX01SYNCHEADER;
+ input PIPERX01VALID;
+ input [1:0] PIPERX02CHARISK;
+ input [31:0] PIPERX02DATA;
+ input PIPERX02DATAVALID;
+ input PIPERX02ELECIDLE;
+ input PIPERX02EQDONE;
+ input PIPERX02EQLPADAPTDONE;
+ input PIPERX02EQLPLFFSSEL;
+ input [17:0] PIPERX02EQLPNEWTXCOEFFORPRESET;
+ input PIPERX02PHYSTATUS;
+ input [1:0] PIPERX02STARTBLOCK;
+ input [2:0] PIPERX02STATUS;
+ input [1:0] PIPERX02SYNCHEADER;
+ input PIPERX02VALID;
+ input [1:0] PIPERX03CHARISK;
+ input [31:0] PIPERX03DATA;
+ input PIPERX03DATAVALID;
+ input PIPERX03ELECIDLE;
+ input PIPERX03EQDONE;
+ input PIPERX03EQLPADAPTDONE;
+ input PIPERX03EQLPLFFSSEL;
+ input [17:0] PIPERX03EQLPNEWTXCOEFFORPRESET;
+ input PIPERX03PHYSTATUS;
+ input [1:0] PIPERX03STARTBLOCK;
+ input [2:0] PIPERX03STATUS;
+ input [1:0] PIPERX03SYNCHEADER;
+ input PIPERX03VALID;
+ input [1:0] PIPERX04CHARISK;
+ input [31:0] PIPERX04DATA;
+ input PIPERX04DATAVALID;
+ input PIPERX04ELECIDLE;
+ input PIPERX04EQDONE;
+ input PIPERX04EQLPADAPTDONE;
+ input PIPERX04EQLPLFFSSEL;
+ input [17:0] PIPERX04EQLPNEWTXCOEFFORPRESET;
+ input PIPERX04PHYSTATUS;
+ input [1:0] PIPERX04STARTBLOCK;
+ input [2:0] PIPERX04STATUS;
+ input [1:0] PIPERX04SYNCHEADER;
+ input PIPERX04VALID;
+ input [1:0] PIPERX05CHARISK;
+ input [31:0] PIPERX05DATA;
+ input PIPERX05DATAVALID;
+ input PIPERX05ELECIDLE;
+ input PIPERX05EQDONE;
+ input PIPERX05EQLPADAPTDONE;
+ input PIPERX05EQLPLFFSSEL;
+ input [17:0] PIPERX05EQLPNEWTXCOEFFORPRESET;
+ input PIPERX05PHYSTATUS;
+ input [1:0] PIPERX05STARTBLOCK;
+ input [2:0] PIPERX05STATUS;
+ input [1:0] PIPERX05SYNCHEADER;
+ input PIPERX05VALID;
+ input [1:0] PIPERX06CHARISK;
+ input [31:0] PIPERX06DATA;
+ input PIPERX06DATAVALID;
+ input PIPERX06ELECIDLE;
+ input PIPERX06EQDONE;
+ input PIPERX06EQLPADAPTDONE;
+ input PIPERX06EQLPLFFSSEL;
+ input [17:0] PIPERX06EQLPNEWTXCOEFFORPRESET;
+ input PIPERX06PHYSTATUS;
+ input [1:0] PIPERX06STARTBLOCK;
+ input [2:0] PIPERX06STATUS;
+ input [1:0] PIPERX06SYNCHEADER;
+ input PIPERX06VALID;
+ input [1:0] PIPERX07CHARISK;
+ input [31:0] PIPERX07DATA;
+ input PIPERX07DATAVALID;
+ input PIPERX07ELECIDLE;
+ input PIPERX07EQDONE;
+ input PIPERX07EQLPADAPTDONE;
+ input PIPERX07EQLPLFFSSEL;
+ input [17:0] PIPERX07EQLPNEWTXCOEFFORPRESET;
+ input PIPERX07PHYSTATUS;
+ input [1:0] PIPERX07STARTBLOCK;
+ input [2:0] PIPERX07STATUS;
+ input [1:0] PIPERX07SYNCHEADER;
+ input PIPERX07VALID;
+ input [1:0] PIPERX08CHARISK;
+ input [31:0] PIPERX08DATA;
+ input PIPERX08DATAVALID;
+ input PIPERX08ELECIDLE;
+ input PIPERX08EQDONE;
+ input PIPERX08EQLPADAPTDONE;
+ input PIPERX08EQLPLFFSSEL;
+ input [17:0] PIPERX08EQLPNEWTXCOEFFORPRESET;
+ input PIPERX08PHYSTATUS;
+ input [1:0] PIPERX08STARTBLOCK;
+ input [2:0] PIPERX08STATUS;
+ input [1:0] PIPERX08SYNCHEADER;
+ input PIPERX08VALID;
+ input [1:0] PIPERX09CHARISK;
+ input [31:0] PIPERX09DATA;
+ input PIPERX09DATAVALID;
+ input PIPERX09ELECIDLE;
+ input PIPERX09EQDONE;
+ input PIPERX09EQLPADAPTDONE;
+ input PIPERX09EQLPLFFSSEL;
+ input [17:0] PIPERX09EQLPNEWTXCOEFFORPRESET;
+ input PIPERX09PHYSTATUS;
+ input [1:0] PIPERX09STARTBLOCK;
+ input [2:0] PIPERX09STATUS;
+ input [1:0] PIPERX09SYNCHEADER;
+ input PIPERX09VALID;
+ input [1:0] PIPERX10CHARISK;
+ input [31:0] PIPERX10DATA;
+ input PIPERX10DATAVALID;
+ input PIPERX10ELECIDLE;
+ input PIPERX10EQDONE;
+ input PIPERX10EQLPADAPTDONE;
+ input PIPERX10EQLPLFFSSEL;
+ input [17:0] PIPERX10EQLPNEWTXCOEFFORPRESET;
+ input PIPERX10PHYSTATUS;
+ input [1:0] PIPERX10STARTBLOCK;
+ input [2:0] PIPERX10STATUS;
+ input [1:0] PIPERX10SYNCHEADER;
+ input PIPERX10VALID;
+ input [1:0] PIPERX11CHARISK;
+ input [31:0] PIPERX11DATA;
+ input PIPERX11DATAVALID;
+ input PIPERX11ELECIDLE;
+ input PIPERX11EQDONE;
+ input PIPERX11EQLPADAPTDONE;
+ input PIPERX11EQLPLFFSSEL;
+ input [17:0] PIPERX11EQLPNEWTXCOEFFORPRESET;
+ input PIPERX11PHYSTATUS;
+ input [1:0] PIPERX11STARTBLOCK;
+ input [2:0] PIPERX11STATUS;
+ input [1:0] PIPERX11SYNCHEADER;
+ input PIPERX11VALID;
+ input [1:0] PIPERX12CHARISK;
+ input [31:0] PIPERX12DATA;
+ input PIPERX12DATAVALID;
+ input PIPERX12ELECIDLE;
+ input PIPERX12EQDONE;
+ input PIPERX12EQLPADAPTDONE;
+ input PIPERX12EQLPLFFSSEL;
+ input [17:0] PIPERX12EQLPNEWTXCOEFFORPRESET;
+ input PIPERX12PHYSTATUS;
+ input [1:0] PIPERX12STARTBLOCK;
+ input [2:0] PIPERX12STATUS;
+ input [1:0] PIPERX12SYNCHEADER;
+ input PIPERX12VALID;
+ input [1:0] PIPERX13CHARISK;
+ input [31:0] PIPERX13DATA;
+ input PIPERX13DATAVALID;
+ input PIPERX13ELECIDLE;
+ input PIPERX13EQDONE;
+ input PIPERX13EQLPADAPTDONE;
+ input PIPERX13EQLPLFFSSEL;
+ input [17:0] PIPERX13EQLPNEWTXCOEFFORPRESET;
+ input PIPERX13PHYSTATUS;
+ input [1:0] PIPERX13STARTBLOCK;
+ input [2:0] PIPERX13STATUS;
+ input [1:0] PIPERX13SYNCHEADER;
+ input PIPERX13VALID;
+ input [1:0] PIPERX14CHARISK;
+ input [31:0] PIPERX14DATA;
+ input PIPERX14DATAVALID;
+ input PIPERX14ELECIDLE;
+ input PIPERX14EQDONE;
+ input PIPERX14EQLPADAPTDONE;
+ input PIPERX14EQLPLFFSSEL;
+ input [17:0] PIPERX14EQLPNEWTXCOEFFORPRESET;
+ input PIPERX14PHYSTATUS;
+ input [1:0] PIPERX14STARTBLOCK;
+ input [2:0] PIPERX14STATUS;
+ input [1:0] PIPERX14SYNCHEADER;
+ input PIPERX14VALID;
+ input [1:0] PIPERX15CHARISK;
+ input [31:0] PIPERX15DATA;
+ input PIPERX15DATAVALID;
+ input PIPERX15ELECIDLE;
+ input PIPERX15EQDONE;
+ input PIPERX15EQLPADAPTDONE;
+ input PIPERX15EQLPLFFSSEL;
+ input [17:0] PIPERX15EQLPNEWTXCOEFFORPRESET;
+ input PIPERX15PHYSTATUS;
+ input [1:0] PIPERX15STARTBLOCK;
+ input [2:0] PIPERX15STATUS;
+ input [1:0] PIPERX15SYNCHEADER;
+ input PIPERX15VALID;
+ input [17:0] PIPETX00EQCOEFF;
+ input PIPETX00EQDONE;
+ input [17:0] PIPETX01EQCOEFF;
+ input PIPETX01EQDONE;
+ input [17:0] PIPETX02EQCOEFF;
+ input PIPETX02EQDONE;
+ input [17:0] PIPETX03EQCOEFF;
+ input PIPETX03EQDONE;
+ input [17:0] PIPETX04EQCOEFF;
+ input PIPETX04EQDONE;
+ input [17:0] PIPETX05EQCOEFF;
+ input PIPETX05EQDONE;
+ input [17:0] PIPETX06EQCOEFF;
+ input PIPETX06EQDONE;
+ input [17:0] PIPETX07EQCOEFF;
+ input PIPETX07EQDONE;
+ input [17:0] PIPETX08EQCOEFF;
+ input PIPETX08EQDONE;
+ input [17:0] PIPETX09EQCOEFF;
+ input PIPETX09EQDONE;
+ input [17:0] PIPETX10EQCOEFF;
+ input PIPETX10EQDONE;
+ input [17:0] PIPETX11EQCOEFF;
+ input PIPETX11EQDONE;
+ input [17:0] PIPETX12EQCOEFF;
+ input PIPETX12EQDONE;
+ input [17:0] PIPETX13EQCOEFF;
+ input PIPETX13EQDONE;
+ input [17:0] PIPETX14EQCOEFF;
+ input PIPETX14EQDONE;
+ input [17:0] PIPETX15EQCOEFF;
+ input PIPETX15EQDONE;
+ input PLEQRESETEIEOSCOUNT;
+ input PLGEN2UPSTREAMPREFERDEEMPH;
+ input PLGEN34REDOEQSPEED;
+ input PLGEN34REDOEQUALIZATION;
+ input RESETN;
+ input [255:0] SAXISCCIXTXTDATA;
+ input [45:0] SAXISCCIXTXTUSER;
+ input SAXISCCIXTXTVALID;
+ input [255:0] SAXISCCTDATA;
+ input [7:0] SAXISCCTKEEP;
+ input SAXISCCTLAST;
+ input [32:0] SAXISCCTUSER;
+ input SAXISCCTVALID;
+ input [255:0] SAXISRQTDATA;
+ input [7:0] SAXISRQTKEEP;
+ input SAXISRQTLAST;
+ input [61:0] SAXISRQTUSER;
+ input SAXISRQTVALID;
+ input USERCLK;
+ input USERCLK2;
+ input USERCLKEN;
+ input [31:0] USERSPAREIN;
+endmodule
+
module EMAC (...);
parameter EMAC0_MODE = "RGMII";
parameter EMAC1_MODE = "RGMII";
@@ -25063,6 +27353,3069 @@ module CMACE4 (...);
input TX_SOPIN3;
endmodule
+module MCB (...);
+ parameter integer ARB_NUM_TIME_SLOTS = 12;
+ parameter [17:0] ARB_TIME_SLOT_0 = 18'b111111111111111111;
+ parameter [17:0] ARB_TIME_SLOT_1 = 18'b111111111111111111;
+ parameter [17:0] ARB_TIME_SLOT_10 = 18'b111111111111111111;
+ parameter [17:0] ARB_TIME_SLOT_11 = 18'b111111111111111111;
+ parameter [17:0] ARB_TIME_SLOT_2 = 18'b111111111111111111;
+ parameter [17:0] ARB_TIME_SLOT_3 = 18'b111111111111111111;
+ parameter [17:0] ARB_TIME_SLOT_4 = 18'b111111111111111111;
+ parameter [17:0] ARB_TIME_SLOT_5 = 18'b111111111111111111;
+ parameter [17:0] ARB_TIME_SLOT_6 = 18'b111111111111111111;
+ parameter [17:0] ARB_TIME_SLOT_7 = 18'b111111111111111111;
+ parameter [17:0] ARB_TIME_SLOT_8 = 18'b111111111111111111;
+ parameter [17:0] ARB_TIME_SLOT_9 = 18'b111111111111111111;
+ parameter [2:0] CAL_BA = 3'h0;
+ parameter CAL_BYPASS = "YES";
+ parameter [11:0] CAL_CA = 12'h000;
+ parameter CAL_CALIBRATION_MODE = "NOCALIBRATION";
+ parameter integer CAL_CLK_DIV = 1;
+ parameter CAL_DELAY = "QUARTER";
+ parameter [14:0] CAL_RA = 15'h0000;
+ parameter MEM_ADDR_ORDER = "BANK_ROW_COLUMN";
+ parameter integer MEM_BA_SIZE = 3;
+ parameter integer MEM_BURST_LEN = 8;
+ parameter integer MEM_CAS_LATENCY = 4;
+ parameter integer MEM_CA_SIZE = 11;
+ parameter MEM_DDR1_2_ODS = "FULL";
+ parameter MEM_DDR2_3_HIGH_TEMP_SR = "NORMAL";
+ parameter MEM_DDR2_3_PA_SR = "FULL";
+ parameter integer MEM_DDR2_ADD_LATENCY = 0;
+ parameter MEM_DDR2_DIFF_DQS_EN = "YES";
+ parameter MEM_DDR2_RTT = "50OHMS";
+ parameter integer MEM_DDR2_WRT_RECOVERY = 4;
+ parameter MEM_DDR3_ADD_LATENCY = "OFF";
+ parameter MEM_DDR3_AUTO_SR = "ENABLED";
+ parameter integer MEM_DDR3_CAS_LATENCY = 7;
+ parameter integer MEM_DDR3_CAS_WR_LATENCY = 5;
+ parameter MEM_DDR3_DYN_WRT_ODT = "OFF";
+ parameter MEM_DDR3_ODS = "DIV7";
+ parameter MEM_DDR3_RTT = "DIV2";
+ parameter integer MEM_DDR3_WRT_RECOVERY = 7;
+ parameter MEM_MDDR_ODS = "FULL";
+ parameter MEM_MOBILE_PA_SR = "FULL";
+ parameter integer MEM_MOBILE_TC_SR = 0;
+ parameter integer MEM_RAS_VAL = 0;
+ parameter integer MEM_RA_SIZE = 13;
+ parameter integer MEM_RCD_VAL = 1;
+ parameter integer MEM_REFI_VAL = 0;
+ parameter integer MEM_RFC_VAL = 0;
+ parameter integer MEM_RP_VAL = 0;
+ parameter integer MEM_RTP_VAL = 0;
+ parameter MEM_TYPE = "DDR3";
+ parameter integer MEM_WIDTH = 4;
+ parameter integer MEM_WR_VAL = 0;
+ parameter integer MEM_WTR_VAL = 3;
+ parameter PORT_CONFIG = "B32_B32_B32_B32";
+ output CAS;
+ output CKE;
+ output DQIOWEN0;
+ output DQSIOWEN90N;
+ output DQSIOWEN90P;
+ output IOIDRPADD;
+ output IOIDRPBROADCAST;
+ output IOIDRPCLK;
+ output IOIDRPCS;
+ output IOIDRPSDO;
+ output IOIDRPTRAIN;
+ output IOIDRPUPDATE;
+ output LDMN;
+ output LDMP;
+ output ODT;
+ output P0CMDEMPTY;
+ output P0CMDFULL;
+ output P0RDEMPTY;
+ output P0RDERROR;
+ output P0RDFULL;
+ output P0RDOVERFLOW;
+ output P0WREMPTY;
+ output P0WRERROR;
+ output P0WRFULL;
+ output P0WRUNDERRUN;
+ output P1CMDEMPTY;
+ output P1CMDFULL;
+ output P1RDEMPTY;
+ output P1RDERROR;
+ output P1RDFULL;
+ output P1RDOVERFLOW;
+ output P1WREMPTY;
+ output P1WRERROR;
+ output P1WRFULL;
+ output P1WRUNDERRUN;
+ output P2CMDEMPTY;
+ output P2CMDFULL;
+ output P2EMPTY;
+ output P2ERROR;
+ output P2FULL;
+ output P2RDOVERFLOW;
+ output P2WRUNDERRUN;
+ output P3CMDEMPTY;
+ output P3CMDFULL;
+ output P3EMPTY;
+ output P3ERROR;
+ output P3FULL;
+ output P3RDOVERFLOW;
+ output P3WRUNDERRUN;
+ output P4CMDEMPTY;
+ output P4CMDFULL;
+ output P4EMPTY;
+ output P4ERROR;
+ output P4FULL;
+ output P4RDOVERFLOW;
+ output P4WRUNDERRUN;
+ output P5CMDEMPTY;
+ output P5CMDFULL;
+ output P5EMPTY;
+ output P5ERROR;
+ output P5FULL;
+ output P5RDOVERFLOW;
+ output P5WRUNDERRUN;
+ output RAS;
+ output RST;
+ output SELFREFRESHMODE;
+ output UDMN;
+ output UDMP;
+ output UOCALSTART;
+ output UOCMDREADYIN;
+ output UODATAVALID;
+ output UODONECAL;
+ output UOREFRSHFLAG;
+ output UOSDO;
+ output WE;
+ output [14:0] ADDR;
+ output [15:0] DQON;
+ output [15:0] DQOP;
+ output [2:0] BA;
+ output [31:0] P0RDDATA;
+ output [31:0] P1RDDATA;
+ output [31:0] P2RDDATA;
+ output [31:0] P3RDDATA;
+ output [31:0] P4RDDATA;
+ output [31:0] P5RDDATA;
+ output [31:0] STATUS;
+ output [4:0] IOIDRPADDR;
+ output [6:0] P0RDCOUNT;
+ output [6:0] P0WRCOUNT;
+ output [6:0] P1RDCOUNT;
+ output [6:0] P1WRCOUNT;
+ output [6:0] P2COUNT;
+ output [6:0] P3COUNT;
+ output [6:0] P4COUNT;
+ output [6:0] P5COUNT;
+ output [7:0] UODATA;
+ input DQSIOIN;
+ input DQSIOIP;
+ input IOIDRPSDI;
+ input P0ARBEN;
+ input P0CMDCLK;
+ input P0CMDEN;
+ input P0RDCLK;
+ input P0RDEN;
+ input P0WRCLK;
+ input P0WREN;
+ input P1ARBEN;
+ input P1CMDCLK;
+ input P1CMDEN;
+ input P1RDCLK;
+ input P1RDEN;
+ input P1WRCLK;
+ input P1WREN;
+ input P2ARBEN;
+ input P2CLK;
+ input P2CMDCLK;
+ input P2CMDEN;
+ input P2EN;
+ input P3ARBEN;
+ input P3CLK;
+ input P3CMDCLK;
+ input P3CMDEN;
+ input P3EN;
+ input P4ARBEN;
+ input P4CLK;
+ input P4CMDCLK;
+ input P4CMDEN;
+ input P4EN;
+ input P5ARBEN;
+ input P5CLK;
+ input P5CMDCLK;
+ input P5CMDEN;
+ input P5EN;
+ input PLLLOCK;
+ input RECAL;
+ input SELFREFRESHENTER;
+ input SYSRST;
+ input UDQSIOIN;
+ input UDQSIOIP;
+ input UIADD;
+ input UIBROADCAST;
+ input UICLK;
+ input UICMD;
+ input UICMDEN;
+ input UICMDIN;
+ input UICS;
+ input UIDONECAL;
+ input UIDQLOWERDEC;
+ input UIDQLOWERINC;
+ input UIDQUPPERDEC;
+ input UIDQUPPERINC;
+ input UIDRPUPDATE;
+ input UILDQSDEC;
+ input UILDQSINC;
+ input UIREAD;
+ input UISDI;
+ input UIUDQSDEC;
+ input UIUDQSINC;
+ input [11:0] P0CMDCA;
+ input [11:0] P1CMDCA;
+ input [11:0] P2CMDCA;
+ input [11:0] P3CMDCA;
+ input [11:0] P4CMDCA;
+ input [11:0] P5CMDCA;
+ input [14:0] P0CMDRA;
+ input [14:0] P1CMDRA;
+ input [14:0] P2CMDRA;
+ input [14:0] P3CMDRA;
+ input [14:0] P4CMDRA;
+ input [14:0] P5CMDRA;
+ input [15:0] DQI;
+ input [1:0] PLLCE;
+ input [1:0] PLLCLK;
+ input [2:0] P0CMDBA;
+ input [2:0] P0CMDINSTR;
+ input [2:0] P1CMDBA;
+ input [2:0] P1CMDINSTR;
+ input [2:0] P2CMDBA;
+ input [2:0] P2CMDINSTR;
+ input [2:0] P3CMDBA;
+ input [2:0] P3CMDINSTR;
+ input [2:0] P4CMDBA;
+ input [2:0] P4CMDINSTR;
+ input [2:0] P5CMDBA;
+ input [2:0] P5CMDINSTR;
+ input [31:0] P0WRDATA;
+ input [31:0] P1WRDATA;
+ input [31:0] P2WRDATA;
+ input [31:0] P3WRDATA;
+ input [31:0] P4WRDATA;
+ input [31:0] P5WRDATA;
+ input [3:0] P0RWRMASK;
+ input [3:0] P1RWRMASK;
+ input [3:0] P2WRMASK;
+ input [3:0] P3WRMASK;
+ input [3:0] P4WRMASK;
+ input [3:0] P5WRMASK;
+ input [3:0] UIDQCOUNT;
+ input [4:0] UIADDR;
+ input [5:0] P0CMDBL;
+ input [5:0] P1CMDBL;
+ input [5:0] P2CMDBL;
+ input [5:0] P3CMDBL;
+ input [5:0] P4CMDBL;
+ input [5:0] P5CMDBL;
+endmodule
+
+(* keep *)
+module HBM_REF_CLK (...);
+ input REF_CLK;
+endmodule
+
+(* keep *)
+module HBM_SNGLBLI_INTF_APB (...);
+ parameter CLK_SEL = "FALSE";
+ parameter [0:0] IS_PCLK_INVERTED = 1'b0;
+ parameter [0:0] IS_PRESET_N_INVERTED = 1'b0;
+ parameter MC_ENABLE = "FALSE";
+ parameter PHY_ENABLE = "FALSE";
+ parameter PHY_PCLK_INVERT = "FALSE";
+ parameter SWITCH_ENABLE = "FALSE";
+ output CATTRIP_PIPE;
+ output [31:0] PRDATA_PIPE;
+ output PREADY_PIPE;
+ output PSLVERR_PIPE;
+ output [2:0] TEMP_PIPE;
+ input [21:0] PADDR;
+ (* invertible_pin = "IS_PCLK_INVERTED" *)
+ input PCLK;
+ input PENABLE;
+ (* invertible_pin = "IS_PRESET_N_INVERTED" *)
+ input PRESET_N;
+ input PSEL;
+ input [31:0] PWDATA;
+ input PWRITE;
+endmodule
+
+(* keep *)
+module HBM_SNGLBLI_INTF_AXI (...);
+ parameter CLK_SEL = "FALSE";
+ parameter integer DATARATE = 1800;
+ parameter [0:0] IS_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_ARESET_N_INVERTED = 1'b0;
+ parameter MC_ENABLE = "FALSE";
+ parameter integer PAGEHIT_PERCENT = 75;
+ parameter PHY_ENABLE = "FALSE";
+ parameter integer READ_PERCENT = 50;
+ parameter SWITCH_ENABLE = "FALSE";
+ parameter integer WRITE_PERCENT = 50;
+ output ARREADY_PIPE;
+ output AWREADY_PIPE;
+ output [5:0] BID_PIPE;
+ output [1:0] BRESP_PIPE;
+ output BVALID_PIPE;
+ output [1:0] DFI_AW_AERR_N_PIPE;
+ output DFI_CLK_BUF;
+ output DFI_CTRLUPD_ACK_PIPE;
+ output [7:0] DFI_DBI_BYTE_DISABLE_PIPE;
+ output [20:0] DFI_DW_RDDATA_DBI_PIPE;
+ output [7:0] DFI_DW_RDDATA_DERR_PIPE;
+ output [1:0] DFI_DW_RDDATA_PAR_VALID_PIPE;
+ output [1:0] DFI_DW_RDDATA_VALID_PIPE;
+ output DFI_INIT_COMPLETE_PIPE;
+ output DFI_PHYUPD_REQ_PIPE;
+ output DFI_PHYUPD_TYPE_PIPE;
+ output DFI_PHY_LP_STATE_PIPE;
+ output DFI_RST_N_BUF;
+ output [5:0] MC_STATUS;
+ output [7:0] PHY_STATUS;
+ output [31:0] RDATA_PARITY_PIPE;
+ output [255:0] RDATA_PIPE;
+ output [5:0] RID_PIPE;
+ output RLAST_PIPE;
+ output [1:0] RRESP_PIPE;
+ output RVALID_PIPE;
+ output [5:0] STATUS;
+ output WREADY_PIPE;
+ (* invertible_pin = "IS_ACLK_INVERTED" *)
+ input ACLK;
+ input [36:0] ARADDR;
+ input [1:0] ARBURST;
+ (* invertible_pin = "IS_ARESET_N_INVERTED" *)
+ input ARESET_N;
+ input [5:0] ARID;
+ input [3:0] ARLEN;
+ input [2:0] ARSIZE;
+ input ARVALID;
+ input [36:0] AWADDR;
+ input [1:0] AWBURST;
+ input [5:0] AWID;
+ input [3:0] AWLEN;
+ input [2:0] AWSIZE;
+ input AWVALID;
+ input BREADY;
+ input BSCAN_CK;
+ input DFI_LP_PWR_X_REQ;
+ input MBIST_EN;
+ input RREADY;
+ input [255:0] WDATA;
+ input [31:0] WDATA_PARITY;
+ input WLAST;
+ input [31:0] WSTRB;
+ input WVALID;
+endmodule
+
+(* keep *)
+module HBM_ONE_STACK_INTF (...);
+ parameter CLK_SEL_00 = "FALSE";
+ parameter CLK_SEL_01 = "FALSE";
+ parameter CLK_SEL_02 = "FALSE";
+ parameter CLK_SEL_03 = "FALSE";
+ parameter CLK_SEL_04 = "FALSE";
+ parameter CLK_SEL_05 = "FALSE";
+ parameter CLK_SEL_06 = "FALSE";
+ parameter CLK_SEL_07 = "FALSE";
+ parameter CLK_SEL_08 = "FALSE";
+ parameter CLK_SEL_09 = "FALSE";
+ parameter CLK_SEL_10 = "FALSE";
+ parameter CLK_SEL_11 = "FALSE";
+ parameter CLK_SEL_12 = "FALSE";
+ parameter CLK_SEL_13 = "FALSE";
+ parameter CLK_SEL_14 = "FALSE";
+ parameter CLK_SEL_15 = "FALSE";
+ parameter integer DATARATE_00 = 1800;
+ parameter integer DATARATE_01 = 1800;
+ parameter integer DATARATE_02 = 1800;
+ parameter integer DATARATE_03 = 1800;
+ parameter integer DATARATE_04 = 1800;
+ parameter integer DATARATE_05 = 1800;
+ parameter integer DATARATE_06 = 1800;
+ parameter integer DATARATE_07 = 1800;
+ parameter DA_LOCKOUT = "FALSE";
+ parameter [0:0] IS_APB_0_PCLK_INVERTED = 1'b0;
+ parameter [0:0] IS_APB_0_PRESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_00_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_00_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_01_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_01_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_02_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_02_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_03_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_03_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_04_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_04_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_05_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_05_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_06_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_06_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_07_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_07_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_08_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_08_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_09_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_09_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_10_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_10_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_11_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_11_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_12_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_12_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_13_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_13_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_14_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_14_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_15_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_15_ARESET_N_INVERTED = 1'b0;
+ parameter MC_ENABLE_0 = "FALSE";
+ parameter MC_ENABLE_1 = "FALSE";
+ parameter MC_ENABLE_2 = "FALSE";
+ parameter MC_ENABLE_3 = "FALSE";
+ parameter MC_ENABLE_4 = "FALSE";
+ parameter MC_ENABLE_5 = "FALSE";
+ parameter MC_ENABLE_6 = "FALSE";
+ parameter MC_ENABLE_7 = "FALSE";
+ parameter MC_ENABLE_APB = "FALSE";
+ parameter integer PAGEHIT_PERCENT_00 = 75;
+ parameter PHY_ENABLE_00 = "FALSE";
+ parameter PHY_ENABLE_01 = "FALSE";
+ parameter PHY_ENABLE_02 = "FALSE";
+ parameter PHY_ENABLE_03 = "FALSE";
+ parameter PHY_ENABLE_04 = "FALSE";
+ parameter PHY_ENABLE_05 = "FALSE";
+ parameter PHY_ENABLE_06 = "FALSE";
+ parameter PHY_ENABLE_07 = "FALSE";
+ parameter PHY_ENABLE_08 = "FALSE";
+ parameter PHY_ENABLE_09 = "FALSE";
+ parameter PHY_ENABLE_10 = "FALSE";
+ parameter PHY_ENABLE_11 = "FALSE";
+ parameter PHY_ENABLE_12 = "FALSE";
+ parameter PHY_ENABLE_13 = "FALSE";
+ parameter PHY_ENABLE_14 = "FALSE";
+ parameter PHY_ENABLE_15 = "FALSE";
+ parameter PHY_ENABLE_APB = "FALSE";
+ parameter PHY_PCLK_INVERT_01 = "FALSE";
+ parameter integer READ_PERCENT_00 = 50;
+ parameter integer READ_PERCENT_01 = 50;
+ parameter integer READ_PERCENT_02 = 50;
+ parameter integer READ_PERCENT_03 = 50;
+ parameter integer READ_PERCENT_04 = 50;
+ parameter integer READ_PERCENT_05 = 50;
+ parameter integer READ_PERCENT_06 = 50;
+ parameter integer READ_PERCENT_07 = 50;
+ parameter integer READ_PERCENT_08 = 50;
+ parameter integer READ_PERCENT_09 = 50;
+ parameter integer READ_PERCENT_10 = 50;
+ parameter integer READ_PERCENT_11 = 50;
+ parameter integer READ_PERCENT_12 = 50;
+ parameter integer READ_PERCENT_13 = 50;
+ parameter integer READ_PERCENT_14 = 50;
+ parameter integer READ_PERCENT_15 = 50;
+ parameter SIM_DEVICE = "ULTRASCALE_PLUS";
+ parameter integer STACK_LOCATION = 0;
+ parameter SWITCH_ENABLE = "FALSE";
+ parameter integer WRITE_PERCENT_00 = 50;
+ parameter integer WRITE_PERCENT_01 = 50;
+ parameter integer WRITE_PERCENT_02 = 50;
+ parameter integer WRITE_PERCENT_03 = 50;
+ parameter integer WRITE_PERCENT_04 = 50;
+ parameter integer WRITE_PERCENT_05 = 50;
+ parameter integer WRITE_PERCENT_06 = 50;
+ parameter integer WRITE_PERCENT_07 = 50;
+ parameter integer WRITE_PERCENT_08 = 50;
+ parameter integer WRITE_PERCENT_09 = 50;
+ parameter integer WRITE_PERCENT_10 = 50;
+ parameter integer WRITE_PERCENT_11 = 50;
+ parameter integer WRITE_PERCENT_12 = 50;
+ parameter integer WRITE_PERCENT_13 = 50;
+ parameter integer WRITE_PERCENT_14 = 50;
+ parameter integer WRITE_PERCENT_15 = 50;
+ output [31:0] APB_0_PRDATA;
+ output APB_0_PREADY;
+ output APB_0_PSLVERR;
+ output AXI_00_ARREADY;
+ output AXI_00_AWREADY;
+ output [5:0] AXI_00_BID;
+ output [1:0] AXI_00_BRESP;
+ output AXI_00_BVALID;
+ output [1:0] AXI_00_DFI_AW_AERR_N;
+ output AXI_00_DFI_CLK_BUF;
+ output [7:0] AXI_00_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_00_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_00_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_00_DFI_DW_RDDATA_VALID;
+ output AXI_00_DFI_INIT_COMPLETE;
+ output AXI_00_DFI_PHYUPD_REQ;
+ output AXI_00_DFI_PHY_LP_STATE;
+ output AXI_00_DFI_RST_N_BUF;
+ output [5:0] AXI_00_MC_STATUS;
+ output [7:0] AXI_00_PHY_STATUS;
+ output [255:0] AXI_00_RDATA;
+ output [31:0] AXI_00_RDATA_PARITY;
+ output [5:0] AXI_00_RID;
+ output AXI_00_RLAST;
+ output [1:0] AXI_00_RRESP;
+ output AXI_00_RVALID;
+ output AXI_00_WREADY;
+ output AXI_01_ARREADY;
+ output AXI_01_AWREADY;
+ output [5:0] AXI_01_BID;
+ output [1:0] AXI_01_BRESP;
+ output AXI_01_BVALID;
+ output [1:0] AXI_01_DFI_AW_AERR_N;
+ output AXI_01_DFI_CLK_BUF;
+ output [7:0] AXI_01_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_01_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_01_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_01_DFI_DW_RDDATA_VALID;
+ output AXI_01_DFI_INIT_COMPLETE;
+ output AXI_01_DFI_PHYUPD_REQ;
+ output AXI_01_DFI_PHY_LP_STATE;
+ output AXI_01_DFI_RST_N_BUF;
+ output [255:0] AXI_01_RDATA;
+ output [31:0] AXI_01_RDATA_PARITY;
+ output [5:0] AXI_01_RID;
+ output AXI_01_RLAST;
+ output [1:0] AXI_01_RRESP;
+ output AXI_01_RVALID;
+ output AXI_01_WREADY;
+ output AXI_02_ARREADY;
+ output AXI_02_AWREADY;
+ output [5:0] AXI_02_BID;
+ output [1:0] AXI_02_BRESP;
+ output AXI_02_BVALID;
+ output [1:0] AXI_02_DFI_AW_AERR_N;
+ output AXI_02_DFI_CLK_BUF;
+ output [7:0] AXI_02_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_02_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_02_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_02_DFI_DW_RDDATA_VALID;
+ output AXI_02_DFI_INIT_COMPLETE;
+ output AXI_02_DFI_PHYUPD_REQ;
+ output AXI_02_DFI_PHY_LP_STATE;
+ output AXI_02_DFI_RST_N_BUF;
+ output [5:0] AXI_02_MC_STATUS;
+ output [7:0] AXI_02_PHY_STATUS;
+ output [255:0] AXI_02_RDATA;
+ output [31:0] AXI_02_RDATA_PARITY;
+ output [5:0] AXI_02_RID;
+ output AXI_02_RLAST;
+ output [1:0] AXI_02_RRESP;
+ output AXI_02_RVALID;
+ output AXI_02_WREADY;
+ output AXI_03_ARREADY;
+ output AXI_03_AWREADY;
+ output [5:0] AXI_03_BID;
+ output [1:0] AXI_03_BRESP;
+ output AXI_03_BVALID;
+ output [1:0] AXI_03_DFI_AW_AERR_N;
+ output AXI_03_DFI_CLK_BUF;
+ output [7:0] AXI_03_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_03_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_03_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_03_DFI_DW_RDDATA_VALID;
+ output AXI_03_DFI_INIT_COMPLETE;
+ output AXI_03_DFI_PHYUPD_REQ;
+ output AXI_03_DFI_PHY_LP_STATE;
+ output AXI_03_DFI_RST_N_BUF;
+ output [255:0] AXI_03_RDATA;
+ output [31:0] AXI_03_RDATA_PARITY;
+ output [5:0] AXI_03_RID;
+ output AXI_03_RLAST;
+ output [1:0] AXI_03_RRESP;
+ output AXI_03_RVALID;
+ output AXI_03_WREADY;
+ output AXI_04_ARREADY;
+ output AXI_04_AWREADY;
+ output [5:0] AXI_04_BID;
+ output [1:0] AXI_04_BRESP;
+ output AXI_04_BVALID;
+ output [1:0] AXI_04_DFI_AW_AERR_N;
+ output AXI_04_DFI_CLK_BUF;
+ output [7:0] AXI_04_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_04_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_04_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_04_DFI_DW_RDDATA_VALID;
+ output AXI_04_DFI_INIT_COMPLETE;
+ output AXI_04_DFI_PHYUPD_REQ;
+ output AXI_04_DFI_PHY_LP_STATE;
+ output AXI_04_DFI_RST_N_BUF;
+ output [5:0] AXI_04_MC_STATUS;
+ output [7:0] AXI_04_PHY_STATUS;
+ output [255:0] AXI_04_RDATA;
+ output [31:0] AXI_04_RDATA_PARITY;
+ output [5:0] AXI_04_RID;
+ output AXI_04_RLAST;
+ output [1:0] AXI_04_RRESP;
+ output AXI_04_RVALID;
+ output AXI_04_WREADY;
+ output AXI_05_ARREADY;
+ output AXI_05_AWREADY;
+ output [5:0] AXI_05_BID;
+ output [1:0] AXI_05_BRESP;
+ output AXI_05_BVALID;
+ output [1:0] AXI_05_DFI_AW_AERR_N;
+ output AXI_05_DFI_CLK_BUF;
+ output [7:0] AXI_05_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_05_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_05_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_05_DFI_DW_RDDATA_VALID;
+ output AXI_05_DFI_INIT_COMPLETE;
+ output AXI_05_DFI_PHYUPD_REQ;
+ output AXI_05_DFI_PHY_LP_STATE;
+ output AXI_05_DFI_RST_N_BUF;
+ output [255:0] AXI_05_RDATA;
+ output [31:0] AXI_05_RDATA_PARITY;
+ output [5:0] AXI_05_RID;
+ output AXI_05_RLAST;
+ output [1:0] AXI_05_RRESP;
+ output AXI_05_RVALID;
+ output AXI_05_WREADY;
+ output AXI_06_ARREADY;
+ output AXI_06_AWREADY;
+ output [5:0] AXI_06_BID;
+ output [1:0] AXI_06_BRESP;
+ output AXI_06_BVALID;
+ output [1:0] AXI_06_DFI_AW_AERR_N;
+ output AXI_06_DFI_CLK_BUF;
+ output [7:0] AXI_06_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_06_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_06_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_06_DFI_DW_RDDATA_VALID;
+ output AXI_06_DFI_INIT_COMPLETE;
+ output AXI_06_DFI_PHYUPD_REQ;
+ output AXI_06_DFI_PHY_LP_STATE;
+ output AXI_06_DFI_RST_N_BUF;
+ output [5:0] AXI_06_MC_STATUS;
+ output [7:0] AXI_06_PHY_STATUS;
+ output [255:0] AXI_06_RDATA;
+ output [31:0] AXI_06_RDATA_PARITY;
+ output [5:0] AXI_06_RID;
+ output AXI_06_RLAST;
+ output [1:0] AXI_06_RRESP;
+ output AXI_06_RVALID;
+ output AXI_06_WREADY;
+ output AXI_07_ARREADY;
+ output AXI_07_AWREADY;
+ output [5:0] AXI_07_BID;
+ output [1:0] AXI_07_BRESP;
+ output AXI_07_BVALID;
+ output [1:0] AXI_07_DFI_AW_AERR_N;
+ output AXI_07_DFI_CLK_BUF;
+ output [7:0] AXI_07_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_07_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_07_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_07_DFI_DW_RDDATA_VALID;
+ output AXI_07_DFI_INIT_COMPLETE;
+ output AXI_07_DFI_PHYUPD_REQ;
+ output AXI_07_DFI_PHY_LP_STATE;
+ output AXI_07_DFI_RST_N_BUF;
+ output [255:0] AXI_07_RDATA;
+ output [31:0] AXI_07_RDATA_PARITY;
+ output [5:0] AXI_07_RID;
+ output AXI_07_RLAST;
+ output [1:0] AXI_07_RRESP;
+ output AXI_07_RVALID;
+ output AXI_07_WREADY;
+ output AXI_08_ARREADY;
+ output AXI_08_AWREADY;
+ output [5:0] AXI_08_BID;
+ output [1:0] AXI_08_BRESP;
+ output AXI_08_BVALID;
+ output [1:0] AXI_08_DFI_AW_AERR_N;
+ output AXI_08_DFI_CLK_BUF;
+ output [7:0] AXI_08_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_08_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_08_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_08_DFI_DW_RDDATA_VALID;
+ output AXI_08_DFI_INIT_COMPLETE;
+ output AXI_08_DFI_PHYUPD_REQ;
+ output AXI_08_DFI_PHY_LP_STATE;
+ output AXI_08_DFI_RST_N_BUF;
+ output [5:0] AXI_08_MC_STATUS;
+ output [7:0] AXI_08_PHY_STATUS;
+ output [255:0] AXI_08_RDATA;
+ output [31:0] AXI_08_RDATA_PARITY;
+ output [5:0] AXI_08_RID;
+ output AXI_08_RLAST;
+ output [1:0] AXI_08_RRESP;
+ output AXI_08_RVALID;
+ output AXI_08_WREADY;
+ output AXI_09_ARREADY;
+ output AXI_09_AWREADY;
+ output [5:0] AXI_09_BID;
+ output [1:0] AXI_09_BRESP;
+ output AXI_09_BVALID;
+ output [1:0] AXI_09_DFI_AW_AERR_N;
+ output AXI_09_DFI_CLK_BUF;
+ output [7:0] AXI_09_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_09_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_09_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_09_DFI_DW_RDDATA_VALID;
+ output AXI_09_DFI_INIT_COMPLETE;
+ output AXI_09_DFI_PHYUPD_REQ;
+ output AXI_09_DFI_PHY_LP_STATE;
+ output AXI_09_DFI_RST_N_BUF;
+ output [255:0] AXI_09_RDATA;
+ output [31:0] AXI_09_RDATA_PARITY;
+ output [5:0] AXI_09_RID;
+ output AXI_09_RLAST;
+ output [1:0] AXI_09_RRESP;
+ output AXI_09_RVALID;
+ output AXI_09_WREADY;
+ output AXI_10_ARREADY;
+ output AXI_10_AWREADY;
+ output [5:0] AXI_10_BID;
+ output [1:0] AXI_10_BRESP;
+ output AXI_10_BVALID;
+ output [1:0] AXI_10_DFI_AW_AERR_N;
+ output AXI_10_DFI_CLK_BUF;
+ output [7:0] AXI_10_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_10_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_10_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_10_DFI_DW_RDDATA_VALID;
+ output AXI_10_DFI_INIT_COMPLETE;
+ output AXI_10_DFI_PHYUPD_REQ;
+ output AXI_10_DFI_PHY_LP_STATE;
+ output AXI_10_DFI_RST_N_BUF;
+ output [5:0] AXI_10_MC_STATUS;
+ output [7:0] AXI_10_PHY_STATUS;
+ output [255:0] AXI_10_RDATA;
+ output [31:0] AXI_10_RDATA_PARITY;
+ output [5:0] AXI_10_RID;
+ output AXI_10_RLAST;
+ output [1:0] AXI_10_RRESP;
+ output AXI_10_RVALID;
+ output AXI_10_WREADY;
+ output AXI_11_ARREADY;
+ output AXI_11_AWREADY;
+ output [5:0] AXI_11_BID;
+ output [1:0] AXI_11_BRESP;
+ output AXI_11_BVALID;
+ output [1:0] AXI_11_DFI_AW_AERR_N;
+ output AXI_11_DFI_CLK_BUF;
+ output [7:0] AXI_11_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_11_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_11_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_11_DFI_DW_RDDATA_VALID;
+ output AXI_11_DFI_INIT_COMPLETE;
+ output AXI_11_DFI_PHYUPD_REQ;
+ output AXI_11_DFI_PHY_LP_STATE;
+ output AXI_11_DFI_RST_N_BUF;
+ output [255:0] AXI_11_RDATA;
+ output [31:0] AXI_11_RDATA_PARITY;
+ output [5:0] AXI_11_RID;
+ output AXI_11_RLAST;
+ output [1:0] AXI_11_RRESP;
+ output AXI_11_RVALID;
+ output AXI_11_WREADY;
+ output AXI_12_ARREADY;
+ output AXI_12_AWREADY;
+ output [5:0] AXI_12_BID;
+ output [1:0] AXI_12_BRESP;
+ output AXI_12_BVALID;
+ output [1:0] AXI_12_DFI_AW_AERR_N;
+ output AXI_12_DFI_CLK_BUF;
+ output [7:0] AXI_12_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_12_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_12_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_12_DFI_DW_RDDATA_VALID;
+ output AXI_12_DFI_INIT_COMPLETE;
+ output AXI_12_DFI_PHYUPD_REQ;
+ output AXI_12_DFI_PHY_LP_STATE;
+ output AXI_12_DFI_RST_N_BUF;
+ output [5:0] AXI_12_MC_STATUS;
+ output [7:0] AXI_12_PHY_STATUS;
+ output [255:0] AXI_12_RDATA;
+ output [31:0] AXI_12_RDATA_PARITY;
+ output [5:0] AXI_12_RID;
+ output AXI_12_RLAST;
+ output [1:0] AXI_12_RRESP;
+ output AXI_12_RVALID;
+ output AXI_12_WREADY;
+ output AXI_13_ARREADY;
+ output AXI_13_AWREADY;
+ output [5:0] AXI_13_BID;
+ output [1:0] AXI_13_BRESP;
+ output AXI_13_BVALID;
+ output [1:0] AXI_13_DFI_AW_AERR_N;
+ output AXI_13_DFI_CLK_BUF;
+ output [7:0] AXI_13_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_13_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_13_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_13_DFI_DW_RDDATA_VALID;
+ output AXI_13_DFI_INIT_COMPLETE;
+ output AXI_13_DFI_PHYUPD_REQ;
+ output AXI_13_DFI_PHY_LP_STATE;
+ output AXI_13_DFI_RST_N_BUF;
+ output [255:0] AXI_13_RDATA;
+ output [31:0] AXI_13_RDATA_PARITY;
+ output [5:0] AXI_13_RID;
+ output AXI_13_RLAST;
+ output [1:0] AXI_13_RRESP;
+ output AXI_13_RVALID;
+ output AXI_13_WREADY;
+ output AXI_14_ARREADY;
+ output AXI_14_AWREADY;
+ output [5:0] AXI_14_BID;
+ output [1:0] AXI_14_BRESP;
+ output AXI_14_BVALID;
+ output [1:0] AXI_14_DFI_AW_AERR_N;
+ output AXI_14_DFI_CLK_BUF;
+ output [7:0] AXI_14_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_14_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_14_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_14_DFI_DW_RDDATA_VALID;
+ output AXI_14_DFI_INIT_COMPLETE;
+ output AXI_14_DFI_PHYUPD_REQ;
+ output AXI_14_DFI_PHY_LP_STATE;
+ output AXI_14_DFI_RST_N_BUF;
+ output [5:0] AXI_14_MC_STATUS;
+ output [7:0] AXI_14_PHY_STATUS;
+ output [255:0] AXI_14_RDATA;
+ output [31:0] AXI_14_RDATA_PARITY;
+ output [5:0] AXI_14_RID;
+ output AXI_14_RLAST;
+ output [1:0] AXI_14_RRESP;
+ output AXI_14_RVALID;
+ output AXI_14_WREADY;
+ output AXI_15_ARREADY;
+ output AXI_15_AWREADY;
+ output [5:0] AXI_15_BID;
+ output [1:0] AXI_15_BRESP;
+ output AXI_15_BVALID;
+ output [1:0] AXI_15_DFI_AW_AERR_N;
+ output AXI_15_DFI_CLK_BUF;
+ output [7:0] AXI_15_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_15_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_15_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_15_DFI_DW_RDDATA_VALID;
+ output AXI_15_DFI_INIT_COMPLETE;
+ output AXI_15_DFI_PHYUPD_REQ;
+ output AXI_15_DFI_PHY_LP_STATE;
+ output AXI_15_DFI_RST_N_BUF;
+ output [255:0] AXI_15_RDATA;
+ output [31:0] AXI_15_RDATA_PARITY;
+ output [5:0] AXI_15_RID;
+ output AXI_15_RLAST;
+ output [1:0] AXI_15_RRESP;
+ output AXI_15_RVALID;
+ output AXI_15_WREADY;
+ output DRAM_0_STAT_CATTRIP;
+ output [2:0] DRAM_0_STAT_TEMP;
+ input [21:0] APB_0_PADDR;
+ (* invertible_pin = "IS_APB_0_PCLK_INVERTED" *)
+ input APB_0_PCLK;
+ input APB_0_PENABLE;
+ (* invertible_pin = "IS_APB_0_PRESET_N_INVERTED" *)
+ input APB_0_PRESET_N;
+ input APB_0_PSEL;
+ input [31:0] APB_0_PWDATA;
+ input APB_0_PWRITE;
+ (* invertible_pin = "IS_AXI_00_ACLK_INVERTED" *)
+ input AXI_00_ACLK;
+ input [36:0] AXI_00_ARADDR;
+ input [1:0] AXI_00_ARBURST;
+ (* invertible_pin = "IS_AXI_00_ARESET_N_INVERTED" *)
+ input AXI_00_ARESET_N;
+ input [5:0] AXI_00_ARID;
+ input [3:0] AXI_00_ARLEN;
+ input [2:0] AXI_00_ARSIZE;
+ input AXI_00_ARVALID;
+ input [36:0] AXI_00_AWADDR;
+ input [1:0] AXI_00_AWBURST;
+ input [5:0] AXI_00_AWID;
+ input [3:0] AXI_00_AWLEN;
+ input [2:0] AXI_00_AWSIZE;
+ input AXI_00_AWVALID;
+ input AXI_00_BREADY;
+ input AXI_00_DFI_LP_PWR_X_REQ;
+ input AXI_00_RREADY;
+ input [255:0] AXI_00_WDATA;
+ input [31:0] AXI_00_WDATA_PARITY;
+ input AXI_00_WLAST;
+ input [31:0] AXI_00_WSTRB;
+ input AXI_00_WVALID;
+ (* invertible_pin = "IS_AXI_01_ACLK_INVERTED" *)
+ input AXI_01_ACLK;
+ input [36:0] AXI_01_ARADDR;
+ input [1:0] AXI_01_ARBURST;
+ (* invertible_pin = "IS_AXI_01_ARESET_N_INVERTED" *)
+ input AXI_01_ARESET_N;
+ input [5:0] AXI_01_ARID;
+ input [3:0] AXI_01_ARLEN;
+ input [2:0] AXI_01_ARSIZE;
+ input AXI_01_ARVALID;
+ input [36:0] AXI_01_AWADDR;
+ input [1:0] AXI_01_AWBURST;
+ input [5:0] AXI_01_AWID;
+ input [3:0] AXI_01_AWLEN;
+ input [2:0] AXI_01_AWSIZE;
+ input AXI_01_AWVALID;
+ input AXI_01_BREADY;
+ input AXI_01_DFI_LP_PWR_X_REQ;
+ input AXI_01_RREADY;
+ input [255:0] AXI_01_WDATA;
+ input [31:0] AXI_01_WDATA_PARITY;
+ input AXI_01_WLAST;
+ input [31:0] AXI_01_WSTRB;
+ input AXI_01_WVALID;
+ (* invertible_pin = "IS_AXI_02_ACLK_INVERTED" *)
+ input AXI_02_ACLK;
+ input [36:0] AXI_02_ARADDR;
+ input [1:0] AXI_02_ARBURST;
+ (* invertible_pin = "IS_AXI_02_ARESET_N_INVERTED" *)
+ input AXI_02_ARESET_N;
+ input [5:0] AXI_02_ARID;
+ input [3:0] AXI_02_ARLEN;
+ input [2:0] AXI_02_ARSIZE;
+ input AXI_02_ARVALID;
+ input [36:0] AXI_02_AWADDR;
+ input [1:0] AXI_02_AWBURST;
+ input [5:0] AXI_02_AWID;
+ input [3:0] AXI_02_AWLEN;
+ input [2:0] AXI_02_AWSIZE;
+ input AXI_02_AWVALID;
+ input AXI_02_BREADY;
+ input AXI_02_DFI_LP_PWR_X_REQ;
+ input AXI_02_RREADY;
+ input [255:0] AXI_02_WDATA;
+ input [31:0] AXI_02_WDATA_PARITY;
+ input AXI_02_WLAST;
+ input [31:0] AXI_02_WSTRB;
+ input AXI_02_WVALID;
+ (* invertible_pin = "IS_AXI_03_ACLK_INVERTED" *)
+ input AXI_03_ACLK;
+ input [36:0] AXI_03_ARADDR;
+ input [1:0] AXI_03_ARBURST;
+ (* invertible_pin = "IS_AXI_03_ARESET_N_INVERTED" *)
+ input AXI_03_ARESET_N;
+ input [5:0] AXI_03_ARID;
+ input [3:0] AXI_03_ARLEN;
+ input [2:0] AXI_03_ARSIZE;
+ input AXI_03_ARVALID;
+ input [36:0] AXI_03_AWADDR;
+ input [1:0] AXI_03_AWBURST;
+ input [5:0] AXI_03_AWID;
+ input [3:0] AXI_03_AWLEN;
+ input [2:0] AXI_03_AWSIZE;
+ input AXI_03_AWVALID;
+ input AXI_03_BREADY;
+ input AXI_03_DFI_LP_PWR_X_REQ;
+ input AXI_03_RREADY;
+ input [255:0] AXI_03_WDATA;
+ input [31:0] AXI_03_WDATA_PARITY;
+ input AXI_03_WLAST;
+ input [31:0] AXI_03_WSTRB;
+ input AXI_03_WVALID;
+ (* invertible_pin = "IS_AXI_04_ACLK_INVERTED" *)
+ input AXI_04_ACLK;
+ input [36:0] AXI_04_ARADDR;
+ input [1:0] AXI_04_ARBURST;
+ (* invertible_pin = "IS_AXI_04_ARESET_N_INVERTED" *)
+ input AXI_04_ARESET_N;
+ input [5:0] AXI_04_ARID;
+ input [3:0] AXI_04_ARLEN;
+ input [2:0] AXI_04_ARSIZE;
+ input AXI_04_ARVALID;
+ input [36:0] AXI_04_AWADDR;
+ input [1:0] AXI_04_AWBURST;
+ input [5:0] AXI_04_AWID;
+ input [3:0] AXI_04_AWLEN;
+ input [2:0] AXI_04_AWSIZE;
+ input AXI_04_AWVALID;
+ input AXI_04_BREADY;
+ input AXI_04_DFI_LP_PWR_X_REQ;
+ input AXI_04_RREADY;
+ input [255:0] AXI_04_WDATA;
+ input [31:0] AXI_04_WDATA_PARITY;
+ input AXI_04_WLAST;
+ input [31:0] AXI_04_WSTRB;
+ input AXI_04_WVALID;
+ (* invertible_pin = "IS_AXI_05_ACLK_INVERTED" *)
+ input AXI_05_ACLK;
+ input [36:0] AXI_05_ARADDR;
+ input [1:0] AXI_05_ARBURST;
+ (* invertible_pin = "IS_AXI_05_ARESET_N_INVERTED" *)
+ input AXI_05_ARESET_N;
+ input [5:0] AXI_05_ARID;
+ input [3:0] AXI_05_ARLEN;
+ input [2:0] AXI_05_ARSIZE;
+ input AXI_05_ARVALID;
+ input [36:0] AXI_05_AWADDR;
+ input [1:0] AXI_05_AWBURST;
+ input [5:0] AXI_05_AWID;
+ input [3:0] AXI_05_AWLEN;
+ input [2:0] AXI_05_AWSIZE;
+ input AXI_05_AWVALID;
+ input AXI_05_BREADY;
+ input AXI_05_DFI_LP_PWR_X_REQ;
+ input AXI_05_RREADY;
+ input [255:0] AXI_05_WDATA;
+ input [31:0] AXI_05_WDATA_PARITY;
+ input AXI_05_WLAST;
+ input [31:0] AXI_05_WSTRB;
+ input AXI_05_WVALID;
+ (* invertible_pin = "IS_AXI_06_ACLK_INVERTED" *)
+ input AXI_06_ACLK;
+ input [36:0] AXI_06_ARADDR;
+ input [1:0] AXI_06_ARBURST;
+ (* invertible_pin = "IS_AXI_06_ARESET_N_INVERTED" *)
+ input AXI_06_ARESET_N;
+ input [5:0] AXI_06_ARID;
+ input [3:0] AXI_06_ARLEN;
+ input [2:0] AXI_06_ARSIZE;
+ input AXI_06_ARVALID;
+ input [36:0] AXI_06_AWADDR;
+ input [1:0] AXI_06_AWBURST;
+ input [5:0] AXI_06_AWID;
+ input [3:0] AXI_06_AWLEN;
+ input [2:0] AXI_06_AWSIZE;
+ input AXI_06_AWVALID;
+ input AXI_06_BREADY;
+ input AXI_06_DFI_LP_PWR_X_REQ;
+ input AXI_06_RREADY;
+ input [255:0] AXI_06_WDATA;
+ input [31:0] AXI_06_WDATA_PARITY;
+ input AXI_06_WLAST;
+ input [31:0] AXI_06_WSTRB;
+ input AXI_06_WVALID;
+ (* invertible_pin = "IS_AXI_07_ACLK_INVERTED" *)
+ input AXI_07_ACLK;
+ input [36:0] AXI_07_ARADDR;
+ input [1:0] AXI_07_ARBURST;
+ (* invertible_pin = "IS_AXI_07_ARESET_N_INVERTED" *)
+ input AXI_07_ARESET_N;
+ input [5:0] AXI_07_ARID;
+ input [3:0] AXI_07_ARLEN;
+ input [2:0] AXI_07_ARSIZE;
+ input AXI_07_ARVALID;
+ input [36:0] AXI_07_AWADDR;
+ input [1:0] AXI_07_AWBURST;
+ input [5:0] AXI_07_AWID;
+ input [3:0] AXI_07_AWLEN;
+ input [2:0] AXI_07_AWSIZE;
+ input AXI_07_AWVALID;
+ input AXI_07_BREADY;
+ input AXI_07_DFI_LP_PWR_X_REQ;
+ input AXI_07_RREADY;
+ input [255:0] AXI_07_WDATA;
+ input [31:0] AXI_07_WDATA_PARITY;
+ input AXI_07_WLAST;
+ input [31:0] AXI_07_WSTRB;
+ input AXI_07_WVALID;
+ (* invertible_pin = "IS_AXI_08_ACLK_INVERTED" *)
+ input AXI_08_ACLK;
+ input [36:0] AXI_08_ARADDR;
+ input [1:0] AXI_08_ARBURST;
+ (* invertible_pin = "IS_AXI_08_ARESET_N_INVERTED" *)
+ input AXI_08_ARESET_N;
+ input [5:0] AXI_08_ARID;
+ input [3:0] AXI_08_ARLEN;
+ input [2:0] AXI_08_ARSIZE;
+ input AXI_08_ARVALID;
+ input [36:0] AXI_08_AWADDR;
+ input [1:0] AXI_08_AWBURST;
+ input [5:0] AXI_08_AWID;
+ input [3:0] AXI_08_AWLEN;
+ input [2:0] AXI_08_AWSIZE;
+ input AXI_08_AWVALID;
+ input AXI_08_BREADY;
+ input AXI_08_DFI_LP_PWR_X_REQ;
+ input AXI_08_RREADY;
+ input [255:0] AXI_08_WDATA;
+ input [31:0] AXI_08_WDATA_PARITY;
+ input AXI_08_WLAST;
+ input [31:0] AXI_08_WSTRB;
+ input AXI_08_WVALID;
+ (* invertible_pin = "IS_AXI_09_ACLK_INVERTED" *)
+ input AXI_09_ACLK;
+ input [36:0] AXI_09_ARADDR;
+ input [1:0] AXI_09_ARBURST;
+ (* invertible_pin = "IS_AXI_09_ARESET_N_INVERTED" *)
+ input AXI_09_ARESET_N;
+ input [5:0] AXI_09_ARID;
+ input [3:0] AXI_09_ARLEN;
+ input [2:0] AXI_09_ARSIZE;
+ input AXI_09_ARVALID;
+ input [36:0] AXI_09_AWADDR;
+ input [1:0] AXI_09_AWBURST;
+ input [5:0] AXI_09_AWID;
+ input [3:0] AXI_09_AWLEN;
+ input [2:0] AXI_09_AWSIZE;
+ input AXI_09_AWVALID;
+ input AXI_09_BREADY;
+ input AXI_09_DFI_LP_PWR_X_REQ;
+ input AXI_09_RREADY;
+ input [255:0] AXI_09_WDATA;
+ input [31:0] AXI_09_WDATA_PARITY;
+ input AXI_09_WLAST;
+ input [31:0] AXI_09_WSTRB;
+ input AXI_09_WVALID;
+ (* invertible_pin = "IS_AXI_10_ACLK_INVERTED" *)
+ input AXI_10_ACLK;
+ input [36:0] AXI_10_ARADDR;
+ input [1:0] AXI_10_ARBURST;
+ (* invertible_pin = "IS_AXI_10_ARESET_N_INVERTED" *)
+ input AXI_10_ARESET_N;
+ input [5:0] AXI_10_ARID;
+ input [3:0] AXI_10_ARLEN;
+ input [2:0] AXI_10_ARSIZE;
+ input AXI_10_ARVALID;
+ input [36:0] AXI_10_AWADDR;
+ input [1:0] AXI_10_AWBURST;
+ input [5:0] AXI_10_AWID;
+ input [3:0] AXI_10_AWLEN;
+ input [2:0] AXI_10_AWSIZE;
+ input AXI_10_AWVALID;
+ input AXI_10_BREADY;
+ input AXI_10_DFI_LP_PWR_X_REQ;
+ input AXI_10_RREADY;
+ input [255:0] AXI_10_WDATA;
+ input [31:0] AXI_10_WDATA_PARITY;
+ input AXI_10_WLAST;
+ input [31:0] AXI_10_WSTRB;
+ input AXI_10_WVALID;
+ (* invertible_pin = "IS_AXI_11_ACLK_INVERTED" *)
+ input AXI_11_ACLK;
+ input [36:0] AXI_11_ARADDR;
+ input [1:0] AXI_11_ARBURST;
+ (* invertible_pin = "IS_AXI_11_ARESET_N_INVERTED" *)
+ input AXI_11_ARESET_N;
+ input [5:0] AXI_11_ARID;
+ input [3:0] AXI_11_ARLEN;
+ input [2:0] AXI_11_ARSIZE;
+ input AXI_11_ARVALID;
+ input [36:0] AXI_11_AWADDR;
+ input [1:0] AXI_11_AWBURST;
+ input [5:0] AXI_11_AWID;
+ input [3:0] AXI_11_AWLEN;
+ input [2:0] AXI_11_AWSIZE;
+ input AXI_11_AWVALID;
+ input AXI_11_BREADY;
+ input AXI_11_DFI_LP_PWR_X_REQ;
+ input AXI_11_RREADY;
+ input [255:0] AXI_11_WDATA;
+ input [31:0] AXI_11_WDATA_PARITY;
+ input AXI_11_WLAST;
+ input [31:0] AXI_11_WSTRB;
+ input AXI_11_WVALID;
+ (* invertible_pin = "IS_AXI_12_ACLK_INVERTED" *)
+ input AXI_12_ACLK;
+ input [36:0] AXI_12_ARADDR;
+ input [1:0] AXI_12_ARBURST;
+ (* invertible_pin = "IS_AXI_12_ARESET_N_INVERTED" *)
+ input AXI_12_ARESET_N;
+ input [5:0] AXI_12_ARID;
+ input [3:0] AXI_12_ARLEN;
+ input [2:0] AXI_12_ARSIZE;
+ input AXI_12_ARVALID;
+ input [36:0] AXI_12_AWADDR;
+ input [1:0] AXI_12_AWBURST;
+ input [5:0] AXI_12_AWID;
+ input [3:0] AXI_12_AWLEN;
+ input [2:0] AXI_12_AWSIZE;
+ input AXI_12_AWVALID;
+ input AXI_12_BREADY;
+ input AXI_12_DFI_LP_PWR_X_REQ;
+ input AXI_12_RREADY;
+ input [255:0] AXI_12_WDATA;
+ input [31:0] AXI_12_WDATA_PARITY;
+ input AXI_12_WLAST;
+ input [31:0] AXI_12_WSTRB;
+ input AXI_12_WVALID;
+ (* invertible_pin = "IS_AXI_13_ACLK_INVERTED" *)
+ input AXI_13_ACLK;
+ input [36:0] AXI_13_ARADDR;
+ input [1:0] AXI_13_ARBURST;
+ (* invertible_pin = "IS_AXI_13_ARESET_N_INVERTED" *)
+ input AXI_13_ARESET_N;
+ input [5:0] AXI_13_ARID;
+ input [3:0] AXI_13_ARLEN;
+ input [2:0] AXI_13_ARSIZE;
+ input AXI_13_ARVALID;
+ input [36:0] AXI_13_AWADDR;
+ input [1:0] AXI_13_AWBURST;
+ input [5:0] AXI_13_AWID;
+ input [3:0] AXI_13_AWLEN;
+ input [2:0] AXI_13_AWSIZE;
+ input AXI_13_AWVALID;
+ input AXI_13_BREADY;
+ input AXI_13_DFI_LP_PWR_X_REQ;
+ input AXI_13_RREADY;
+ input [255:0] AXI_13_WDATA;
+ input [31:0] AXI_13_WDATA_PARITY;
+ input AXI_13_WLAST;
+ input [31:0] AXI_13_WSTRB;
+ input AXI_13_WVALID;
+ (* invertible_pin = "IS_AXI_14_ACLK_INVERTED" *)
+ input AXI_14_ACLK;
+ input [36:0] AXI_14_ARADDR;
+ input [1:0] AXI_14_ARBURST;
+ (* invertible_pin = "IS_AXI_14_ARESET_N_INVERTED" *)
+ input AXI_14_ARESET_N;
+ input [5:0] AXI_14_ARID;
+ input [3:0] AXI_14_ARLEN;
+ input [2:0] AXI_14_ARSIZE;
+ input AXI_14_ARVALID;
+ input [36:0] AXI_14_AWADDR;
+ input [1:0] AXI_14_AWBURST;
+ input [5:0] AXI_14_AWID;
+ input [3:0] AXI_14_AWLEN;
+ input [2:0] AXI_14_AWSIZE;
+ input AXI_14_AWVALID;
+ input AXI_14_BREADY;
+ input AXI_14_DFI_LP_PWR_X_REQ;
+ input AXI_14_RREADY;
+ input [255:0] AXI_14_WDATA;
+ input [31:0] AXI_14_WDATA_PARITY;
+ input AXI_14_WLAST;
+ input [31:0] AXI_14_WSTRB;
+ input AXI_14_WVALID;
+ (* invertible_pin = "IS_AXI_15_ACLK_INVERTED" *)
+ input AXI_15_ACLK;
+ input [36:0] AXI_15_ARADDR;
+ input [1:0] AXI_15_ARBURST;
+ (* invertible_pin = "IS_AXI_15_ARESET_N_INVERTED" *)
+ input AXI_15_ARESET_N;
+ input [5:0] AXI_15_ARID;
+ input [3:0] AXI_15_ARLEN;
+ input [2:0] AXI_15_ARSIZE;
+ input AXI_15_ARVALID;
+ input [36:0] AXI_15_AWADDR;
+ input [1:0] AXI_15_AWBURST;
+ input [5:0] AXI_15_AWID;
+ input [3:0] AXI_15_AWLEN;
+ input [2:0] AXI_15_AWSIZE;
+ input AXI_15_AWVALID;
+ input AXI_15_BREADY;
+ input AXI_15_DFI_LP_PWR_X_REQ;
+ input AXI_15_RREADY;
+ input [255:0] AXI_15_WDATA;
+ input [31:0] AXI_15_WDATA_PARITY;
+ input AXI_15_WLAST;
+ input [31:0] AXI_15_WSTRB;
+ input AXI_15_WVALID;
+ input BSCAN_DRCK;
+ input BSCAN_TCK;
+ input HBM_REF_CLK;
+ input MBIST_EN_00;
+ input MBIST_EN_01;
+ input MBIST_EN_02;
+ input MBIST_EN_03;
+ input MBIST_EN_04;
+ input MBIST_EN_05;
+ input MBIST_EN_06;
+ input MBIST_EN_07;
+endmodule
+
+(* keep *)
+module HBM_TWO_STACK_INTF (...);
+ parameter CLK_SEL_00 = "FALSE";
+ parameter CLK_SEL_01 = "FALSE";
+ parameter CLK_SEL_02 = "FALSE";
+ parameter CLK_SEL_03 = "FALSE";
+ parameter CLK_SEL_04 = "FALSE";
+ parameter CLK_SEL_05 = "FALSE";
+ parameter CLK_SEL_06 = "FALSE";
+ parameter CLK_SEL_07 = "FALSE";
+ parameter CLK_SEL_08 = "FALSE";
+ parameter CLK_SEL_09 = "FALSE";
+ parameter CLK_SEL_10 = "FALSE";
+ parameter CLK_SEL_11 = "FALSE";
+ parameter CLK_SEL_12 = "FALSE";
+ parameter CLK_SEL_13 = "FALSE";
+ parameter CLK_SEL_14 = "FALSE";
+ parameter CLK_SEL_15 = "FALSE";
+ parameter CLK_SEL_16 = "FALSE";
+ parameter CLK_SEL_17 = "FALSE";
+ parameter CLK_SEL_18 = "FALSE";
+ parameter CLK_SEL_19 = "FALSE";
+ parameter CLK_SEL_20 = "FALSE";
+ parameter CLK_SEL_21 = "FALSE";
+ parameter CLK_SEL_22 = "FALSE";
+ parameter CLK_SEL_23 = "FALSE";
+ parameter CLK_SEL_24 = "FALSE";
+ parameter CLK_SEL_25 = "FALSE";
+ parameter CLK_SEL_26 = "FALSE";
+ parameter CLK_SEL_27 = "FALSE";
+ parameter CLK_SEL_28 = "FALSE";
+ parameter CLK_SEL_29 = "FALSE";
+ parameter CLK_SEL_30 = "FALSE";
+ parameter CLK_SEL_31 = "FALSE";
+ parameter integer DATARATE_00 = 1800;
+ parameter integer DATARATE_01 = 1800;
+ parameter integer DATARATE_02 = 1800;
+ parameter integer DATARATE_03 = 1800;
+ parameter integer DATARATE_04 = 1800;
+ parameter integer DATARATE_05 = 1800;
+ parameter integer DATARATE_06 = 1800;
+ parameter integer DATARATE_07 = 1800;
+ parameter integer DATARATE_08 = 1800;
+ parameter integer DATARATE_09 = 1800;
+ parameter integer DATARATE_10 = 1800;
+ parameter integer DATARATE_11 = 1800;
+ parameter integer DATARATE_12 = 1800;
+ parameter integer DATARATE_13 = 1800;
+ parameter integer DATARATE_14 = 1800;
+ parameter integer DATARATE_15 = 1800;
+ parameter DA_LOCKOUT_0 = "FALSE";
+ parameter DA_LOCKOUT_1 = "FALSE";
+ parameter [0:0] IS_APB_0_PCLK_INVERTED = 1'b0;
+ parameter [0:0] IS_APB_0_PRESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_APB_1_PCLK_INVERTED = 1'b0;
+ parameter [0:0] IS_APB_1_PRESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_00_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_00_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_01_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_01_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_02_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_02_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_03_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_03_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_04_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_04_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_05_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_05_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_06_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_06_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_07_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_07_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_08_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_08_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_09_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_09_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_10_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_10_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_11_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_11_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_12_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_12_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_13_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_13_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_14_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_14_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_15_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_15_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_16_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_16_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_17_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_17_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_18_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_18_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_19_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_19_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_20_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_20_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_21_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_21_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_22_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_22_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_23_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_23_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_24_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_24_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_25_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_25_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_26_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_26_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_27_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_27_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_28_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_28_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_29_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_29_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_30_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_30_ARESET_N_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_31_ACLK_INVERTED = 1'b0;
+ parameter [0:0] IS_AXI_31_ARESET_N_INVERTED = 1'b0;
+ parameter MC_ENABLE_00 = "FALSE";
+ parameter MC_ENABLE_01 = "FALSE";
+ parameter MC_ENABLE_02 = "FALSE";
+ parameter MC_ENABLE_03 = "FALSE";
+ parameter MC_ENABLE_04 = "FALSE";
+ parameter MC_ENABLE_05 = "FALSE";
+ parameter MC_ENABLE_06 = "FALSE";
+ parameter MC_ENABLE_07 = "FALSE";
+ parameter MC_ENABLE_08 = "FALSE";
+ parameter MC_ENABLE_09 = "FALSE";
+ parameter MC_ENABLE_10 = "FALSE";
+ parameter MC_ENABLE_11 = "FALSE";
+ parameter MC_ENABLE_12 = "FALSE";
+ parameter MC_ENABLE_13 = "FALSE";
+ parameter MC_ENABLE_14 = "FALSE";
+ parameter MC_ENABLE_15 = "FALSE";
+ parameter MC_ENABLE_APB_00 = "FALSE";
+ parameter MC_ENABLE_APB_01 = "FALSE";
+ parameter integer PAGEHIT_PERCENT_00 = 75;
+ parameter integer PAGEHIT_PERCENT_01 = 75;
+ parameter PHY_ENABLE_00 = "FALSE";
+ parameter PHY_ENABLE_01 = "FALSE";
+ parameter PHY_ENABLE_02 = "FALSE";
+ parameter PHY_ENABLE_03 = "FALSE";
+ parameter PHY_ENABLE_04 = "FALSE";
+ parameter PHY_ENABLE_05 = "FALSE";
+ parameter PHY_ENABLE_06 = "FALSE";
+ parameter PHY_ENABLE_07 = "FALSE";
+ parameter PHY_ENABLE_08 = "FALSE";
+ parameter PHY_ENABLE_09 = "FALSE";
+ parameter PHY_ENABLE_10 = "FALSE";
+ parameter PHY_ENABLE_11 = "FALSE";
+ parameter PHY_ENABLE_12 = "FALSE";
+ parameter PHY_ENABLE_13 = "FALSE";
+ parameter PHY_ENABLE_14 = "FALSE";
+ parameter PHY_ENABLE_15 = "FALSE";
+ parameter PHY_ENABLE_16 = "FALSE";
+ parameter PHY_ENABLE_17 = "FALSE";
+ parameter PHY_ENABLE_18 = "FALSE";
+ parameter PHY_ENABLE_19 = "FALSE";
+ parameter PHY_ENABLE_20 = "FALSE";
+ parameter PHY_ENABLE_21 = "FALSE";
+ parameter PHY_ENABLE_22 = "FALSE";
+ parameter PHY_ENABLE_23 = "FALSE";
+ parameter PHY_ENABLE_24 = "FALSE";
+ parameter PHY_ENABLE_25 = "FALSE";
+ parameter PHY_ENABLE_26 = "FALSE";
+ parameter PHY_ENABLE_27 = "FALSE";
+ parameter PHY_ENABLE_28 = "FALSE";
+ parameter PHY_ENABLE_29 = "FALSE";
+ parameter PHY_ENABLE_30 = "FALSE";
+ parameter PHY_ENABLE_31 = "FALSE";
+ parameter PHY_ENABLE_APB_00 = "FALSE";
+ parameter PHY_ENABLE_APB_01 = "FALSE";
+ parameter PHY_PCLK_INVERT_01 = "FALSE";
+ parameter PHY_PCLK_INVERT_02 = "FALSE";
+ parameter integer READ_PERCENT_00 = 50;
+ parameter integer READ_PERCENT_01 = 50;
+ parameter integer READ_PERCENT_02 = 50;
+ parameter integer READ_PERCENT_03 = 50;
+ parameter integer READ_PERCENT_04 = 50;
+ parameter integer READ_PERCENT_05 = 50;
+ parameter integer READ_PERCENT_06 = 50;
+ parameter integer READ_PERCENT_07 = 50;
+ parameter integer READ_PERCENT_08 = 50;
+ parameter integer READ_PERCENT_09 = 50;
+ parameter integer READ_PERCENT_10 = 50;
+ parameter integer READ_PERCENT_11 = 50;
+ parameter integer READ_PERCENT_12 = 50;
+ parameter integer READ_PERCENT_13 = 50;
+ parameter integer READ_PERCENT_14 = 50;
+ parameter integer READ_PERCENT_15 = 50;
+ parameter integer READ_PERCENT_16 = 50;
+ parameter integer READ_PERCENT_17 = 50;
+ parameter integer READ_PERCENT_18 = 50;
+ parameter integer READ_PERCENT_19 = 50;
+ parameter integer READ_PERCENT_20 = 50;
+ parameter integer READ_PERCENT_21 = 50;
+ parameter integer READ_PERCENT_22 = 50;
+ parameter integer READ_PERCENT_23 = 50;
+ parameter integer READ_PERCENT_24 = 50;
+ parameter integer READ_PERCENT_25 = 50;
+ parameter integer READ_PERCENT_26 = 50;
+ parameter integer READ_PERCENT_27 = 50;
+ parameter integer READ_PERCENT_28 = 50;
+ parameter integer READ_PERCENT_29 = 50;
+ parameter integer READ_PERCENT_30 = 50;
+ parameter integer READ_PERCENT_31 = 50;
+ parameter SIM_DEVICE = "ULTRASCALE_PLUS";
+ parameter SWITCH_ENABLE_00 = "FALSE";
+ parameter SWITCH_ENABLE_01 = "FALSE";
+ parameter integer WRITE_PERCENT_00 = 50;
+ parameter integer WRITE_PERCENT_01 = 50;
+ parameter integer WRITE_PERCENT_02 = 50;
+ parameter integer WRITE_PERCENT_03 = 50;
+ parameter integer WRITE_PERCENT_04 = 50;
+ parameter integer WRITE_PERCENT_05 = 50;
+ parameter integer WRITE_PERCENT_06 = 50;
+ parameter integer WRITE_PERCENT_07 = 50;
+ parameter integer WRITE_PERCENT_08 = 50;
+ parameter integer WRITE_PERCENT_09 = 50;
+ parameter integer WRITE_PERCENT_10 = 50;
+ parameter integer WRITE_PERCENT_11 = 50;
+ parameter integer WRITE_PERCENT_12 = 50;
+ parameter integer WRITE_PERCENT_13 = 50;
+ parameter integer WRITE_PERCENT_14 = 50;
+ parameter integer WRITE_PERCENT_15 = 50;
+ parameter integer WRITE_PERCENT_16 = 50;
+ parameter integer WRITE_PERCENT_17 = 50;
+ parameter integer WRITE_PERCENT_18 = 50;
+ parameter integer WRITE_PERCENT_19 = 50;
+ parameter integer WRITE_PERCENT_20 = 50;
+ parameter integer WRITE_PERCENT_21 = 50;
+ parameter integer WRITE_PERCENT_22 = 50;
+ parameter integer WRITE_PERCENT_23 = 50;
+ parameter integer WRITE_PERCENT_24 = 50;
+ parameter integer WRITE_PERCENT_25 = 50;
+ parameter integer WRITE_PERCENT_26 = 50;
+ parameter integer WRITE_PERCENT_27 = 50;
+ parameter integer WRITE_PERCENT_28 = 50;
+ parameter integer WRITE_PERCENT_29 = 50;
+ parameter integer WRITE_PERCENT_30 = 50;
+ parameter integer WRITE_PERCENT_31 = 50;
+ output [31:0] APB_0_PRDATA;
+ output APB_0_PREADY;
+ output APB_0_PSLVERR;
+ output [31:0] APB_1_PRDATA;
+ output APB_1_PREADY;
+ output APB_1_PSLVERR;
+ output AXI_00_ARREADY;
+ output AXI_00_AWREADY;
+ output [5:0] AXI_00_BID;
+ output [1:0] AXI_00_BRESP;
+ output AXI_00_BVALID;
+ output [1:0] AXI_00_DFI_AW_AERR_N;
+ output AXI_00_DFI_CLK_BUF;
+ output [7:0] AXI_00_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_00_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_00_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_00_DFI_DW_RDDATA_VALID;
+ output AXI_00_DFI_INIT_COMPLETE;
+ output AXI_00_DFI_PHYUPD_REQ;
+ output AXI_00_DFI_PHY_LP_STATE;
+ output AXI_00_DFI_RST_N_BUF;
+ output [5:0] AXI_00_MC_STATUS;
+ output [7:0] AXI_00_PHY_STATUS;
+ output [255:0] AXI_00_RDATA;
+ output [31:0] AXI_00_RDATA_PARITY;
+ output [5:0] AXI_00_RID;
+ output AXI_00_RLAST;
+ output [1:0] AXI_00_RRESP;
+ output AXI_00_RVALID;
+ output AXI_00_WREADY;
+ output AXI_01_ARREADY;
+ output AXI_01_AWREADY;
+ output [5:0] AXI_01_BID;
+ output [1:0] AXI_01_BRESP;
+ output AXI_01_BVALID;
+ output [1:0] AXI_01_DFI_AW_AERR_N;
+ output AXI_01_DFI_CLK_BUF;
+ output [7:0] AXI_01_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_01_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_01_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_01_DFI_DW_RDDATA_VALID;
+ output AXI_01_DFI_INIT_COMPLETE;
+ output AXI_01_DFI_PHYUPD_REQ;
+ output AXI_01_DFI_PHY_LP_STATE;
+ output AXI_01_DFI_RST_N_BUF;
+ output [255:0] AXI_01_RDATA;
+ output [31:0] AXI_01_RDATA_PARITY;
+ output [5:0] AXI_01_RID;
+ output AXI_01_RLAST;
+ output [1:0] AXI_01_RRESP;
+ output AXI_01_RVALID;
+ output AXI_01_WREADY;
+ output AXI_02_ARREADY;
+ output AXI_02_AWREADY;
+ output [5:0] AXI_02_BID;
+ output [1:0] AXI_02_BRESP;
+ output AXI_02_BVALID;
+ output [1:0] AXI_02_DFI_AW_AERR_N;
+ output AXI_02_DFI_CLK_BUF;
+ output [7:0] AXI_02_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_02_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_02_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_02_DFI_DW_RDDATA_VALID;
+ output AXI_02_DFI_INIT_COMPLETE;
+ output AXI_02_DFI_PHYUPD_REQ;
+ output AXI_02_DFI_PHY_LP_STATE;
+ output AXI_02_DFI_RST_N_BUF;
+ output [5:0] AXI_02_MC_STATUS;
+ output [7:0] AXI_02_PHY_STATUS;
+ output [255:0] AXI_02_RDATA;
+ output [31:0] AXI_02_RDATA_PARITY;
+ output [5:0] AXI_02_RID;
+ output AXI_02_RLAST;
+ output [1:0] AXI_02_RRESP;
+ output AXI_02_RVALID;
+ output AXI_02_WREADY;
+ output AXI_03_ARREADY;
+ output AXI_03_AWREADY;
+ output [5:0] AXI_03_BID;
+ output [1:0] AXI_03_BRESP;
+ output AXI_03_BVALID;
+ output [1:0] AXI_03_DFI_AW_AERR_N;
+ output AXI_03_DFI_CLK_BUF;
+ output [7:0] AXI_03_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_03_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_03_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_03_DFI_DW_RDDATA_VALID;
+ output AXI_03_DFI_INIT_COMPLETE;
+ output AXI_03_DFI_PHYUPD_REQ;
+ output AXI_03_DFI_PHY_LP_STATE;
+ output AXI_03_DFI_RST_N_BUF;
+ output [255:0] AXI_03_RDATA;
+ output [31:0] AXI_03_RDATA_PARITY;
+ output [5:0] AXI_03_RID;
+ output AXI_03_RLAST;
+ output [1:0] AXI_03_RRESP;
+ output AXI_03_RVALID;
+ output AXI_03_WREADY;
+ output AXI_04_ARREADY;
+ output AXI_04_AWREADY;
+ output [5:0] AXI_04_BID;
+ output [1:0] AXI_04_BRESP;
+ output AXI_04_BVALID;
+ output [1:0] AXI_04_DFI_AW_AERR_N;
+ output AXI_04_DFI_CLK_BUF;
+ output [7:0] AXI_04_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_04_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_04_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_04_DFI_DW_RDDATA_VALID;
+ output AXI_04_DFI_INIT_COMPLETE;
+ output AXI_04_DFI_PHYUPD_REQ;
+ output AXI_04_DFI_PHY_LP_STATE;
+ output AXI_04_DFI_RST_N_BUF;
+ output [5:0] AXI_04_MC_STATUS;
+ output [7:0] AXI_04_PHY_STATUS;
+ output [255:0] AXI_04_RDATA;
+ output [31:0] AXI_04_RDATA_PARITY;
+ output [5:0] AXI_04_RID;
+ output AXI_04_RLAST;
+ output [1:0] AXI_04_RRESP;
+ output AXI_04_RVALID;
+ output AXI_04_WREADY;
+ output AXI_05_ARREADY;
+ output AXI_05_AWREADY;
+ output [5:0] AXI_05_BID;
+ output [1:0] AXI_05_BRESP;
+ output AXI_05_BVALID;
+ output [1:0] AXI_05_DFI_AW_AERR_N;
+ output AXI_05_DFI_CLK_BUF;
+ output [7:0] AXI_05_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_05_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_05_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_05_DFI_DW_RDDATA_VALID;
+ output AXI_05_DFI_INIT_COMPLETE;
+ output AXI_05_DFI_PHYUPD_REQ;
+ output AXI_05_DFI_PHY_LP_STATE;
+ output AXI_05_DFI_RST_N_BUF;
+ output [255:0] AXI_05_RDATA;
+ output [31:0] AXI_05_RDATA_PARITY;
+ output [5:0] AXI_05_RID;
+ output AXI_05_RLAST;
+ output [1:0] AXI_05_RRESP;
+ output AXI_05_RVALID;
+ output AXI_05_WREADY;
+ output AXI_06_ARREADY;
+ output AXI_06_AWREADY;
+ output [5:0] AXI_06_BID;
+ output [1:0] AXI_06_BRESP;
+ output AXI_06_BVALID;
+ output [1:0] AXI_06_DFI_AW_AERR_N;
+ output AXI_06_DFI_CLK_BUF;
+ output [7:0] AXI_06_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_06_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_06_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_06_DFI_DW_RDDATA_VALID;
+ output AXI_06_DFI_INIT_COMPLETE;
+ output AXI_06_DFI_PHYUPD_REQ;
+ output AXI_06_DFI_PHY_LP_STATE;
+ output AXI_06_DFI_RST_N_BUF;
+ output [5:0] AXI_06_MC_STATUS;
+ output [7:0] AXI_06_PHY_STATUS;
+ output [255:0] AXI_06_RDATA;
+ output [31:0] AXI_06_RDATA_PARITY;
+ output [5:0] AXI_06_RID;
+ output AXI_06_RLAST;
+ output [1:0] AXI_06_RRESP;
+ output AXI_06_RVALID;
+ output AXI_06_WREADY;
+ output AXI_07_ARREADY;
+ output AXI_07_AWREADY;
+ output [5:0] AXI_07_BID;
+ output [1:0] AXI_07_BRESP;
+ output AXI_07_BVALID;
+ output [1:0] AXI_07_DFI_AW_AERR_N;
+ output AXI_07_DFI_CLK_BUF;
+ output [7:0] AXI_07_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_07_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_07_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_07_DFI_DW_RDDATA_VALID;
+ output AXI_07_DFI_INIT_COMPLETE;
+ output AXI_07_DFI_PHYUPD_REQ;
+ output AXI_07_DFI_PHY_LP_STATE;
+ output AXI_07_DFI_RST_N_BUF;
+ output [255:0] AXI_07_RDATA;
+ output [31:0] AXI_07_RDATA_PARITY;
+ output [5:0] AXI_07_RID;
+ output AXI_07_RLAST;
+ output [1:0] AXI_07_RRESP;
+ output AXI_07_RVALID;
+ output AXI_07_WREADY;
+ output AXI_08_ARREADY;
+ output AXI_08_AWREADY;
+ output [5:0] AXI_08_BID;
+ output [1:0] AXI_08_BRESP;
+ output AXI_08_BVALID;
+ output [1:0] AXI_08_DFI_AW_AERR_N;
+ output AXI_08_DFI_CLK_BUF;
+ output [7:0] AXI_08_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_08_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_08_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_08_DFI_DW_RDDATA_VALID;
+ output AXI_08_DFI_INIT_COMPLETE;
+ output AXI_08_DFI_PHYUPD_REQ;
+ output AXI_08_DFI_PHY_LP_STATE;
+ output AXI_08_DFI_RST_N_BUF;
+ output [5:0] AXI_08_MC_STATUS;
+ output [7:0] AXI_08_PHY_STATUS;
+ output [255:0] AXI_08_RDATA;
+ output [31:0] AXI_08_RDATA_PARITY;
+ output [5:0] AXI_08_RID;
+ output AXI_08_RLAST;
+ output [1:0] AXI_08_RRESP;
+ output AXI_08_RVALID;
+ output AXI_08_WREADY;
+ output AXI_09_ARREADY;
+ output AXI_09_AWREADY;
+ output [5:0] AXI_09_BID;
+ output [1:0] AXI_09_BRESP;
+ output AXI_09_BVALID;
+ output [1:0] AXI_09_DFI_AW_AERR_N;
+ output AXI_09_DFI_CLK_BUF;
+ output [7:0] AXI_09_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_09_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_09_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_09_DFI_DW_RDDATA_VALID;
+ output AXI_09_DFI_INIT_COMPLETE;
+ output AXI_09_DFI_PHYUPD_REQ;
+ output AXI_09_DFI_PHY_LP_STATE;
+ output AXI_09_DFI_RST_N_BUF;
+ output [255:0] AXI_09_RDATA;
+ output [31:0] AXI_09_RDATA_PARITY;
+ output [5:0] AXI_09_RID;
+ output AXI_09_RLAST;
+ output [1:0] AXI_09_RRESP;
+ output AXI_09_RVALID;
+ output AXI_09_WREADY;
+ output AXI_10_ARREADY;
+ output AXI_10_AWREADY;
+ output [5:0] AXI_10_BID;
+ output [1:0] AXI_10_BRESP;
+ output AXI_10_BVALID;
+ output [1:0] AXI_10_DFI_AW_AERR_N;
+ output AXI_10_DFI_CLK_BUF;
+ output [7:0] AXI_10_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_10_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_10_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_10_DFI_DW_RDDATA_VALID;
+ output AXI_10_DFI_INIT_COMPLETE;
+ output AXI_10_DFI_PHYUPD_REQ;
+ output AXI_10_DFI_PHY_LP_STATE;
+ output AXI_10_DFI_RST_N_BUF;
+ output [5:0] AXI_10_MC_STATUS;
+ output [7:0] AXI_10_PHY_STATUS;
+ output [255:0] AXI_10_RDATA;
+ output [31:0] AXI_10_RDATA_PARITY;
+ output [5:0] AXI_10_RID;
+ output AXI_10_RLAST;
+ output [1:0] AXI_10_RRESP;
+ output AXI_10_RVALID;
+ output AXI_10_WREADY;
+ output AXI_11_ARREADY;
+ output AXI_11_AWREADY;
+ output [5:0] AXI_11_BID;
+ output [1:0] AXI_11_BRESP;
+ output AXI_11_BVALID;
+ output [1:0] AXI_11_DFI_AW_AERR_N;
+ output AXI_11_DFI_CLK_BUF;
+ output [7:0] AXI_11_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_11_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_11_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_11_DFI_DW_RDDATA_VALID;
+ output AXI_11_DFI_INIT_COMPLETE;
+ output AXI_11_DFI_PHYUPD_REQ;
+ output AXI_11_DFI_PHY_LP_STATE;
+ output AXI_11_DFI_RST_N_BUF;
+ output [255:0] AXI_11_RDATA;
+ output [31:0] AXI_11_RDATA_PARITY;
+ output [5:0] AXI_11_RID;
+ output AXI_11_RLAST;
+ output [1:0] AXI_11_RRESP;
+ output AXI_11_RVALID;
+ output AXI_11_WREADY;
+ output AXI_12_ARREADY;
+ output AXI_12_AWREADY;
+ output [5:0] AXI_12_BID;
+ output [1:0] AXI_12_BRESP;
+ output AXI_12_BVALID;
+ output [1:0] AXI_12_DFI_AW_AERR_N;
+ output AXI_12_DFI_CLK_BUF;
+ output [7:0] AXI_12_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_12_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_12_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_12_DFI_DW_RDDATA_VALID;
+ output AXI_12_DFI_INIT_COMPLETE;
+ output AXI_12_DFI_PHYUPD_REQ;
+ output AXI_12_DFI_PHY_LP_STATE;
+ output AXI_12_DFI_RST_N_BUF;
+ output [5:0] AXI_12_MC_STATUS;
+ output [7:0] AXI_12_PHY_STATUS;
+ output [255:0] AXI_12_RDATA;
+ output [31:0] AXI_12_RDATA_PARITY;
+ output [5:0] AXI_12_RID;
+ output AXI_12_RLAST;
+ output [1:0] AXI_12_RRESP;
+ output AXI_12_RVALID;
+ output AXI_12_WREADY;
+ output AXI_13_ARREADY;
+ output AXI_13_AWREADY;
+ output [5:0] AXI_13_BID;
+ output [1:0] AXI_13_BRESP;
+ output AXI_13_BVALID;
+ output [1:0] AXI_13_DFI_AW_AERR_N;
+ output AXI_13_DFI_CLK_BUF;
+ output [7:0] AXI_13_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_13_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_13_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_13_DFI_DW_RDDATA_VALID;
+ output AXI_13_DFI_INIT_COMPLETE;
+ output AXI_13_DFI_PHYUPD_REQ;
+ output AXI_13_DFI_PHY_LP_STATE;
+ output AXI_13_DFI_RST_N_BUF;
+ output [255:0] AXI_13_RDATA;
+ output [31:0] AXI_13_RDATA_PARITY;
+ output [5:0] AXI_13_RID;
+ output AXI_13_RLAST;
+ output [1:0] AXI_13_RRESP;
+ output AXI_13_RVALID;
+ output AXI_13_WREADY;
+ output AXI_14_ARREADY;
+ output AXI_14_AWREADY;
+ output [5:0] AXI_14_BID;
+ output [1:0] AXI_14_BRESP;
+ output AXI_14_BVALID;
+ output [1:0] AXI_14_DFI_AW_AERR_N;
+ output AXI_14_DFI_CLK_BUF;
+ output [7:0] AXI_14_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_14_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_14_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_14_DFI_DW_RDDATA_VALID;
+ output AXI_14_DFI_INIT_COMPLETE;
+ output AXI_14_DFI_PHYUPD_REQ;
+ output AXI_14_DFI_PHY_LP_STATE;
+ output AXI_14_DFI_RST_N_BUF;
+ output [5:0] AXI_14_MC_STATUS;
+ output [7:0] AXI_14_PHY_STATUS;
+ output [255:0] AXI_14_RDATA;
+ output [31:0] AXI_14_RDATA_PARITY;
+ output [5:0] AXI_14_RID;
+ output AXI_14_RLAST;
+ output [1:0] AXI_14_RRESP;
+ output AXI_14_RVALID;
+ output AXI_14_WREADY;
+ output AXI_15_ARREADY;
+ output AXI_15_AWREADY;
+ output [5:0] AXI_15_BID;
+ output [1:0] AXI_15_BRESP;
+ output AXI_15_BVALID;
+ output [1:0] AXI_15_DFI_AW_AERR_N;
+ output AXI_15_DFI_CLK_BUF;
+ output [7:0] AXI_15_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_15_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_15_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_15_DFI_DW_RDDATA_VALID;
+ output AXI_15_DFI_INIT_COMPLETE;
+ output AXI_15_DFI_PHYUPD_REQ;
+ output AXI_15_DFI_PHY_LP_STATE;
+ output AXI_15_DFI_RST_N_BUF;
+ output [255:0] AXI_15_RDATA;
+ output [31:0] AXI_15_RDATA_PARITY;
+ output [5:0] AXI_15_RID;
+ output AXI_15_RLAST;
+ output [1:0] AXI_15_RRESP;
+ output AXI_15_RVALID;
+ output AXI_15_WREADY;
+ output AXI_16_ARREADY;
+ output AXI_16_AWREADY;
+ output [5:0] AXI_16_BID;
+ output [1:0] AXI_16_BRESP;
+ output AXI_16_BVALID;
+ output [1:0] AXI_16_DFI_AW_AERR_N;
+ output AXI_16_DFI_CLK_BUF;
+ output [7:0] AXI_16_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_16_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_16_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_16_DFI_DW_RDDATA_VALID;
+ output AXI_16_DFI_INIT_COMPLETE;
+ output AXI_16_DFI_PHYUPD_REQ;
+ output AXI_16_DFI_PHY_LP_STATE;
+ output AXI_16_DFI_RST_N_BUF;
+ output [5:0] AXI_16_MC_STATUS;
+ output [7:0] AXI_16_PHY_STATUS;
+ output [255:0] AXI_16_RDATA;
+ output [31:0] AXI_16_RDATA_PARITY;
+ output [5:0] AXI_16_RID;
+ output AXI_16_RLAST;
+ output [1:0] AXI_16_RRESP;
+ output AXI_16_RVALID;
+ output AXI_16_WREADY;
+ output AXI_17_ARREADY;
+ output AXI_17_AWREADY;
+ output [5:0] AXI_17_BID;
+ output [1:0] AXI_17_BRESP;
+ output AXI_17_BVALID;
+ output [1:0] AXI_17_DFI_AW_AERR_N;
+ output AXI_17_DFI_CLK_BUF;
+ output [7:0] AXI_17_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_17_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_17_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_17_DFI_DW_RDDATA_VALID;
+ output AXI_17_DFI_INIT_COMPLETE;
+ output AXI_17_DFI_PHYUPD_REQ;
+ output AXI_17_DFI_PHY_LP_STATE;
+ output AXI_17_DFI_RST_N_BUF;
+ output [255:0] AXI_17_RDATA;
+ output [31:0] AXI_17_RDATA_PARITY;
+ output [5:0] AXI_17_RID;
+ output AXI_17_RLAST;
+ output [1:0] AXI_17_RRESP;
+ output AXI_17_RVALID;
+ output AXI_17_WREADY;
+ output AXI_18_ARREADY;
+ output AXI_18_AWREADY;
+ output [5:0] AXI_18_BID;
+ output [1:0] AXI_18_BRESP;
+ output AXI_18_BVALID;
+ output [1:0] AXI_18_DFI_AW_AERR_N;
+ output AXI_18_DFI_CLK_BUF;
+ output [7:0] AXI_18_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_18_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_18_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_18_DFI_DW_RDDATA_VALID;
+ output AXI_18_DFI_INIT_COMPLETE;
+ output AXI_18_DFI_PHYUPD_REQ;
+ output AXI_18_DFI_PHY_LP_STATE;
+ output AXI_18_DFI_RST_N_BUF;
+ output [5:0] AXI_18_MC_STATUS;
+ output [7:0] AXI_18_PHY_STATUS;
+ output [255:0] AXI_18_RDATA;
+ output [31:0] AXI_18_RDATA_PARITY;
+ output [5:0] AXI_18_RID;
+ output AXI_18_RLAST;
+ output [1:0] AXI_18_RRESP;
+ output AXI_18_RVALID;
+ output AXI_18_WREADY;
+ output AXI_19_ARREADY;
+ output AXI_19_AWREADY;
+ output [5:0] AXI_19_BID;
+ output [1:0] AXI_19_BRESP;
+ output AXI_19_BVALID;
+ output [1:0] AXI_19_DFI_AW_AERR_N;
+ output AXI_19_DFI_CLK_BUF;
+ output [7:0] AXI_19_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_19_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_19_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_19_DFI_DW_RDDATA_VALID;
+ output AXI_19_DFI_INIT_COMPLETE;
+ output AXI_19_DFI_PHYUPD_REQ;
+ output AXI_19_DFI_PHY_LP_STATE;
+ output AXI_19_DFI_RST_N_BUF;
+ output [255:0] AXI_19_RDATA;
+ output [31:0] AXI_19_RDATA_PARITY;
+ output [5:0] AXI_19_RID;
+ output AXI_19_RLAST;
+ output [1:0] AXI_19_RRESP;
+ output AXI_19_RVALID;
+ output AXI_19_WREADY;
+ output AXI_20_ARREADY;
+ output AXI_20_AWREADY;
+ output [5:0] AXI_20_BID;
+ output [1:0] AXI_20_BRESP;
+ output AXI_20_BVALID;
+ output [1:0] AXI_20_DFI_AW_AERR_N;
+ output AXI_20_DFI_CLK_BUF;
+ output [7:0] AXI_20_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_20_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_20_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_20_DFI_DW_RDDATA_VALID;
+ output AXI_20_DFI_INIT_COMPLETE;
+ output AXI_20_DFI_PHYUPD_REQ;
+ output AXI_20_DFI_PHY_LP_STATE;
+ output AXI_20_DFI_RST_N_BUF;
+ output [5:0] AXI_20_MC_STATUS;
+ output [7:0] AXI_20_PHY_STATUS;
+ output [255:0] AXI_20_RDATA;
+ output [31:0] AXI_20_RDATA_PARITY;
+ output [5:0] AXI_20_RID;
+ output AXI_20_RLAST;
+ output [1:0] AXI_20_RRESP;
+ output AXI_20_RVALID;
+ output AXI_20_WREADY;
+ output AXI_21_ARREADY;
+ output AXI_21_AWREADY;
+ output [5:0] AXI_21_BID;
+ output [1:0] AXI_21_BRESP;
+ output AXI_21_BVALID;
+ output [1:0] AXI_21_DFI_AW_AERR_N;
+ output AXI_21_DFI_CLK_BUF;
+ output [7:0] AXI_21_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_21_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_21_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_21_DFI_DW_RDDATA_VALID;
+ output AXI_21_DFI_INIT_COMPLETE;
+ output AXI_21_DFI_PHYUPD_REQ;
+ output AXI_21_DFI_PHY_LP_STATE;
+ output AXI_21_DFI_RST_N_BUF;
+ output [255:0] AXI_21_RDATA;
+ output [31:0] AXI_21_RDATA_PARITY;
+ output [5:0] AXI_21_RID;
+ output AXI_21_RLAST;
+ output [1:0] AXI_21_RRESP;
+ output AXI_21_RVALID;
+ output AXI_21_WREADY;
+ output AXI_22_ARREADY;
+ output AXI_22_AWREADY;
+ output [5:0] AXI_22_BID;
+ output [1:0] AXI_22_BRESP;
+ output AXI_22_BVALID;
+ output [1:0] AXI_22_DFI_AW_AERR_N;
+ output AXI_22_DFI_CLK_BUF;
+ output [7:0] AXI_22_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_22_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_22_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_22_DFI_DW_RDDATA_VALID;
+ output AXI_22_DFI_INIT_COMPLETE;
+ output AXI_22_DFI_PHYUPD_REQ;
+ output AXI_22_DFI_PHY_LP_STATE;
+ output AXI_22_DFI_RST_N_BUF;
+ output [5:0] AXI_22_MC_STATUS;
+ output [7:0] AXI_22_PHY_STATUS;
+ output [255:0] AXI_22_RDATA;
+ output [31:0] AXI_22_RDATA_PARITY;
+ output [5:0] AXI_22_RID;
+ output AXI_22_RLAST;
+ output [1:0] AXI_22_RRESP;
+ output AXI_22_RVALID;
+ output AXI_22_WREADY;
+ output AXI_23_ARREADY;
+ output AXI_23_AWREADY;
+ output [5:0] AXI_23_BID;
+ output [1:0] AXI_23_BRESP;
+ output AXI_23_BVALID;
+ output [1:0] AXI_23_DFI_AW_AERR_N;
+ output AXI_23_DFI_CLK_BUF;
+ output [7:0] AXI_23_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_23_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_23_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_23_DFI_DW_RDDATA_VALID;
+ output AXI_23_DFI_INIT_COMPLETE;
+ output AXI_23_DFI_PHYUPD_REQ;
+ output AXI_23_DFI_PHY_LP_STATE;
+ output AXI_23_DFI_RST_N_BUF;
+ output [255:0] AXI_23_RDATA;
+ output [31:0] AXI_23_RDATA_PARITY;
+ output [5:0] AXI_23_RID;
+ output AXI_23_RLAST;
+ output [1:0] AXI_23_RRESP;
+ output AXI_23_RVALID;
+ output AXI_23_WREADY;
+ output AXI_24_ARREADY;
+ output AXI_24_AWREADY;
+ output [5:0] AXI_24_BID;
+ output [1:0] AXI_24_BRESP;
+ output AXI_24_BVALID;
+ output [1:0] AXI_24_DFI_AW_AERR_N;
+ output AXI_24_DFI_CLK_BUF;
+ output [7:0] AXI_24_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_24_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_24_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_24_DFI_DW_RDDATA_VALID;
+ output AXI_24_DFI_INIT_COMPLETE;
+ output AXI_24_DFI_PHYUPD_REQ;
+ output AXI_24_DFI_PHY_LP_STATE;
+ output AXI_24_DFI_RST_N_BUF;
+ output [5:0] AXI_24_MC_STATUS;
+ output [7:0] AXI_24_PHY_STATUS;
+ output [255:0] AXI_24_RDATA;
+ output [31:0] AXI_24_RDATA_PARITY;
+ output [5:0] AXI_24_RID;
+ output AXI_24_RLAST;
+ output [1:0] AXI_24_RRESP;
+ output AXI_24_RVALID;
+ output AXI_24_WREADY;
+ output AXI_25_ARREADY;
+ output AXI_25_AWREADY;
+ output [5:0] AXI_25_BID;
+ output [1:0] AXI_25_BRESP;
+ output AXI_25_BVALID;
+ output [1:0] AXI_25_DFI_AW_AERR_N;
+ output AXI_25_DFI_CLK_BUF;
+ output [7:0] AXI_25_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_25_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_25_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_25_DFI_DW_RDDATA_VALID;
+ output AXI_25_DFI_INIT_COMPLETE;
+ output AXI_25_DFI_PHYUPD_REQ;
+ output AXI_25_DFI_PHY_LP_STATE;
+ output AXI_25_DFI_RST_N_BUF;
+ output [255:0] AXI_25_RDATA;
+ output [31:0] AXI_25_RDATA_PARITY;
+ output [5:0] AXI_25_RID;
+ output AXI_25_RLAST;
+ output [1:0] AXI_25_RRESP;
+ output AXI_25_RVALID;
+ output AXI_25_WREADY;
+ output AXI_26_ARREADY;
+ output AXI_26_AWREADY;
+ output [5:0] AXI_26_BID;
+ output [1:0] AXI_26_BRESP;
+ output AXI_26_BVALID;
+ output [1:0] AXI_26_DFI_AW_AERR_N;
+ output AXI_26_DFI_CLK_BUF;
+ output [7:0] AXI_26_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_26_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_26_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_26_DFI_DW_RDDATA_VALID;
+ output AXI_26_DFI_INIT_COMPLETE;
+ output AXI_26_DFI_PHYUPD_REQ;
+ output AXI_26_DFI_PHY_LP_STATE;
+ output AXI_26_DFI_RST_N_BUF;
+ output [5:0] AXI_26_MC_STATUS;
+ output [7:0] AXI_26_PHY_STATUS;
+ output [255:0] AXI_26_RDATA;
+ output [31:0] AXI_26_RDATA_PARITY;
+ output [5:0] AXI_26_RID;
+ output AXI_26_RLAST;
+ output [1:0] AXI_26_RRESP;
+ output AXI_26_RVALID;
+ output AXI_26_WREADY;
+ output AXI_27_ARREADY;
+ output AXI_27_AWREADY;
+ output [5:0] AXI_27_BID;
+ output [1:0] AXI_27_BRESP;
+ output AXI_27_BVALID;
+ output [1:0] AXI_27_DFI_AW_AERR_N;
+ output AXI_27_DFI_CLK_BUF;
+ output [7:0] AXI_27_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_27_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_27_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_27_DFI_DW_RDDATA_VALID;
+ output AXI_27_DFI_INIT_COMPLETE;
+ output AXI_27_DFI_PHYUPD_REQ;
+ output AXI_27_DFI_PHY_LP_STATE;
+ output AXI_27_DFI_RST_N_BUF;
+ output [255:0] AXI_27_RDATA;
+ output [31:0] AXI_27_RDATA_PARITY;
+ output [5:0] AXI_27_RID;
+ output AXI_27_RLAST;
+ output [1:0] AXI_27_RRESP;
+ output AXI_27_RVALID;
+ output AXI_27_WREADY;
+ output AXI_28_ARREADY;
+ output AXI_28_AWREADY;
+ output [5:0] AXI_28_BID;
+ output [1:0] AXI_28_BRESP;
+ output AXI_28_BVALID;
+ output [1:0] AXI_28_DFI_AW_AERR_N;
+ output AXI_28_DFI_CLK_BUF;
+ output [7:0] AXI_28_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_28_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_28_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_28_DFI_DW_RDDATA_VALID;
+ output AXI_28_DFI_INIT_COMPLETE;
+ output AXI_28_DFI_PHYUPD_REQ;
+ output AXI_28_DFI_PHY_LP_STATE;
+ output AXI_28_DFI_RST_N_BUF;
+ output [5:0] AXI_28_MC_STATUS;
+ output [7:0] AXI_28_PHY_STATUS;
+ output [255:0] AXI_28_RDATA;
+ output [31:0] AXI_28_RDATA_PARITY;
+ output [5:0] AXI_28_RID;
+ output AXI_28_RLAST;
+ output [1:0] AXI_28_RRESP;
+ output AXI_28_RVALID;
+ output AXI_28_WREADY;
+ output AXI_29_ARREADY;
+ output AXI_29_AWREADY;
+ output [5:0] AXI_29_BID;
+ output [1:0] AXI_29_BRESP;
+ output AXI_29_BVALID;
+ output [1:0] AXI_29_DFI_AW_AERR_N;
+ output AXI_29_DFI_CLK_BUF;
+ output [7:0] AXI_29_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_29_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_29_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_29_DFI_DW_RDDATA_VALID;
+ output AXI_29_DFI_INIT_COMPLETE;
+ output AXI_29_DFI_PHYUPD_REQ;
+ output AXI_29_DFI_PHY_LP_STATE;
+ output AXI_29_DFI_RST_N_BUF;
+ output [255:0] AXI_29_RDATA;
+ output [31:0] AXI_29_RDATA_PARITY;
+ output [5:0] AXI_29_RID;
+ output AXI_29_RLAST;
+ output [1:0] AXI_29_RRESP;
+ output AXI_29_RVALID;
+ output AXI_29_WREADY;
+ output AXI_30_ARREADY;
+ output AXI_30_AWREADY;
+ output [5:0] AXI_30_BID;
+ output [1:0] AXI_30_BRESP;
+ output AXI_30_BVALID;
+ output [1:0] AXI_30_DFI_AW_AERR_N;
+ output AXI_30_DFI_CLK_BUF;
+ output [7:0] AXI_30_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_30_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_30_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_30_DFI_DW_RDDATA_VALID;
+ output AXI_30_DFI_INIT_COMPLETE;
+ output AXI_30_DFI_PHYUPD_REQ;
+ output AXI_30_DFI_PHY_LP_STATE;
+ output AXI_30_DFI_RST_N_BUF;
+ output [5:0] AXI_30_MC_STATUS;
+ output [7:0] AXI_30_PHY_STATUS;
+ output [255:0] AXI_30_RDATA;
+ output [31:0] AXI_30_RDATA_PARITY;
+ output [5:0] AXI_30_RID;
+ output AXI_30_RLAST;
+ output [1:0] AXI_30_RRESP;
+ output AXI_30_RVALID;
+ output AXI_30_WREADY;
+ output AXI_31_ARREADY;
+ output AXI_31_AWREADY;
+ output [5:0] AXI_31_BID;
+ output [1:0] AXI_31_BRESP;
+ output AXI_31_BVALID;
+ output [1:0] AXI_31_DFI_AW_AERR_N;
+ output AXI_31_DFI_CLK_BUF;
+ output [7:0] AXI_31_DFI_DBI_BYTE_DISABLE;
+ output [20:0] AXI_31_DFI_DW_RDDATA_DBI;
+ output [7:0] AXI_31_DFI_DW_RDDATA_DERR;
+ output [1:0] AXI_31_DFI_DW_RDDATA_VALID;
+ output AXI_31_DFI_INIT_COMPLETE;
+ output AXI_31_DFI_PHYUPD_REQ;
+ output AXI_31_DFI_PHY_LP_STATE;
+ output AXI_31_DFI_RST_N_BUF;
+ output [255:0] AXI_31_RDATA;
+ output [31:0] AXI_31_RDATA_PARITY;
+ output [5:0] AXI_31_RID;
+ output AXI_31_RLAST;
+ output [1:0] AXI_31_RRESP;
+ output AXI_31_RVALID;
+ output AXI_31_WREADY;
+ output DRAM_0_STAT_CATTRIP;
+ output [2:0] DRAM_0_STAT_TEMP;
+ output DRAM_1_STAT_CATTRIP;
+ output [2:0] DRAM_1_STAT_TEMP;
+ input [21:0] APB_0_PADDR;
+ (* invertible_pin = "IS_APB_0_PCLK_INVERTED" *)
+ input APB_0_PCLK;
+ input APB_0_PENABLE;
+ (* invertible_pin = "IS_APB_0_PRESET_N_INVERTED" *)
+ input APB_0_PRESET_N;
+ input APB_0_PSEL;
+ input [31:0] APB_0_PWDATA;
+ input APB_0_PWRITE;
+ input [21:0] APB_1_PADDR;
+ (* invertible_pin = "IS_APB_1_PCLK_INVERTED" *)
+ input APB_1_PCLK;
+ input APB_1_PENABLE;
+ (* invertible_pin = "IS_APB_1_PRESET_N_INVERTED" *)
+ input APB_1_PRESET_N;
+ input APB_1_PSEL;
+ input [31:0] APB_1_PWDATA;
+ input APB_1_PWRITE;
+ (* invertible_pin = "IS_AXI_00_ACLK_INVERTED" *)
+ input AXI_00_ACLK;
+ input [36:0] AXI_00_ARADDR;
+ input [1:0] AXI_00_ARBURST;
+ (* invertible_pin = "IS_AXI_00_ARESET_N_INVERTED" *)
+ input AXI_00_ARESET_N;
+ input [5:0] AXI_00_ARID;
+ input [3:0] AXI_00_ARLEN;
+ input [2:0] AXI_00_ARSIZE;
+ input AXI_00_ARVALID;
+ input [36:0] AXI_00_AWADDR;
+ input [1:0] AXI_00_AWBURST;
+ input [5:0] AXI_00_AWID;
+ input [3:0] AXI_00_AWLEN;
+ input [2:0] AXI_00_AWSIZE;
+ input AXI_00_AWVALID;
+ input AXI_00_BREADY;
+ input AXI_00_DFI_LP_PWR_X_REQ;
+ input AXI_00_RREADY;
+ input [255:0] AXI_00_WDATA;
+ input [31:0] AXI_00_WDATA_PARITY;
+ input AXI_00_WLAST;
+ input [31:0] AXI_00_WSTRB;
+ input AXI_00_WVALID;
+ (* invertible_pin = "IS_AXI_01_ACLK_INVERTED" *)
+ input AXI_01_ACLK;
+ input [36:0] AXI_01_ARADDR;
+ input [1:0] AXI_01_ARBURST;
+ (* invertible_pin = "IS_AXI_01_ARESET_N_INVERTED" *)
+ input AXI_01_ARESET_N;
+ input [5:0] AXI_01_ARID;
+ input [3:0] AXI_01_ARLEN;
+ input [2:0] AXI_01_ARSIZE;
+ input AXI_01_ARVALID;
+ input [36:0] AXI_01_AWADDR;
+ input [1:0] AXI_01_AWBURST;
+ input [5:0] AXI_01_AWID;
+ input [3:0] AXI_01_AWLEN;
+ input [2:0] AXI_01_AWSIZE;
+ input AXI_01_AWVALID;
+ input AXI_01_BREADY;
+ input AXI_01_DFI_LP_PWR_X_REQ;
+ input AXI_01_RREADY;
+ input [255:0] AXI_01_WDATA;
+ input [31:0] AXI_01_WDATA_PARITY;
+ input AXI_01_WLAST;
+ input [31:0] AXI_01_WSTRB;
+ input AXI_01_WVALID;
+ (* invertible_pin = "IS_AXI_02_ACLK_INVERTED" *)
+ input AXI_02_ACLK;
+ input [36:0] AXI_02_ARADDR;
+ input [1:0] AXI_02_ARBURST;
+ (* invertible_pin = "IS_AXI_02_ARESET_N_INVERTED" *)
+ input AXI_02_ARESET_N;
+ input [5:0] AXI_02_ARID;
+ input [3:0] AXI_02_ARLEN;
+ input [2:0] AXI_02_ARSIZE;
+ input AXI_02_ARVALID;
+ input [36:0] AXI_02_AWADDR;
+ input [1:0] AXI_02_AWBURST;
+ input [5:0] AXI_02_AWID;
+ input [3:0] AXI_02_AWLEN;
+ input [2:0] AXI_02_AWSIZE;
+ input AXI_02_AWVALID;
+ input AXI_02_BREADY;
+ input AXI_02_DFI_LP_PWR_X_REQ;
+ input AXI_02_RREADY;
+ input [255:0] AXI_02_WDATA;
+ input [31:0] AXI_02_WDATA_PARITY;
+ input AXI_02_WLAST;
+ input [31:0] AXI_02_WSTRB;
+ input AXI_02_WVALID;
+ (* invertible_pin = "IS_AXI_03_ACLK_INVERTED" *)
+ input AXI_03_ACLK;
+ input [36:0] AXI_03_ARADDR;
+ input [1:0] AXI_03_ARBURST;
+ (* invertible_pin = "IS_AXI_03_ARESET_N_INVERTED" *)
+ input AXI_03_ARESET_N;
+ input [5:0] AXI_03_ARID;
+ input [3:0] AXI_03_ARLEN;
+ input [2:0] AXI_03_ARSIZE;
+ input AXI_03_ARVALID;
+ input [36:0] AXI_03_AWADDR;
+ input [1:0] AXI_03_AWBURST;
+ input [5:0] AXI_03_AWID;
+ input [3:0] AXI_03_AWLEN;
+ input [2:0] AXI_03_AWSIZE;
+ input AXI_03_AWVALID;
+ input AXI_03_BREADY;
+ input AXI_03_DFI_LP_PWR_X_REQ;
+ input AXI_03_RREADY;
+ input [255:0] AXI_03_WDATA;
+ input [31:0] AXI_03_WDATA_PARITY;
+ input AXI_03_WLAST;
+ input [31:0] AXI_03_WSTRB;
+ input AXI_03_WVALID;
+ (* invertible_pin = "IS_AXI_04_ACLK_INVERTED" *)
+ input AXI_04_ACLK;
+ input [36:0] AXI_04_ARADDR;
+ input [1:0] AXI_04_ARBURST;
+ (* invertible_pin = "IS_AXI_04_ARESET_N_INVERTED" *)
+ input AXI_04_ARESET_N;
+ input [5:0] AXI_04_ARID;
+ input [3:0] AXI_04_ARLEN;
+ input [2:0] AXI_04_ARSIZE;
+ input AXI_04_ARVALID;
+ input [36:0] AXI_04_AWADDR;
+ input [1:0] AXI_04_AWBURST;
+ input [5:0] AXI_04_AWID;
+ input [3:0] AXI_04_AWLEN;
+ input [2:0] AXI_04_AWSIZE;
+ input AXI_04_AWVALID;
+ input AXI_04_BREADY;
+ input AXI_04_DFI_LP_PWR_X_REQ;
+ input AXI_04_RREADY;
+ input [255:0] AXI_04_WDATA;
+ input [31:0] AXI_04_WDATA_PARITY;
+ input AXI_04_WLAST;
+ input [31:0] AXI_04_WSTRB;
+ input AXI_04_WVALID;
+ (* invertible_pin = "IS_AXI_05_ACLK_INVERTED" *)
+ input AXI_05_ACLK;
+ input [36:0] AXI_05_ARADDR;
+ input [1:0] AXI_05_ARBURST;
+ (* invertible_pin = "IS_AXI_05_ARESET_N_INVERTED" *)
+ input AXI_05_ARESET_N;
+ input [5:0] AXI_05_ARID;
+ input [3:0] AXI_05_ARLEN;
+ input [2:0] AXI_05_ARSIZE;
+ input AXI_05_ARVALID;
+ input [36:0] AXI_05_AWADDR;
+ input [1:0] AXI_05_AWBURST;
+ input [5:0] AXI_05_AWID;
+ input [3:0] AXI_05_AWLEN;
+ input [2:0] AXI_05_AWSIZE;
+ input AXI_05_AWVALID;
+ input AXI_05_BREADY;
+ input AXI_05_DFI_LP_PWR_X_REQ;
+ input AXI_05_RREADY;
+ input [255:0] AXI_05_WDATA;
+ input [31:0] AXI_05_WDATA_PARITY;
+ input AXI_05_WLAST;
+ input [31:0] AXI_05_WSTRB;
+ input AXI_05_WVALID;
+ (* invertible_pin = "IS_AXI_06_ACLK_INVERTED" *)
+ input AXI_06_ACLK;
+ input [36:0] AXI_06_ARADDR;
+ input [1:0] AXI_06_ARBURST;
+ (* invertible_pin = "IS_AXI_06_ARESET_N_INVERTED" *)
+ input AXI_06_ARESET_N;
+ input [5:0] AXI_06_ARID;
+ input [3:0] AXI_06_ARLEN;
+ input [2:0] AXI_06_ARSIZE;
+ input AXI_06_ARVALID;
+ input [36:0] AXI_06_AWADDR;
+ input [1:0] AXI_06_AWBURST;
+ input [5:0] AXI_06_AWID;
+ input [3:0] AXI_06_AWLEN;
+ input [2:0] AXI_06_AWSIZE;
+ input AXI_06_AWVALID;
+ input AXI_06_BREADY;
+ input AXI_06_DFI_LP_PWR_X_REQ;
+ input AXI_06_RREADY;
+ input [255:0] AXI_06_WDATA;
+ input [31:0] AXI_06_WDATA_PARITY;
+ input AXI_06_WLAST;
+ input [31:0] AXI_06_WSTRB;
+ input AXI_06_WVALID;
+ (* invertible_pin = "IS_AXI_07_ACLK_INVERTED" *)
+ input AXI_07_ACLK;
+ input [36:0] AXI_07_ARADDR;
+ input [1:0] AXI_07_ARBURST;
+ (* invertible_pin = "IS_AXI_07_ARESET_N_INVERTED" *)
+ input AXI_07_ARESET_N;
+ input [5:0] AXI_07_ARID;
+ input [3:0] AXI_07_ARLEN;
+ input [2:0] AXI_07_ARSIZE;
+ input AXI_07_ARVALID;
+ input [36:0] AXI_07_AWADDR;
+ input [1:0] AXI_07_AWBURST;
+ input [5:0] AXI_07_AWID;
+ input [3:0] AXI_07_AWLEN;
+ input [2:0] AXI_07_AWSIZE;
+ input AXI_07_AWVALID;
+ input AXI_07_BREADY;
+ input AXI_07_DFI_LP_PWR_X_REQ;
+ input AXI_07_RREADY;
+ input [255:0] AXI_07_WDATA;
+ input [31:0] AXI_07_WDATA_PARITY;
+ input AXI_07_WLAST;
+ input [31:0] AXI_07_WSTRB;
+ input AXI_07_WVALID;
+ (* invertible_pin = "IS_AXI_08_ACLK_INVERTED" *)
+ input AXI_08_ACLK;
+ input [36:0] AXI_08_ARADDR;
+ input [1:0] AXI_08_ARBURST;
+ (* invertible_pin = "IS_AXI_08_ARESET_N_INVERTED" *)
+ input AXI_08_ARESET_N;
+ input [5:0] AXI_08_ARID;
+ input [3:0] AXI_08_ARLEN;
+ input [2:0] AXI_08_ARSIZE;
+ input AXI_08_ARVALID;
+ input [36:0] AXI_08_AWADDR;
+ input [1:0] AXI_08_AWBURST;
+ input [5:0] AXI_08_AWID;
+ input [3:0] AXI_08_AWLEN;
+ input [2:0] AXI_08_AWSIZE;
+ input AXI_08_AWVALID;
+ input AXI_08_BREADY;
+ input AXI_08_DFI_LP_PWR_X_REQ;
+ input AXI_08_RREADY;
+ input [255:0] AXI_08_WDATA;
+ input [31:0] AXI_08_WDATA_PARITY;
+ input AXI_08_WLAST;
+ input [31:0] AXI_08_WSTRB;
+ input AXI_08_WVALID;
+ (* invertible_pin = "IS_AXI_09_ACLK_INVERTED" *)
+ input AXI_09_ACLK;
+ input [36:0] AXI_09_ARADDR;
+ input [1:0] AXI_09_ARBURST;
+ (* invertible_pin = "IS_AXI_09_ARESET_N_INVERTED" *)
+ input AXI_09_ARESET_N;
+ input [5:0] AXI_09_ARID;
+ input [3:0] AXI_09_ARLEN;
+ input [2:0] AXI_09_ARSIZE;
+ input AXI_09_ARVALID;
+ input [36:0] AXI_09_AWADDR;
+ input [1:0] AXI_09_AWBURST;
+ input [5:0] AXI_09_AWID;
+ input [3:0] AXI_09_AWLEN;
+ input [2:0] AXI_09_AWSIZE;
+ input AXI_09_AWVALID;
+ input AXI_09_BREADY;
+ input AXI_09_DFI_LP_PWR_X_REQ;
+ input AXI_09_RREADY;
+ input [255:0] AXI_09_WDATA;
+ input [31:0] AXI_09_WDATA_PARITY;
+ input AXI_09_WLAST;
+ input [31:0] AXI_09_WSTRB;
+ input AXI_09_WVALID;
+ (* invertible_pin = "IS_AXI_10_ACLK_INVERTED" *)
+ input AXI_10_ACLK;
+ input [36:0] AXI_10_ARADDR;
+ input [1:0] AXI_10_ARBURST;
+ (* invertible_pin = "IS_AXI_10_ARESET_N_INVERTED" *)
+ input AXI_10_ARESET_N;
+ input [5:0] AXI_10_ARID;
+ input [3:0] AXI_10_ARLEN;
+ input [2:0] AXI_10_ARSIZE;
+ input AXI_10_ARVALID;
+ input [36:0] AXI_10_AWADDR;
+ input [1:0] AXI_10_AWBURST;
+ input [5:0] AXI_10_AWID;
+ input [3:0] AXI_10_AWLEN;
+ input [2:0] AXI_10_AWSIZE;
+ input AXI_10_AWVALID;
+ input AXI_10_BREADY;
+ input AXI_10_DFI_LP_PWR_X_REQ;
+ input AXI_10_RREADY;
+ input [255:0] AXI_10_WDATA;
+ input [31:0] AXI_10_WDATA_PARITY;
+ input AXI_10_WLAST;
+ input [31:0] AXI_10_WSTRB;
+ input AXI_10_WVALID;
+ (* invertible_pin = "IS_AXI_11_ACLK_INVERTED" *)
+ input AXI_11_ACLK;
+ input [36:0] AXI_11_ARADDR;
+ input [1:0] AXI_11_ARBURST;
+ (* invertible_pin = "IS_AXI_11_ARESET_N_INVERTED" *)
+ input AXI_11_ARESET_N;
+ input [5:0] AXI_11_ARID;
+ input [3:0] AXI_11_ARLEN;
+ input [2:0] AXI_11_ARSIZE;
+ input AXI_11_ARVALID;
+ input [36:0] AXI_11_AWADDR;
+ input [1:0] AXI_11_AWBURST;
+ input [5:0] AXI_11_AWID;
+ input [3:0] AXI_11_AWLEN;
+ input [2:0] AXI_11_AWSIZE;
+ input AXI_11_AWVALID;
+ input AXI_11_BREADY;
+ input AXI_11_DFI_LP_PWR_X_REQ;
+ input AXI_11_RREADY;
+ input [255:0] AXI_11_WDATA;
+ input [31:0] AXI_11_WDATA_PARITY;
+ input AXI_11_WLAST;
+ input [31:0] AXI_11_WSTRB;
+ input AXI_11_WVALID;
+ (* invertible_pin = "IS_AXI_12_ACLK_INVERTED" *)
+ input AXI_12_ACLK;
+ input [36:0] AXI_12_ARADDR;
+ input [1:0] AXI_12_ARBURST;
+ (* invertible_pin = "IS_AXI_12_ARESET_N_INVERTED" *)
+ input AXI_12_ARESET_N;
+ input [5:0] AXI_12_ARID;
+ input [3:0] AXI_12_ARLEN;
+ input [2:0] AXI_12_ARSIZE;
+ input AXI_12_ARVALID;
+ input [36:0] AXI_12_AWADDR;
+ input [1:0] AXI_12_AWBURST;
+ input [5:0] AXI_12_AWID;
+ input [3:0] AXI_12_AWLEN;
+ input [2:0] AXI_12_AWSIZE;
+ input AXI_12_AWVALID;
+ input AXI_12_BREADY;
+ input AXI_12_DFI_LP_PWR_X_REQ;
+ input AXI_12_RREADY;
+ input [255:0] AXI_12_WDATA;
+ input [31:0] AXI_12_WDATA_PARITY;
+ input AXI_12_WLAST;
+ input [31:0] AXI_12_WSTRB;
+ input AXI_12_WVALID;
+ (* invertible_pin = "IS_AXI_13_ACLK_INVERTED" *)
+ input AXI_13_ACLK;
+ input [36:0] AXI_13_ARADDR;
+ input [1:0] AXI_13_ARBURST;
+ (* invertible_pin = "IS_AXI_13_ARESET_N_INVERTED" *)
+ input AXI_13_ARESET_N;
+ input [5:0] AXI_13_ARID;
+ input [3:0] AXI_13_ARLEN;
+ input [2:0] AXI_13_ARSIZE;
+ input AXI_13_ARVALID;
+ input [36:0] AXI_13_AWADDR;
+ input [1:0] AXI_13_AWBURST;
+ input [5:0] AXI_13_AWID;
+ input [3:0] AXI_13_AWLEN;
+ input [2:0] AXI_13_AWSIZE;
+ input AXI_13_AWVALID;
+ input AXI_13_BREADY;
+ input AXI_13_DFI_LP_PWR_X_REQ;
+ input AXI_13_RREADY;
+ input [255:0] AXI_13_WDATA;
+ input [31:0] AXI_13_WDATA_PARITY;
+ input AXI_13_WLAST;
+ input [31:0] AXI_13_WSTRB;
+ input AXI_13_WVALID;
+ (* invertible_pin = "IS_AXI_14_ACLK_INVERTED" *)
+ input AXI_14_ACLK;
+ input [36:0] AXI_14_ARADDR;
+ input [1:0] AXI_14_ARBURST;
+ (* invertible_pin = "IS_AXI_14_ARESET_N_INVERTED" *)
+ input AXI_14_ARESET_N;
+ input [5:0] AXI_14_ARID;
+ input [3:0] AXI_14_ARLEN;
+ input [2:0] AXI_14_ARSIZE;
+ input AXI_14_ARVALID;
+ input [36:0] AXI_14_AWADDR;
+ input [1:0] AXI_14_AWBURST;
+ input [5:0] AXI_14_AWID;
+ input [3:0] AXI_14_AWLEN;
+ input [2:0] AXI_14_AWSIZE;
+ input AXI_14_AWVALID;
+ input AXI_14_BREADY;
+ input AXI_14_DFI_LP_PWR_X_REQ;
+ input AXI_14_RREADY;
+ input [255:0] AXI_14_WDATA;
+ input [31:0] AXI_14_WDATA_PARITY;
+ input AXI_14_WLAST;
+ input [31:0] AXI_14_WSTRB;
+ input AXI_14_WVALID;
+ (* invertible_pin = "IS_AXI_15_ACLK_INVERTED" *)
+ input AXI_15_ACLK;
+ input [36:0] AXI_15_ARADDR;
+ input [1:0] AXI_15_ARBURST;
+ (* invertible_pin = "IS_AXI_15_ARESET_N_INVERTED" *)
+ input AXI_15_ARESET_N;
+ input [5:0] AXI_15_ARID;
+ input [3:0] AXI_15_ARLEN;
+ input [2:0] AXI_15_ARSIZE;
+ input AXI_15_ARVALID;
+ input [36:0] AXI_15_AWADDR;
+ input [1:0] AXI_15_AWBURST;
+ input [5:0] AXI_15_AWID;
+ input [3:0] AXI_15_AWLEN;
+ input [2:0] AXI_15_AWSIZE;
+ input AXI_15_AWVALID;
+ input AXI_15_BREADY;
+ input AXI_15_DFI_LP_PWR_X_REQ;
+ input AXI_15_RREADY;
+ input [255:0] AXI_15_WDATA;
+ input [31:0] AXI_15_WDATA_PARITY;
+ input AXI_15_WLAST;
+ input [31:0] AXI_15_WSTRB;
+ input AXI_15_WVALID;
+ (* invertible_pin = "IS_AXI_16_ACLK_INVERTED" *)
+ input AXI_16_ACLK;
+ input [36:0] AXI_16_ARADDR;
+ input [1:0] AXI_16_ARBURST;
+ (* invertible_pin = "IS_AXI_16_ARESET_N_INVERTED" *)
+ input AXI_16_ARESET_N;
+ input [5:0] AXI_16_ARID;
+ input [3:0] AXI_16_ARLEN;
+ input [2:0] AXI_16_ARSIZE;
+ input AXI_16_ARVALID;
+ input [36:0] AXI_16_AWADDR;
+ input [1:0] AXI_16_AWBURST;
+ input [5:0] AXI_16_AWID;
+ input [3:0] AXI_16_AWLEN;
+ input [2:0] AXI_16_AWSIZE;
+ input AXI_16_AWVALID;
+ input AXI_16_BREADY;
+ input AXI_16_DFI_LP_PWR_X_REQ;
+ input AXI_16_RREADY;
+ input [255:0] AXI_16_WDATA;
+ input [31:0] AXI_16_WDATA_PARITY;
+ input AXI_16_WLAST;
+ input [31:0] AXI_16_WSTRB;
+ input AXI_16_WVALID;
+ (* invertible_pin = "IS_AXI_17_ACLK_INVERTED" *)
+ input AXI_17_ACLK;
+ input [36:0] AXI_17_ARADDR;
+ input [1:0] AXI_17_ARBURST;
+ (* invertible_pin = "IS_AXI_17_ARESET_N_INVERTED" *)
+ input AXI_17_ARESET_N;
+ input [5:0] AXI_17_ARID;
+ input [3:0] AXI_17_ARLEN;
+ input [2:0] AXI_17_ARSIZE;
+ input AXI_17_ARVALID;
+ input [36:0] AXI_17_AWADDR;
+ input [1:0] AXI_17_AWBURST;
+ input [5:0] AXI_17_AWID;
+ input [3:0] AXI_17_AWLEN;
+ input [2:0] AXI_17_AWSIZE;
+ input AXI_17_AWVALID;
+ input AXI_17_BREADY;
+ input AXI_17_DFI_LP_PWR_X_REQ;
+ input AXI_17_RREADY;
+ input [255:0] AXI_17_WDATA;
+ input [31:0] AXI_17_WDATA_PARITY;
+ input AXI_17_WLAST;
+ input [31:0] AXI_17_WSTRB;
+ input AXI_17_WVALID;
+ (* invertible_pin = "IS_AXI_18_ACLK_INVERTED" *)
+ input AXI_18_ACLK;
+ input [36:0] AXI_18_ARADDR;
+ input [1:0] AXI_18_ARBURST;
+ (* invertible_pin = "IS_AXI_18_ARESET_N_INVERTED" *)
+ input AXI_18_ARESET_N;
+ input [5:0] AXI_18_ARID;
+ input [3:0] AXI_18_ARLEN;
+ input [2:0] AXI_18_ARSIZE;
+ input AXI_18_ARVALID;
+ input [36:0] AXI_18_AWADDR;
+ input [1:0] AXI_18_AWBURST;
+ input [5:0] AXI_18_AWID;
+ input [3:0] AXI_18_AWLEN;
+ input [2:0] AXI_18_AWSIZE;
+ input AXI_18_AWVALID;
+ input AXI_18_BREADY;
+ input AXI_18_DFI_LP_PWR_X_REQ;
+ input AXI_18_RREADY;
+ input [255:0] AXI_18_WDATA;
+ input [31:0] AXI_18_WDATA_PARITY;
+ input AXI_18_WLAST;
+ input [31:0] AXI_18_WSTRB;
+ input AXI_18_WVALID;
+ (* invertible_pin = "IS_AXI_19_ACLK_INVERTED" *)
+ input AXI_19_ACLK;
+ input [36:0] AXI_19_ARADDR;
+ input [1:0] AXI_19_ARBURST;
+ (* invertible_pin = "IS_AXI_19_ARESET_N_INVERTED" *)
+ input AXI_19_ARESET_N;
+ input [5:0] AXI_19_ARID;
+ input [3:0] AXI_19_ARLEN;
+ input [2:0] AXI_19_ARSIZE;
+ input AXI_19_ARVALID;
+ input [36:0] AXI_19_AWADDR;
+ input [1:0] AXI_19_AWBURST;
+ input [5:0] AXI_19_AWID;
+ input [3:0] AXI_19_AWLEN;
+ input [2:0] AXI_19_AWSIZE;
+ input AXI_19_AWVALID;
+ input AXI_19_BREADY;
+ input AXI_19_DFI_LP_PWR_X_REQ;
+ input AXI_19_RREADY;
+ input [255:0] AXI_19_WDATA;
+ input [31:0] AXI_19_WDATA_PARITY;
+ input AXI_19_WLAST;
+ input [31:0] AXI_19_WSTRB;
+ input AXI_19_WVALID;
+ (* invertible_pin = "IS_AXI_20_ACLK_INVERTED" *)
+ input AXI_20_ACLK;
+ input [36:0] AXI_20_ARADDR;
+ input [1:0] AXI_20_ARBURST;
+ (* invertible_pin = "IS_AXI_20_ARESET_N_INVERTED" *)
+ input AXI_20_ARESET_N;
+ input [5:0] AXI_20_ARID;
+ input [3:0] AXI_20_ARLEN;
+ input [2:0] AXI_20_ARSIZE;
+ input AXI_20_ARVALID;
+ input [36:0] AXI_20_AWADDR;
+ input [1:0] AXI_20_AWBURST;
+ input [5:0] AXI_20_AWID;
+ input [3:0] AXI_20_AWLEN;
+ input [2:0] AXI_20_AWSIZE;
+ input AXI_20_AWVALID;
+ input AXI_20_BREADY;
+ input AXI_20_DFI_LP_PWR_X_REQ;
+ input AXI_20_RREADY;
+ input [255:0] AXI_20_WDATA;
+ input [31:0] AXI_20_WDATA_PARITY;
+ input AXI_20_WLAST;
+ input [31:0] AXI_20_WSTRB;
+ input AXI_20_WVALID;
+ (* invertible_pin = "IS_AXI_21_ACLK_INVERTED" *)
+ input AXI_21_ACLK;
+ input [36:0] AXI_21_ARADDR;
+ input [1:0] AXI_21_ARBURST;
+ (* invertible_pin = "IS_AXI_21_ARESET_N_INVERTED" *)
+ input AXI_21_ARESET_N;
+ input [5:0] AXI_21_ARID;
+ input [3:0] AXI_21_ARLEN;
+ input [2:0] AXI_21_ARSIZE;
+ input AXI_21_ARVALID;
+ input [36:0] AXI_21_AWADDR;
+ input [1:0] AXI_21_AWBURST;
+ input [5:0] AXI_21_AWID;
+ input [3:0] AXI_21_AWLEN;
+ input [2:0] AXI_21_AWSIZE;
+ input AXI_21_AWVALID;
+ input AXI_21_BREADY;
+ input AXI_21_DFI_LP_PWR_X_REQ;
+ input AXI_21_RREADY;
+ input [255:0] AXI_21_WDATA;
+ input [31:0] AXI_21_WDATA_PARITY;
+ input AXI_21_WLAST;
+ input [31:0] AXI_21_WSTRB;
+ input AXI_21_WVALID;
+ (* invertible_pin = "IS_AXI_22_ACLK_INVERTED" *)
+ input AXI_22_ACLK;
+ input [36:0] AXI_22_ARADDR;
+ input [1:0] AXI_22_ARBURST;
+ (* invertible_pin = "IS_AXI_22_ARESET_N_INVERTED" *)
+ input AXI_22_ARESET_N;
+ input [5:0] AXI_22_ARID;
+ input [3:0] AXI_22_ARLEN;
+ input [2:0] AXI_22_ARSIZE;
+ input AXI_22_ARVALID;
+ input [36:0] AXI_22_AWADDR;
+ input [1:0] AXI_22_AWBURST;
+ input [5:0] AXI_22_AWID;
+ input [3:0] AXI_22_AWLEN;
+ input [2:0] AXI_22_AWSIZE;
+ input AXI_22_AWVALID;
+ input AXI_22_BREADY;
+ input AXI_22_DFI_LP_PWR_X_REQ;
+ input AXI_22_RREADY;
+ input [255:0] AXI_22_WDATA;
+ input [31:0] AXI_22_WDATA_PARITY;
+ input AXI_22_WLAST;
+ input [31:0] AXI_22_WSTRB;
+ input AXI_22_WVALID;
+ (* invertible_pin = "IS_AXI_23_ACLK_INVERTED" *)
+ input AXI_23_ACLK;
+ input [36:0] AXI_23_ARADDR;
+ input [1:0] AXI_23_ARBURST;
+ (* invertible_pin = "IS_AXI_23_ARESET_N_INVERTED" *)
+ input AXI_23_ARESET_N;
+ input [5:0] AXI_23_ARID;
+ input [3:0] AXI_23_ARLEN;
+ input [2:0] AXI_23_ARSIZE;
+ input AXI_23_ARVALID;
+ input [36:0] AXI_23_AWADDR;
+ input [1:0] AXI_23_AWBURST;
+ input [5:0] AXI_23_AWID;
+ input [3:0] AXI_23_AWLEN;
+ input [2:0] AXI_23_AWSIZE;
+ input AXI_23_AWVALID;
+ input AXI_23_BREADY;
+ input AXI_23_DFI_LP_PWR_X_REQ;
+ input AXI_23_RREADY;
+ input [255:0] AXI_23_WDATA;
+ input [31:0] AXI_23_WDATA_PARITY;
+ input AXI_23_WLAST;
+ input [31:0] AXI_23_WSTRB;
+ input AXI_23_WVALID;
+ (* invertible_pin = "IS_AXI_24_ACLK_INVERTED" *)
+ input AXI_24_ACLK;
+ input [36:0] AXI_24_ARADDR;
+ input [1:0] AXI_24_ARBURST;
+ (* invertible_pin = "IS_AXI_24_ARESET_N_INVERTED" *)
+ input AXI_24_ARESET_N;
+ input [5:0] AXI_24_ARID;
+ input [3:0] AXI_24_ARLEN;
+ input [2:0] AXI_24_ARSIZE;
+ input AXI_24_ARVALID;
+ input [36:0] AXI_24_AWADDR;
+ input [1:0] AXI_24_AWBURST;
+ input [5:0] AXI_24_AWID;
+ input [3:0] AXI_24_AWLEN;
+ input [2:0] AXI_24_AWSIZE;
+ input AXI_24_AWVALID;
+ input AXI_24_BREADY;
+ input AXI_24_DFI_LP_PWR_X_REQ;
+ input AXI_24_RREADY;
+ input [255:0] AXI_24_WDATA;
+ input [31:0] AXI_24_WDATA_PARITY;
+ input AXI_24_WLAST;
+ input [31:0] AXI_24_WSTRB;
+ input AXI_24_WVALID;
+ (* invertible_pin = "IS_AXI_25_ACLK_INVERTED" *)
+ input AXI_25_ACLK;
+ input [36:0] AXI_25_ARADDR;
+ input [1:0] AXI_25_ARBURST;
+ (* invertible_pin = "IS_AXI_25_ARESET_N_INVERTED" *)
+ input AXI_25_ARESET_N;
+ input [5:0] AXI_25_ARID;
+ input [3:0] AXI_25_ARLEN;
+ input [2:0] AXI_25_ARSIZE;
+ input AXI_25_ARVALID;
+ input [36:0] AXI_25_AWADDR;
+ input [1:0] AXI_25_AWBURST;
+ input [5:0] AXI_25_AWID;
+ input [3:0] AXI_25_AWLEN;
+ input [2:0] AXI_25_AWSIZE;
+ input AXI_25_AWVALID;
+ input AXI_25_BREADY;
+ input AXI_25_DFI_LP_PWR_X_REQ;
+ input AXI_25_RREADY;
+ input [255:0] AXI_25_WDATA;
+ input [31:0] AXI_25_WDATA_PARITY;
+ input AXI_25_WLAST;
+ input [31:0] AXI_25_WSTRB;
+ input AXI_25_WVALID;
+ (* invertible_pin = "IS_AXI_26_ACLK_INVERTED" *)
+ input AXI_26_ACLK;
+ input [36:0] AXI_26_ARADDR;
+ input [1:0] AXI_26_ARBURST;
+ (* invertible_pin = "IS_AXI_26_ARESET_N_INVERTED" *)
+ input AXI_26_ARESET_N;
+ input [5:0] AXI_26_ARID;
+ input [3:0] AXI_26_ARLEN;
+ input [2:0] AXI_26_ARSIZE;
+ input AXI_26_ARVALID;
+ input [36:0] AXI_26_AWADDR;
+ input [1:0] AXI_26_AWBURST;
+ input [5:0] AXI_26_AWID;
+ input [3:0] AXI_26_AWLEN;
+ input [2:0] AXI_26_AWSIZE;
+ input AXI_26_AWVALID;
+ input AXI_26_BREADY;
+ input AXI_26_DFI_LP_PWR_X_REQ;
+ input AXI_26_RREADY;
+ input [255:0] AXI_26_WDATA;
+ input [31:0] AXI_26_WDATA_PARITY;
+ input AXI_26_WLAST;
+ input [31:0] AXI_26_WSTRB;
+ input AXI_26_WVALID;
+ (* invertible_pin = "IS_AXI_27_ACLK_INVERTED" *)
+ input AXI_27_ACLK;
+ input [36:0] AXI_27_ARADDR;
+ input [1:0] AXI_27_ARBURST;
+ (* invertible_pin = "IS_AXI_27_ARESET_N_INVERTED" *)
+ input AXI_27_ARESET_N;
+ input [5:0] AXI_27_ARID;
+ input [3:0] AXI_27_ARLEN;
+ input [2:0] AXI_27_ARSIZE;
+ input AXI_27_ARVALID;
+ input [36:0] AXI_27_AWADDR;
+ input [1:0] AXI_27_AWBURST;
+ input [5:0] AXI_27_AWID;
+ input [3:0] AXI_27_AWLEN;
+ input [2:0] AXI_27_AWSIZE;
+ input AXI_27_AWVALID;
+ input AXI_27_BREADY;
+ input AXI_27_DFI_LP_PWR_X_REQ;
+ input AXI_27_RREADY;
+ input [255:0] AXI_27_WDATA;
+ input [31:0] AXI_27_WDATA_PARITY;
+ input AXI_27_WLAST;
+ input [31:0] AXI_27_WSTRB;
+ input AXI_27_WVALID;
+ (* invertible_pin = "IS_AXI_28_ACLK_INVERTED" *)
+ input AXI_28_ACLK;
+ input [36:0] AXI_28_ARADDR;
+ input [1:0] AXI_28_ARBURST;
+ (* invertible_pin = "IS_AXI_28_ARESET_N_INVERTED" *)
+ input AXI_28_ARESET_N;
+ input [5:0] AXI_28_ARID;
+ input [3:0] AXI_28_ARLEN;
+ input [2:0] AXI_28_ARSIZE;
+ input AXI_28_ARVALID;
+ input [36:0] AXI_28_AWADDR;
+ input [1:0] AXI_28_AWBURST;
+ input [5:0] AXI_28_AWID;
+ input [3:0] AXI_28_AWLEN;
+ input [2:0] AXI_28_AWSIZE;
+ input AXI_28_AWVALID;
+ input AXI_28_BREADY;
+ input AXI_28_DFI_LP_PWR_X_REQ;
+ input AXI_28_RREADY;
+ input [255:0] AXI_28_WDATA;
+ input [31:0] AXI_28_WDATA_PARITY;
+ input AXI_28_WLAST;
+ input [31:0] AXI_28_WSTRB;
+ input AXI_28_WVALID;
+ (* invertible_pin = "IS_AXI_29_ACLK_INVERTED" *)
+ input AXI_29_ACLK;
+ input [36:0] AXI_29_ARADDR;
+ input [1:0] AXI_29_ARBURST;
+ (* invertible_pin = "IS_AXI_29_ARESET_N_INVERTED" *)
+ input AXI_29_ARESET_N;
+ input [5:0] AXI_29_ARID;
+ input [3:0] AXI_29_ARLEN;
+ input [2:0] AXI_29_ARSIZE;
+ input AXI_29_ARVALID;
+ input [36:0] AXI_29_AWADDR;
+ input [1:0] AXI_29_AWBURST;
+ input [5:0] AXI_29_AWID;
+ input [3:0] AXI_29_AWLEN;
+ input [2:0] AXI_29_AWSIZE;
+ input AXI_29_AWVALID;
+ input AXI_29_BREADY;
+ input AXI_29_DFI_LP_PWR_X_REQ;
+ input AXI_29_RREADY;
+ input [255:0] AXI_29_WDATA;
+ input [31:0] AXI_29_WDATA_PARITY;
+ input AXI_29_WLAST;
+ input [31:0] AXI_29_WSTRB;
+ input AXI_29_WVALID;
+ (* invertible_pin = "IS_AXI_30_ACLK_INVERTED" *)
+ input AXI_30_ACLK;
+ input [36:0] AXI_30_ARADDR;
+ input [1:0] AXI_30_ARBURST;
+ (* invertible_pin = "IS_AXI_30_ARESET_N_INVERTED" *)
+ input AXI_30_ARESET_N;
+ input [5:0] AXI_30_ARID;
+ input [3:0] AXI_30_ARLEN;
+ input [2:0] AXI_30_ARSIZE;
+ input AXI_30_ARVALID;
+ input [36:0] AXI_30_AWADDR;
+ input [1:0] AXI_30_AWBURST;
+ input [5:0] AXI_30_AWID;
+ input [3:0] AXI_30_AWLEN;
+ input [2:0] AXI_30_AWSIZE;
+ input AXI_30_AWVALID;
+ input AXI_30_BREADY;
+ input AXI_30_DFI_LP_PWR_X_REQ;
+ input AXI_30_RREADY;
+ input [255:0] AXI_30_WDATA;
+ input [31:0] AXI_30_WDATA_PARITY;
+ input AXI_30_WLAST;
+ input [31:0] AXI_30_WSTRB;
+ input AXI_30_WVALID;
+ (* invertible_pin = "IS_AXI_31_ACLK_INVERTED" *)
+ input AXI_31_ACLK;
+ input [36:0] AXI_31_ARADDR;
+ input [1:0] AXI_31_ARBURST;
+ (* invertible_pin = "IS_AXI_31_ARESET_N_INVERTED" *)
+ input AXI_31_ARESET_N;
+ input [5:0] AXI_31_ARID;
+ input [3:0] AXI_31_ARLEN;
+ input [2:0] AXI_31_ARSIZE;
+ input AXI_31_ARVALID;
+ input [36:0] AXI_31_AWADDR;
+ input [1:0] AXI_31_AWBURST;
+ input [5:0] AXI_31_AWID;
+ input [3:0] AXI_31_AWLEN;
+ input [2:0] AXI_31_AWSIZE;
+ input AXI_31_AWVALID;
+ input AXI_31_BREADY;
+ input AXI_31_DFI_LP_PWR_X_REQ;
+ input AXI_31_RREADY;
+ input [255:0] AXI_31_WDATA;
+ input [31:0] AXI_31_WDATA_PARITY;
+ input AXI_31_WLAST;
+ input [31:0] AXI_31_WSTRB;
+ input AXI_31_WVALID;
+ input BSCAN_DRCK_0;
+ input BSCAN_DRCK_1;
+ input BSCAN_TCK_0;
+ input BSCAN_TCK_1;
+ input HBM_REF_CLK_0;
+ input HBM_REF_CLK_1;
+ input MBIST_EN_00;
+ input MBIST_EN_01;
+ input MBIST_EN_02;
+ input MBIST_EN_03;
+ input MBIST_EN_04;
+ input MBIST_EN_05;
+ input MBIST_EN_06;
+ input MBIST_EN_07;
+ input MBIST_EN_08;
+ input MBIST_EN_09;
+ input MBIST_EN_10;
+ input MBIST_EN_11;
+ input MBIST_EN_12;
+ input MBIST_EN_13;
+ input MBIST_EN_14;
+ input MBIST_EN_15;
+endmodule
+
module PPC405_ADV (...);
parameter in_delay=100;
parameter out_delay=100;
@@ -25658,269 +31011,6 @@ module PPC440 (...);
input [28:31] TIEC440PVR;
endmodule
-module MCB (...);
- parameter integer ARB_NUM_TIME_SLOTS = 12;
- parameter [17:0] ARB_TIME_SLOT_0 = 18'b111111111111111111;
- parameter [17:0] ARB_TIME_SLOT_1 = 18'b111111111111111111;
- parameter [17:0] ARB_TIME_SLOT_10 = 18'b111111111111111111;
- parameter [17:0] ARB_TIME_SLOT_11 = 18'b111111111111111111;
- parameter [17:0] ARB_TIME_SLOT_2 = 18'b111111111111111111;
- parameter [17:0] ARB_TIME_SLOT_3 = 18'b111111111111111111;
- parameter [17:0] ARB_TIME_SLOT_4 = 18'b111111111111111111;
- parameter [17:0] ARB_TIME_SLOT_5 = 18'b111111111111111111;
- parameter [17:0] ARB_TIME_SLOT_6 = 18'b111111111111111111;
- parameter [17:0] ARB_TIME_SLOT_7 = 18'b111111111111111111;
- parameter [17:0] ARB_TIME_SLOT_8 = 18'b111111111111111111;
- parameter [17:0] ARB_TIME_SLOT_9 = 18'b111111111111111111;
- parameter [2:0] CAL_BA = 3'h0;
- parameter CAL_BYPASS = "YES";
- parameter [11:0] CAL_CA = 12'h000;
- parameter CAL_CALIBRATION_MODE = "NOCALIBRATION";
- parameter integer CAL_CLK_DIV = 1;
- parameter CAL_DELAY = "QUARTER";
- parameter [14:0] CAL_RA = 15'h0000;
- parameter MEM_ADDR_ORDER = "BANK_ROW_COLUMN";
- parameter integer MEM_BA_SIZE = 3;
- parameter integer MEM_BURST_LEN = 8;
- parameter integer MEM_CAS_LATENCY = 4;
- parameter integer MEM_CA_SIZE = 11;
- parameter MEM_DDR1_2_ODS = "FULL";
- parameter MEM_DDR2_3_HIGH_TEMP_SR = "NORMAL";
- parameter MEM_DDR2_3_PA_SR = "FULL";
- parameter integer MEM_DDR2_ADD_LATENCY = 0;
- parameter MEM_DDR2_DIFF_DQS_EN = "YES";
- parameter MEM_DDR2_RTT = "50OHMS";
- parameter integer MEM_DDR2_WRT_RECOVERY = 4;
- parameter MEM_DDR3_ADD_LATENCY = "OFF";
- parameter MEM_DDR3_AUTO_SR = "ENABLED";
- parameter integer MEM_DDR3_CAS_LATENCY = 7;
- parameter integer MEM_DDR3_CAS_WR_LATENCY = 5;
- parameter MEM_DDR3_DYN_WRT_ODT = "OFF";
- parameter MEM_DDR3_ODS = "DIV7";
- parameter MEM_DDR3_RTT = "DIV2";
- parameter integer MEM_DDR3_WRT_RECOVERY = 7;
- parameter MEM_MDDR_ODS = "FULL";
- parameter MEM_MOBILE_PA_SR = "FULL";
- parameter integer MEM_MOBILE_TC_SR = 0;
- parameter integer MEM_RAS_VAL = 0;
- parameter integer MEM_RA_SIZE = 13;
- parameter integer MEM_RCD_VAL = 1;
- parameter integer MEM_REFI_VAL = 0;
- parameter integer MEM_RFC_VAL = 0;
- parameter integer MEM_RP_VAL = 0;
- parameter integer MEM_RTP_VAL = 0;
- parameter MEM_TYPE = "DDR3";
- parameter integer MEM_WIDTH = 4;
- parameter integer MEM_WR_VAL = 0;
- parameter integer MEM_WTR_VAL = 3;
- parameter PORT_CONFIG = "B32_B32_B32_B32";
- output CAS;
- output CKE;
- output DQIOWEN0;
- output DQSIOWEN90N;
- output DQSIOWEN90P;
- output IOIDRPADD;
- output IOIDRPBROADCAST;
- output IOIDRPCLK;
- output IOIDRPCS;
- output IOIDRPSDO;
- output IOIDRPTRAIN;
- output IOIDRPUPDATE;
- output LDMN;
- output LDMP;
- output ODT;
- output P0CMDEMPTY;
- output P0CMDFULL;
- output P0RDEMPTY;
- output P0RDERROR;
- output P0RDFULL;
- output P0RDOVERFLOW;
- output P0WREMPTY;
- output P0WRERROR;
- output P0WRFULL;
- output P0WRUNDERRUN;
- output P1CMDEMPTY;
- output P1CMDFULL;
- output P1RDEMPTY;
- output P1RDERROR;
- output P1RDFULL;
- output P1RDOVERFLOW;
- output P1WREMPTY;
- output P1WRERROR;
- output P1WRFULL;
- output P1WRUNDERRUN;
- output P2CMDEMPTY;
- output P2CMDFULL;
- output P2EMPTY;
- output P2ERROR;
- output P2FULL;
- output P2RDOVERFLOW;
- output P2WRUNDERRUN;
- output P3CMDEMPTY;
- output P3CMDFULL;
- output P3EMPTY;
- output P3ERROR;
- output P3FULL;
- output P3RDOVERFLOW;
- output P3WRUNDERRUN;
- output P4CMDEMPTY;
- output P4CMDFULL;
- output P4EMPTY;
- output P4ERROR;
- output P4FULL;
- output P4RDOVERFLOW;
- output P4WRUNDERRUN;
- output P5CMDEMPTY;
- output P5CMDFULL;
- output P5EMPTY;
- output P5ERROR;
- output P5FULL;
- output P5RDOVERFLOW;
- output P5WRUNDERRUN;
- output RAS;
- output RST;
- output SELFREFRESHMODE;
- output UDMN;
- output UDMP;
- output UOCALSTART;
- output UOCMDREADYIN;
- output UODATAVALID;
- output UODONECAL;
- output UOREFRSHFLAG;
- output UOSDO;
- output WE;
- output [14:0] ADDR;
- output [15:0] DQON;
- output [15:0] DQOP;
- output [2:0] BA;
- output [31:0] P0RDDATA;
- output [31:0] P1RDDATA;
- output [31:0] P2RDDATA;
- output [31:0] P3RDDATA;
- output [31:0] P4RDDATA;
- output [31:0] P5RDDATA;
- output [31:0] STATUS;
- output [4:0] IOIDRPADDR;
- output [6:0] P0RDCOUNT;
- output [6:0] P0WRCOUNT;
- output [6:0] P1RDCOUNT;
- output [6:0] P1WRCOUNT;
- output [6:0] P2COUNT;
- output [6:0] P3COUNT;
- output [6:0] P4COUNT;
- output [6:0] P5COUNT;
- output [7:0] UODATA;
- input DQSIOIN;
- input DQSIOIP;
- input IOIDRPSDI;
- input P0ARBEN;
- input P0CMDCLK;
- input P0CMDEN;
- input P0RDCLK;
- input P0RDEN;
- input P0WRCLK;
- input P0WREN;
- input P1ARBEN;
- input P1CMDCLK;
- input P1CMDEN;
- input P1RDCLK;
- input P1RDEN;
- input P1WRCLK;
- input P1WREN;
- input P2ARBEN;
- input P2CLK;
- input P2CMDCLK;
- input P2CMDEN;
- input P2EN;
- input P3ARBEN;
- input P3CLK;
- input P3CMDCLK;
- input P3CMDEN;
- input P3EN;
- input P4ARBEN;
- input P4CLK;
- input P4CMDCLK;
- input P4CMDEN;
- input P4EN;
- input P5ARBEN;
- input P5CLK;
- input P5CMDCLK;
- input P5CMDEN;
- input P5EN;
- input PLLLOCK;
- input RECAL;
- input SELFREFRESHENTER;
- input SYSRST;
- input UDQSIOIN;
- input UDQSIOIP;
- input UIADD;
- input UIBROADCAST;
- input UICLK;
- input UICMD;
- input UICMDEN;
- input UICMDIN;
- input UICS;
- input UIDONECAL;
- input UIDQLOWERDEC;
- input UIDQLOWERINC;
- input UIDQUPPERDEC;
- input UIDQUPPERINC;
- input UIDRPUPDATE;
- input UILDQSDEC;
- input UILDQSINC;
- input UIREAD;
- input UISDI;
- input UIUDQSDEC;
- input UIUDQSINC;
- input [11:0] P0CMDCA;
- input [11:0] P1CMDCA;
- input [11:0] P2CMDCA;
- input [11:0] P3CMDCA;
- input [11:0] P4CMDCA;
- input [11:0] P5CMDCA;
- input [14:0] P0CMDRA;
- input [14:0] P1CMDRA;
- input [14:0] P2CMDRA;
- input [14:0] P3CMDRA;
- input [14:0] P4CMDRA;
- input [14:0] P5CMDRA;
- input [15:0] DQI;
- input [1:0] PLLCE;
- input [1:0] PLLCLK;
- input [2:0] P0CMDBA;
- input [2:0] P0CMDINSTR;
- input [2:0] P1CMDBA;
- input [2:0] P1CMDINSTR;
- input [2:0] P2CMDBA;
- input [2:0] P2CMDINSTR;
- input [2:0] P3CMDBA;
- input [2:0] P3CMDINSTR;
- input [2:0] P4CMDBA;
- input [2:0] P4CMDINSTR;
- input [2:0] P5CMDBA;
- input [2:0] P5CMDINSTR;
- input [31:0] P0WRDATA;
- input [31:0] P1WRDATA;
- input [31:0] P2WRDATA;
- input [31:0] P3WRDATA;
- input [31:0] P4WRDATA;
- input [31:0] P5WRDATA;
- input [3:0] P0RWRMASK;
- input [3:0] P1RWRMASK;
- input [3:0] P2WRMASK;
- input [3:0] P3WRMASK;
- input [3:0] P4WRMASK;
- input [3:0] P5WRMASK;
- input [3:0] UIDQCOUNT;
- input [4:0] UIADDR;
- input [5:0] P0CMDBL;
- input [5:0] P1CMDBL;
- input [5:0] P2CMDBL;
- input [5:0] P3CMDBL;
- input [5:0] P4CMDBL;
- input [5:0] P5CMDBL;
-endmodule
-
(* keep *)
module PS7 (...);
output DMA0DAVALID;
@@ -28054,3 +33144,297 @@ module ILKNE4 (...);
input TX_SOPIN3;
endmodule
+(* keep *)
+module VCU (...);
+ parameter integer CORECLKREQ = 667;
+ parameter integer DECHORRESOLUTION = 3840;
+ parameter DECODERCHROMAFORMAT = "4_2_2";
+ parameter DECODERCODING = "H.265";
+ parameter integer DECODERCOLORDEPTH = 10;
+ parameter integer DECODERNUMCORES = 2;
+ parameter integer DECVERTRESOLUTION = 2160;
+ parameter ENABLEDECODER = "TRUE";
+ parameter ENABLEENCODER = "TRUE";
+ parameter integer ENCHORRESOLUTION = 3840;
+ parameter ENCODERCHROMAFORMAT = "4_2_2";
+ parameter ENCODERCODING = "H.265";
+ parameter integer ENCODERCOLORDEPTH = 10;
+ parameter integer ENCODERNUMCORES = 4;
+ parameter integer ENCVERTRESOLUTION = 2160;
+ output VCUPLARREADYAXILITEAPB;
+ output VCUPLAWREADYAXILITEAPB;
+ output [1:0] VCUPLBRESPAXILITEAPB;
+ output VCUPLBVALIDAXILITEAPB;
+ output VCUPLCORESTATUSCLKPLL;
+ output [43:0] VCUPLDECARADDR0;
+ output [43:0] VCUPLDECARADDR1;
+ output [1:0] VCUPLDECARBURST0;
+ output [1:0] VCUPLDECARBURST1;
+ output [3:0] VCUPLDECARCACHE0;
+ output [3:0] VCUPLDECARCACHE1;
+ output [3:0] VCUPLDECARID0;
+ output [3:0] VCUPLDECARID1;
+ output [7:0] VCUPLDECARLEN0;
+ output [7:0] VCUPLDECARLEN1;
+ output VCUPLDECARPROT0;
+ output VCUPLDECARPROT1;
+ output [3:0] VCUPLDECARQOS0;
+ output [3:0] VCUPLDECARQOS1;
+ output [2:0] VCUPLDECARSIZE0;
+ output [2:0] VCUPLDECARSIZE1;
+ output VCUPLDECARVALID0;
+ output VCUPLDECARVALID1;
+ output [43:0] VCUPLDECAWADDR0;
+ output [43:0] VCUPLDECAWADDR1;
+ output [1:0] VCUPLDECAWBURST0;
+ output [1:0] VCUPLDECAWBURST1;
+ output [3:0] VCUPLDECAWCACHE0;
+ output [3:0] VCUPLDECAWCACHE1;
+ output [3:0] VCUPLDECAWID0;
+ output [3:0] VCUPLDECAWID1;
+ output [7:0] VCUPLDECAWLEN0;
+ output [7:0] VCUPLDECAWLEN1;
+ output VCUPLDECAWPROT0;
+ output VCUPLDECAWPROT1;
+ output [3:0] VCUPLDECAWQOS0;
+ output [3:0] VCUPLDECAWQOS1;
+ output [2:0] VCUPLDECAWSIZE0;
+ output [2:0] VCUPLDECAWSIZE1;
+ output VCUPLDECAWVALID0;
+ output VCUPLDECAWVALID1;
+ output VCUPLDECBREADY0;
+ output VCUPLDECBREADY1;
+ output VCUPLDECRREADY0;
+ output VCUPLDECRREADY1;
+ output [127:0] VCUPLDECWDATA0;
+ output [127:0] VCUPLDECWDATA1;
+ output VCUPLDECWLAST0;
+ output VCUPLDECWLAST1;
+ output VCUPLDECWVALID0;
+ output VCUPLDECWVALID1;
+ output [16:0] VCUPLENCALL2CADDR;
+ output VCUPLENCALL2CRVALID;
+ output [319:0] VCUPLENCALL2CWDATA;
+ output VCUPLENCALL2CWVALID;
+ output [43:0] VCUPLENCARADDR0;
+ output [43:0] VCUPLENCARADDR1;
+ output [1:0] VCUPLENCARBURST0;
+ output [1:0] VCUPLENCARBURST1;
+ output [3:0] VCUPLENCARCACHE0;
+ output [3:0] VCUPLENCARCACHE1;
+ output [3:0] VCUPLENCARID0;
+ output [3:0] VCUPLENCARID1;
+ output [7:0] VCUPLENCARLEN0;
+ output [7:0] VCUPLENCARLEN1;
+ output VCUPLENCARPROT0;
+ output VCUPLENCARPROT1;
+ output [3:0] VCUPLENCARQOS0;
+ output [3:0] VCUPLENCARQOS1;
+ output [2:0] VCUPLENCARSIZE0;
+ output [2:0] VCUPLENCARSIZE1;
+ output VCUPLENCARVALID0;
+ output VCUPLENCARVALID1;
+ output [43:0] VCUPLENCAWADDR0;
+ output [43:0] VCUPLENCAWADDR1;
+ output [1:0] VCUPLENCAWBURST0;
+ output [1:0] VCUPLENCAWBURST1;
+ output [3:0] VCUPLENCAWCACHE0;
+ output [3:0] VCUPLENCAWCACHE1;
+ output [3:0] VCUPLENCAWID0;
+ output [3:0] VCUPLENCAWID1;
+ output [7:0] VCUPLENCAWLEN0;
+ output [7:0] VCUPLENCAWLEN1;
+ output VCUPLENCAWPROT0;
+ output VCUPLENCAWPROT1;
+ output [3:0] VCUPLENCAWQOS0;
+ output [3:0] VCUPLENCAWQOS1;
+ output [2:0] VCUPLENCAWSIZE0;
+ output [2:0] VCUPLENCAWSIZE1;
+ output VCUPLENCAWVALID0;
+ output VCUPLENCAWVALID1;
+ output VCUPLENCBREADY0;
+ output VCUPLENCBREADY1;
+ output VCUPLENCRREADY0;
+ output VCUPLENCRREADY1;
+ output [127:0] VCUPLENCWDATA0;
+ output [127:0] VCUPLENCWDATA1;
+ output VCUPLENCWLAST0;
+ output VCUPLENCWLAST1;
+ output VCUPLENCWVALID0;
+ output VCUPLENCWVALID1;
+ output [43:0] VCUPLMCUMAXIICDCARADDR;
+ output [1:0] VCUPLMCUMAXIICDCARBURST;
+ output [3:0] VCUPLMCUMAXIICDCARCACHE;
+ output [2:0] VCUPLMCUMAXIICDCARID;
+ output [7:0] VCUPLMCUMAXIICDCARLEN;
+ output VCUPLMCUMAXIICDCARLOCK;
+ output [2:0] VCUPLMCUMAXIICDCARPROT;
+ output [3:0] VCUPLMCUMAXIICDCARQOS;
+ output [2:0] VCUPLMCUMAXIICDCARSIZE;
+ output VCUPLMCUMAXIICDCARVALID;
+ output [43:0] VCUPLMCUMAXIICDCAWADDR;
+ output [1:0] VCUPLMCUMAXIICDCAWBURST;
+ output [3:0] VCUPLMCUMAXIICDCAWCACHE;
+ output [2:0] VCUPLMCUMAXIICDCAWID;
+ output [7:0] VCUPLMCUMAXIICDCAWLEN;
+ output VCUPLMCUMAXIICDCAWLOCK;
+ output [2:0] VCUPLMCUMAXIICDCAWPROT;
+ output [3:0] VCUPLMCUMAXIICDCAWQOS;
+ output [2:0] VCUPLMCUMAXIICDCAWSIZE;
+ output VCUPLMCUMAXIICDCAWVALID;
+ output VCUPLMCUMAXIICDCBREADY;
+ output VCUPLMCUMAXIICDCRREADY;
+ output [31:0] VCUPLMCUMAXIICDCWDATA;
+ output VCUPLMCUMAXIICDCWLAST;
+ output [3:0] VCUPLMCUMAXIICDCWSTRB;
+ output VCUPLMCUMAXIICDCWVALID;
+ output VCUPLMCUSTATUSCLKPLL;
+ output VCUPLPINTREQ;
+ output VCUPLPLLSTATUSPLLLOCK;
+ output VCUPLPWRSUPPLYSTATUSVCCAUX;
+ output VCUPLPWRSUPPLYSTATUSVCUINT;
+ output [31:0] VCUPLRDATAAXILITEAPB;
+ output [1:0] VCUPLRRESPAXILITEAPB;
+ output VCUPLRVALIDAXILITEAPB;
+ output VCUPLWREADYAXILITEAPB;
+ input INITPLVCUGASKETCLAMPCONTROLLVLSHVCCINTD;
+ input [19:0] PLVCUARADDRAXILITEAPB;
+ input [2:0] PLVCUARPROTAXILITEAPB;
+ input PLVCUARVALIDAXILITEAPB;
+ input [19:0] PLVCUAWADDRAXILITEAPB;
+ input [2:0] PLVCUAWPROTAXILITEAPB;
+ input PLVCUAWVALIDAXILITEAPB;
+ input PLVCUAXIDECCLK;
+ input PLVCUAXIENCCLK;
+ input PLVCUAXILITECLK;
+ input PLVCUAXIMCUCLK;
+ input PLVCUBREADYAXILITEAPB;
+ input PLVCUCORECLK;
+ input PLVCUDECARREADY0;
+ input PLVCUDECARREADY1;
+ input PLVCUDECAWREADY0;
+ input PLVCUDECAWREADY1;
+ input [3:0] PLVCUDECBID0;
+ input [3:0] PLVCUDECBID1;
+ input [1:0] PLVCUDECBRESP0;
+ input [1:0] PLVCUDECBRESP1;
+ input PLVCUDECBVALID0;
+ input PLVCUDECBVALID1;
+ input [127:0] PLVCUDECRDATA0;
+ input [127:0] PLVCUDECRDATA1;
+ input [3:0] PLVCUDECRID0;
+ input [3:0] PLVCUDECRID1;
+ input PLVCUDECRLAST0;
+ input PLVCUDECRLAST1;
+ input [1:0] PLVCUDECRRESP0;
+ input [1:0] PLVCUDECRRESP1;
+ input PLVCUDECRVALID0;
+ input PLVCUDECRVALID1;
+ input PLVCUDECWREADY0;
+ input PLVCUDECWREADY1;
+ input [319:0] PLVCUENCALL2CRDATA;
+ input PLVCUENCALL2CRREADY;
+ input PLVCUENCARREADY0;
+ input PLVCUENCARREADY1;
+ input PLVCUENCAWREADY0;
+ input PLVCUENCAWREADY1;
+ input [3:0] PLVCUENCBID0;
+ input [3:0] PLVCUENCBID1;
+ input [1:0] PLVCUENCBRESP0;
+ input [1:0] PLVCUENCBRESP1;
+ input PLVCUENCBVALID0;
+ input PLVCUENCBVALID1;
+ input PLVCUENCL2CCLK;
+ input [127:0] PLVCUENCRDATA0;
+ input [127:0] PLVCUENCRDATA1;
+ input [3:0] PLVCUENCRID0;
+ input [3:0] PLVCUENCRID1;
+ input PLVCUENCRLAST0;
+ input PLVCUENCRLAST1;
+ input [1:0] PLVCUENCRRESP0;
+ input [1:0] PLVCUENCRRESP1;
+ input PLVCUENCRVALID0;
+ input PLVCUENCRVALID1;
+ input PLVCUENCWREADY0;
+ input PLVCUENCWREADY1;
+ input PLVCUMCUCLK;
+ input PLVCUMCUMAXIICDCARREADY;
+ input PLVCUMCUMAXIICDCAWREADY;
+ input [2:0] PLVCUMCUMAXIICDCBID;
+ input [1:0] PLVCUMCUMAXIICDCBRESP;
+ input PLVCUMCUMAXIICDCBVALID;
+ input [31:0] PLVCUMCUMAXIICDCRDATA;
+ input [2:0] PLVCUMCUMAXIICDCRID;
+ input PLVCUMCUMAXIICDCRLAST;
+ input [1:0] PLVCUMCUMAXIICDCRRESP;
+ input PLVCUMCUMAXIICDCRVALID;
+ input PLVCUMCUMAXIICDCWREADY;
+ input PLVCUPLLREFCLKPL;
+ input PLVCURAWRSTN;
+ input PLVCURREADYAXILITEAPB;
+ input [31:0] PLVCUWDATAAXILITEAPB;
+ input [3:0] PLVCUWSTRBAXILITEAPB;
+ input PLVCUWVALIDAXILITEAPB;
+endmodule
+
+module FE (...);
+ parameter MODE = "TURBO_DECODE";
+ parameter real PHYSICAL_UTILIZATION = 100.00;
+ parameter SIM_DEVICE = "ULTRASCALE_PLUS";
+ parameter STANDARD = "LTE";
+ parameter real THROUGHPUT_UTILIZATION = 100.00;
+ output [399:0] DEBUG_DOUT;
+ output DEBUG_PHASE;
+ output INTERRUPT;
+ output [511:0] M_AXIS_DOUT_TDATA;
+ output M_AXIS_DOUT_TLAST;
+ output M_AXIS_DOUT_TVALID;
+ output [31:0] M_AXIS_STATUS_TDATA;
+ output M_AXIS_STATUS_TVALID;
+ output [15:0] SPARE_OUT;
+ output S_AXIS_CTRL_TREADY;
+ output S_AXIS_DIN_TREADY;
+ output S_AXIS_DIN_WORDS_TREADY;
+ output S_AXIS_DOUT_WORDS_TREADY;
+ output S_AXI_ARREADY;
+ output S_AXI_AWREADY;
+ output S_AXI_BVALID;
+ output [31:0] S_AXI_RDATA;
+ output S_AXI_RVALID;
+ output S_AXI_WREADY;
+ input CORE_CLK;
+ input DEBUG_CLK_EN;
+ input DEBUG_EN;
+ input [3:0] DEBUG_SEL_IN;
+ input M_AXIS_DOUT_ACLK;
+ input M_AXIS_DOUT_TREADY;
+ input M_AXIS_STATUS_ACLK;
+ input M_AXIS_STATUS_TREADY;
+ input RESET_N;
+ input [15:0] SPARE_IN;
+ input S_AXIS_CTRL_ACLK;
+ input [31:0] S_AXIS_CTRL_TDATA;
+ input S_AXIS_CTRL_TVALID;
+ input S_AXIS_DIN_ACLK;
+ input [511:0] S_AXIS_DIN_TDATA;
+ input S_AXIS_DIN_TLAST;
+ input S_AXIS_DIN_TVALID;
+ input S_AXIS_DIN_WORDS_ACLK;
+ input [31:0] S_AXIS_DIN_WORDS_TDATA;
+ input S_AXIS_DIN_WORDS_TLAST;
+ input S_AXIS_DIN_WORDS_TVALID;
+ input S_AXIS_DOUT_WORDS_ACLK;
+ input [31:0] S_AXIS_DOUT_WORDS_TDATA;
+ input S_AXIS_DOUT_WORDS_TLAST;
+ input S_AXIS_DOUT_WORDS_TVALID;
+ input S_AXI_ACLK;
+ input [17:0] S_AXI_ARADDR;
+ input S_AXI_ARVALID;
+ input [17:0] S_AXI_AWADDR;
+ input S_AXI_AWVALID;
+ input S_AXI_BREADY;
+ input S_AXI_RREADY;
+ input [31:0] S_AXI_WDATA;
+ input S_AXI_WVALID;
+endmodule
+
diff --git a/techlibs/xilinx/ff_map.v b/techlibs/xilinx/ff_map.v
new file mode 100644
index 000000000..2079fd99a
--- /dev/null
+++ b/techlibs/xilinx/ff_map.v
@@ -0,0 +1,120 @@
+/*
+ * 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 _NO_FFS
+
+// Async reset, enable.
+
+module \$_DFFE_NP0P_ (input D, C, E, R, output Q);
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ FDCE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .CLR(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+module \$_DFFE_PP0P_ (input D, C, E, R, output Q);
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ FDCE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .CLR(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+
+module \$_DFFE_NP1P_ (input D, C, E, R, output Q);
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ FDPE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .PRE(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+module \$_DFFE_PP1P_ (input D, C, E, R, output Q);
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ FDPE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .PRE(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+
+// Async set and reset, enable.
+
+module \$_DFFSRE_NPPP_ (input D, C, E, S, R, output Q);
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ FDCPE #(.INIT(_TECHMAP_WIREINIT_Q_), .IS_C_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .CLR(R), .PRE(S));
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+module \$_DFFSRE_PPPP_ (input D, C, E, S, R, output Q);
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ FDCPE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .CLR(R), .PRE(S));
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+
+// Sync reset, enable.
+
+module \$_SDFFE_NP0P_ (input D, C, E, R, output Q);
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+module \$_SDFFE_PP0P_ (input D, C, E, R, output Q);
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ FDRE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+
+module \$_SDFFE_NP1P_ (input D, C, E, R, output Q);
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ FDSE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .S(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+module \$_SDFFE_PP1P_ (input D, C, E, R, output Q);
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ FDSE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .S(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+
+// Latches with reset.
+
+module \$_DLATCH_NP0_ (input E, R, D, output Q);
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ LDCE #(.INIT(_TECHMAP_WIREINIT_Q_), .IS_G_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .G(E), .GE(1'b1), .CLR(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+module \$_DLATCH_PP0_ (input E, R, D, output Q);
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ LDCE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .G(E), .GE(1'b1), .CLR(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+module \$_DLATCH_NP1_ (input E, R, D, output Q);
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ LDPE #(.INIT(_TECHMAP_WIREINIT_Q_), .IS_G_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .G(E), .GE(1'b1), .PRE(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+module \$_DLATCH_PP1_ (input E, R, D, output Q);
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ LDPE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .G(E), .GE(1'b1), .PRE(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+
+// Latches with set and reset.
+
+module \$_DLATCH_NPP_ (input E, S, R, D, output Q);
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ LDCPE #(.INIT(_TECHMAP_WIREINIT_Q_), .IS_G_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .G(E), .GE(1'b1), .CLR(R), .PRE(S));
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+module \$_DLATCH_PPP_ (input E, S, R, D, output Q);
+ parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
+ LDCPE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .G(E), .GE(1'b1), .CLR(R), .PRE(S));
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+
+`endif
+
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 b66dc850d..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
@@ -77,10 +77,6 @@ struct SynthXilinxPass : public ScriptPass
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(" -vpr\n");
- log(" generate an output netlist (and BLIF file) suitable for VPR\n");
- log(" (this feature is experimental and incomplete)\n");
- log("\n");
log(" -ise\n");
log(" generate an output netlist suitable for ISE\n");
log("\n");
@@ -142,7 +138,7 @@ struct SynthXilinxPass : public ScriptPass
}
std::string top_opt, edif_file, blif_file, family;
- bool flatten, retime, vpr, ise, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, uram;
+ bool flatten, retime, ise, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, uram;
bool abc9, dff;
bool flatten_before_abc;
int widemux;
@@ -157,7 +153,6 @@ struct SynthXilinxPass : public ScriptPass
family = "xc7";
flatten = false;
retime = false;
- vpr = false;
ise = false;
noiopad = false;
noclkbuf = false;
@@ -229,10 +224,6 @@ struct SynthXilinxPass : public ScriptPass
nowidelut = true;
continue;
}
- if (args[argidx] == "-vpr") {
- vpr = true;
- continue;
- }
if (args[argidx] == "-ise") {
ise = true;
continue;
@@ -342,18 +333,9 @@ struct SynthXilinxPass : public ScriptPass
std::string lut_size_s = std::to_string(lut_size);
if (help_mode)
lut_size_s = "[46]";
- std::string ff_map_file;
- if (help_mode)
- ff_map_file = "+/xilinx/{family}_ff_map.v";
- else if (family == "xc6s")
- ff_map_file = "+/xilinx/xc6s_ff_map.v";
- else
- ff_map_file = "+/xilinx/xc7_ff_map.v";
if (check_label("begin")) {
std::string read_args;
- if (vpr)
- read_args += " -D_EXPLICIT_CARRY";
read_args += " -lib -specify +/xilinx/cells_sim.v";
run("read_verilog" + read_args);
@@ -375,6 +357,8 @@ struct SynthXilinxPass : public ScriptPass
run("opt_expr");
run("opt_clean");
run("check");
+ run("opt -nodffe -nosdff");
+ run("fsm");
run("opt");
if (help_mode)
run("wreduce [-keepdc]", "(option for '-widemux')");
@@ -462,8 +446,6 @@ struct SynthXilinxPass : public ScriptPass
run("alumacc");
run("share");
run("opt");
- run("fsm");
- run("opt -fast");
run("memory -nomap");
run("opt_clean");
}
@@ -522,28 +504,21 @@ struct SynthXilinxPass : public ScriptPass
}
if (check_label("map_ffram")) {
- // Required for dff2dffs to work.
- run("simplemap t:$dff t:$adff t:$mux");
- // Needs to be done before opt -mux_bool happens.
- if (help_mode)
- run("dff2dffs [-match-init]", "(-match-init for xc6s only)");
- else if (family == "xc6s")
- run("dff2dffs -match-init");
- else
- run("dff2dffs");
- if (widemux > 0)
+ if (widemux > 0) {
run("opt -fast -mux_bool -undriven -fine"); // Necessary to omit -mux_undef otherwise muxcover
// performs less efficiently
- else
+ } else {
run("opt -fast -full");
+ }
run("memory_map");
}
if (check_label("fine")) {
- run("dff2dffe -direct-match $_DFF_* -direct-match $_SDFF_*");
- if (help_mode)
- run("muxcover <internal options> ('-widemux' only)");
- else if (widemux > 0) {
+ if (help_mode) {
+ run("simplemap t:$mux", "('-widemux' only)");
+ run("muxcover <internal options>", "('-widemux' only)");
+ } else if (widemux > 0) {
+ run("simplemap t:$mux");
constexpr int cost_mux2 = 100;
std::string muxcover_args = stringf(" -nodecode -mux2=%d", cost_mux2);
switch (widemux) {
@@ -577,17 +552,16 @@ struct SynthXilinxPass : public ScriptPass
techmap_args += stringf(" -D MIN_MUX_INPUTS=%d -map +/xilinx/mux_map.v", widemux);
if (!nocarry) {
techmap_args += " -map +/xilinx/arith_map.v";
- if (vpr)
- techmap_args += " -D _EXPLICIT_CARRY";
}
run("techmap " + techmap_args);
run("opt -fast");
}
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);
@@ -595,16 +569,22 @@ struct SynthXilinxPass : public ScriptPass
run("clean");
}
- if (check_label("map_ffs", "('-abc9' only)")) {
+ if (check_label("map_ffs")) {
+ if (family == "xc6s")
+ run("dfflegalize -cell $_DFFE_?P?P_ r -cell $_SDFFE_?P?P_ r -cell $_DLATCH_?P?_ r", "(for xc6s)");
+ else if (family == "xc6v" || family == "xc7" || family == "xcu" || family == "xcup")
+ run("dfflegalize -cell $_DFFE_?P?P_ 01 -cell $_SDFFE_?P?P_ 01 -cell $_DLATCH_?P?_ 01", "(for xc6v, xc7, xcu, xcup)");
+ else
+ run("dfflegalize -cell $_DFFE_?P?P_ 01 -cell $_DFFSRE_?PPP_ 01 -cell $_SDFFE_?P?P_ 01 -cell $_DLATCH_?P?_ 01 -cell $_DLATCHSR_?PP_ 01", "(for xc5v and older)");
if (abc9 || help_mode) {
if (dff || help_mode)
- run("zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$_SDFF*", "('-dff' only)");
- run("techmap -map " + ff_map_file);
+ run("zinit -all w:* t:$_SDFFE_*", "('-dff' only)");
+ run("techmap -map +/xilinx/ff_map.v", "('-abc9' only)");
}
}
if (check_label("map_luts")) {
- run("opt_expr -mux_undef");
+ run("opt_expr -mux_undef -noclkinv");
if (flatten_before_abc)
run("flatten");
if (help_mode)
@@ -653,13 +633,13 @@ struct SynthXilinxPass : public ScriptPass
}
run("clean");
+ if (help_mode || !abc9)
+ run("techmap -map +/xilinx/ff_map.v", "(only if not '-abc9')");
// This shregmap call infers fixed length shift registers after abc
// has performed any necessary retiming
if (!nosrl || help_mode)
run("xilinx_srl -fixed -minlen 3", "(skip if '-nosrl')");
std::string techmap_args = "-map +/xilinx/lut_map.v -map +/xilinx/cells_map.v";
- if (help_mode || !abc9)
- techmap_args += stringf(" -map %s", ff_map_file.c_str());
techmap_args += " -D LUT_WIDTH=" + lut_size_s;
run("techmap " + techmap_args);
if (help_mode)
@@ -683,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")) {
@@ -692,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/xc6s_ff_map.v b/techlibs/xilinx/xc6s_ff_map.v
deleted file mode 100644
index a1e4218b9..000000000
--- a/techlibs/xilinx/xc6s_ff_map.v
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * yosys -- Yosys Open SYnthesis Suite
- *
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-// ============================================================================
-// FF mapping for Spartan 6. The primitives used are the same as Series 7,
-// but with one major difference: the initial value is implied by the
-// primitive type used (FFs with reset pin must have INIT set to 0 or x, FFs
-// with set pin must have INIT set to 1 or x). For Yosys primitives without
-// set/reset, this means we have to pick the primitive type based on the INIT
-// value.
-
-`ifndef _NO_FFS
-
-// No reset.
-
-module \$_DFF_N_ (input D, C, output Q);
- parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
- generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
- FDSE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .S(1'b0));
- else
- FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0));
- endgenerate
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-module \$_DFF_P_ (input D, C, output Q);
- parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
- generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
- FDSE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .S(1'b0));
- else
- FDRE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0));
- endgenerate
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-
-// No reset, enable.
-
-module \$_DFFE_NP_ (input D, C, E, output Q);
- parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
- generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
- FDSE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .S(1'b0));
- else
- FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0));
- endgenerate
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-module \$_DFFE_PP_ (input D, C, E, output Q);
- parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
- generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
- FDSE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .S(1'b0));
- else
- FDRE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0));
- endgenerate
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-
-// Async reset.
-
-module \$_DFF_NP0_ (input D, C, R, output Q);
- parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
- generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
- $error("Spartan 6 doesn't support FFs with asynchronous reset initialized to 1");
- else
- FDCE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R));
- endgenerate
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-module \$_DFF_PP0_ (input D, C, R, output Q);
- parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
- generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
- $error("Spartan 6 doesn't support FFs with asynchronous reset initialized to 1");
- else
- FDCE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R));
- endgenerate
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-
-module \$_DFF_NP1_ (input D, C, R, output Q);
- parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
- generate if (_TECHMAP_WIREINIT_Q_ === 1'b0)
- $error("Spartan 6 doesn't support FFs with asynchronous set initialized to 0");
- else
- FDPE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R));
- endgenerate
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-module \$_DFF_PP1_ (input D, C, R, output Q);
- parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
- generate if (_TECHMAP_WIREINIT_Q_ === 1'b0)
- $error("Spartan 6 doesn't support FFs with asynchronous set initialized to 0");
- else
- FDPE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R));
- endgenerate
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-
-// Async reset, enable.
-
-module \$_DFFE_NP0P_ (input D, C, E, R, output Q);
- parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
- generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
- $error("Spartan 6 doesn't support FFs with asynchronous reset initialized to 1");
- else
- FDCE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .CLR( R));
- endgenerate
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-module \$_DFFE_PP0P_ (input D, C, E, R, output Q);
- parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
- generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
- $error("Spartan 6 doesn't support FFs with asynchronous reset initialized to 1");
- else
- FDCE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .CLR( R));
- endgenerate
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-
-module \$_DFFE_NP1P_ (input D, C, E, R, output Q);
- parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
- generate if (_TECHMAP_WIREINIT_Q_ === 1'b0)
- $error("Spartan 6 doesn't support FFs with asynchronous set initialized to 0");
- else
- FDPE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .PRE( R));
- endgenerate
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-module \$_DFFE_PP1P_ (input D, C, E, R, output Q);
- parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
- generate if (_TECHMAP_WIREINIT_Q_ === 1'b0)
- $error("Spartan 6 doesn't support FFs with asynchronous set initialized to 0");
- else
- FDPE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .PRE( R));
- endgenerate
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-
-// Sync reset.
-
-module \$_SDFF_NP0_ (input D, C, R, output Q);
- parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
- generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
- $error("Spartan 6 doesn't support FFs with reset initialized to 1");
- else
- FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R( R));
- endgenerate
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-module \$_SDFF_PP0_ (input D, C, R, output Q);
- parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
- generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
- $error("Spartan 6 doesn't support FFs with reset initialized to 1");
- else
- FDRE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R( R));
- endgenerate
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-
-module \$_SDFF_NP1_ (input D, C, R, output Q);
- parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
- generate if (_TECHMAP_WIREINIT_Q_ === 1'b0)
- $error("Spartan 6 doesn't support FFs with set initialized to 0");
- else
- FDSE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .S( R));
- endgenerate
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-module \$_SDFF_PP1_ (input D, C, R, output Q);
- parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
- generate if (_TECHMAP_WIREINIT_Q_ === 1'b0)
- $error("Spartan 6 doesn't support FFs with set initialized to 0");
- else
- FDSE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .S( R));
- endgenerate
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-
-// Sync reset, enable.
-
-module \$_SDFFE_NP0P_ (input D, C, E, R, output Q);
- parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
- generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
- $error("Spartan 6 doesn't support FFs with reset initialized to 1");
- else
- FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R( R));
- endgenerate
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-module \$_SDFFE_PP0P_ (input D, C, E, R, output Q);
- parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
- generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
- $error("Spartan 6 doesn't support FFs with reset initialized to 1");
- else
- FDRE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R( R));
- endgenerate
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-
-module \$_SDFFE_NP1P_ (input D, C, E, R, output Q);
- parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
- generate if (_TECHMAP_WIREINIT_Q_ === 1'b0)
- $error("Spartan 6 doesn't support FFs with set initialized to 0");
- else
- FDSE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .S( R));
- endgenerate
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-module \$_SDFFE_PP1P_ (input D, C, E, R, output Q);
- parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
- generate if (_TECHMAP_WIREINIT_Q_ === 1'b0)
- $error("Spartan 6 doesn't support FFs with set initialized to 0");
- else
- FDSE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .S( R));
- endgenerate
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-
-// Latches (no reset).
-
-module \$_DLATCH_N_ (input E, D, output Q);
- parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
- generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
- LDPE #(.INIT(_TECHMAP_WIREINIT_Q_), .IS_G_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .G(E), .GE(1'b1), .PRE(1'b0));
- else
- LDCE #(.INIT(_TECHMAP_WIREINIT_Q_), .IS_G_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .G(E), .GE(1'b1), .CLR(1'b0));
- endgenerate
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-module \$_DLATCH_P_ (input E, D, output Q);
- parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
- generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
- LDPE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .G(E), .GE(1'b1), .PRE(1'b0));
- else
- LDCE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .G(E), .GE(1'b1), .CLR(1'b0));
- endgenerate
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-
-// Latches with reset (TODO).
-
-`endif
-
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/xc7_dsp_map.v b/techlibs/xilinx/xc7_dsp_map.v
index a4256eb92..58df977ec 100644
--- a/techlibs/xilinx/xc7_dsp_map.v
+++ b/techlibs/xilinx/xc7_dsp_map.v
@@ -33,6 +33,7 @@ module \$__MUL25X18 (input [24:0] A, input [17:0] B, output [42:0] Y);
.B(B),
.C(48'b0),
.D(25'b0),
+ .CARRYIN(1'b0),
.P(P_48),
.INMODE(5'b00000),
diff --git a/techlibs/xilinx/xc7_ff_map.v b/techlibs/xilinx/xc7_ff_map.v
deleted file mode 100644
index 750e8f8eb..000000000
--- a/techlibs/xilinx/xc7_ff_map.v
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * yosys -- Yosys Open SYnthesis Suite
- *
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-// ============================================================================
-// FF mapping for Virtex 6, Series 7 and Ultrascale. These families support
-// the following features:
-//
-// - a CLB flip-flop can be used as a latch or as a flip-flop
-// - a CLB flip-flop has the following pins:
-//
-// - data input
-// - clock (or gate for latches) (with optional inversion)
-// - clock enable (or gate enable, which is just ANDed with gate — unused by
-// synthesis)
-// - either a set or a reset input, which (for FFs) can be either
-// synchronous or asynchronous (with optional inversion)
-// - data output
-//
-// - a flip-flop also has an initial value, which is set at device
-// initialization (or whenever GSR is asserted)
-
-`ifndef _NO_FFS
-
-// No reset.
-
-module \$_DFF_N_ (input D, C, output Q);
- parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
- FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0));
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-module \$_DFF_P_ (input D, C, output Q);
- parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
- FDRE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0));
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-
-// No reset, enable.
-
-module \$_DFFE_NP_ (input D, C, E, output Q);
- parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
- FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0));
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-module \$_DFFE_PP_ (input D, C, E, output Q);
- parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
- FDRE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0));
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-
-// Async reset.
-
-module \$_DFF_NP0_ (input D, C, R, output Q);
- parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
- FDCE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R));
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-module \$_DFF_PP0_ (input D, C, R, output Q);
- parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
- FDCE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R));
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-
-module \$_DFF_NP1_ (input D, C, R, output Q);
- parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
- FDPE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R));
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-module \$_DFF_PP1_ (input D, C, R, output Q);
- parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
- FDPE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R));
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-
-// Async reset, enable.
-
-module \$_DFFE_NP0P_ (input D, C, E, R, output Q);
- parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
- FDCE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .CLR( R));
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-module \$_DFFE_PP0P_ (input D, C, E, R, output Q);
- parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
- FDCE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .CLR( R));
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-
-module \$_DFFE_NP1P_ (input D, C, E, R, output Q);
- parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
- FDPE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .PRE( R));
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-module \$_DFFE_PP1P_ (input D, C, E, R, output Q);
- parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
- FDPE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .PRE( R));
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-
-// Sync reset.
-
-module \$_SDFF_NP0_ (input D, C, R, output Q);
- parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
- FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R( R));
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-module \$_SDFF_PP0_ (input D, C, R, output Q);
- parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
- FDRE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R( R));
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-
-module \$_SDFF_NP1_ (input D, C, R, output Q);
- parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
- FDSE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .S( R));
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-module \$_SDFF_PP1_ (input D, C, R, output Q);
- parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
- FDSE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .S( R));
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-
-// Sync reset, enable.
-
-module \$_SDFFE_NP0P_ (input D, C, E, R, output Q);
- parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
- FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R( R));
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-module \$_SDFFE_PP0P_ (input D, C, E, R, output Q);
- parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
- FDRE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R( R));
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-
-module \$_SDFFE_NP1P_ (input D, C, E, R, output Q);
- parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
- FDSE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .S( R));
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-module \$_SDFFE_PP1P_ (input D, C, E, R, output Q);
- parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
- FDSE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .S( R));
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-
-// Latches (no reset).
-
-module \$_DLATCH_N_ (input E, D, output Q);
- parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
- LDCE #(.INIT(_TECHMAP_WIREINIT_Q_), .IS_G_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .G(E), .GE(1'b1), .CLR(1'b0));
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-module \$_DLATCH_P_ (input E, D, output Q);
- parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
- LDCE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .G(E), .GE(1'b1), .CLR(1'b0));
- wire _TECHMAP_REMOVEINIT_Q_ = 1;
-endmodule
-
-// Latches with reset (TODO).
-
-`endif
-
diff --git a/techlibs/xilinx/xilinx_dffopt.cc b/techlibs/xilinx/xilinx_dffopt.cc
index 365f505fb..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
@@ -209,7 +209,7 @@ lut_sigin_done:
continue;
LutData lut_d = it_D->second.first;
Cell *cell_d = it_D->second.second;
- if (cell->getParam(ID(IS_D_INVERTED)).as_bool()) {
+ if (cell->hasParam(ID(IS_D_INVERTED)) && cell->getParam(ID(IS_D_INVERTED)).as_bool()) {
// Flip all bits in the LUT.
for (int i = 0; i < GetSize(lut_d.first); i++)
lut_d.first.bits[i] = (lut_d.first.bits[i] == State::S1) ? State::S0 : State::S1;
@@ -249,7 +249,7 @@ lut_sigin_done:
if (has_s) {
SigBit sig_S = sigmap(cell->getPort(ID::S));
LutData lut_s = LutData(Const(2, 2), {sig_S});
- bool inv_s = cell->getParam(ID(IS_S_INVERTED)).as_bool();
+ bool inv_s = cell->hasParam(ID(IS_S_INVERTED)) && cell->getParam(ID(IS_S_INVERTED)).as_bool();
auto it_S = bit_to_lut.find(sig_S);
if (it_S != bit_to_lut.end())
lut_s = it_S->second.first;
@@ -271,7 +271,7 @@ lut_sigin_done:
if (has_r) {
SigBit sig_R = sigmap(cell->getPort(ID::R));
LutData lut_r = LutData(Const(2, 2), {sig_R});
- bool inv_r = cell->getParam(ID(IS_R_INVERTED)).as_bool();
+ bool inv_r = cell->hasParam(ID(IS_R_INVERTED)) && cell->getParam(ID(IS_R_INVERTED)).as_bool();
auto it_R = bit_to_lut.find(sig_R);
if (it_R != bit_to_lut.end())
lut_r = it_R->second.first;
diff --git a/tests/aiger/.gitignore b/tests/aiger/.gitignore
index b76bdb653..54b4a279b 100644
--- a/tests/aiger/.gitignore
+++ b/tests/aiger/.gitignore
@@ -1,3 +1,3 @@
/*_ref.v
-/*.aag.log
-/*.aig.log
+/*.log
+/neg.out/
diff --git a/tests/aiger/run-test.sh b/tests/aiger/run-test.sh
index de7bc68cf..bcf2b964a 100755
--- a/tests/aiger/run-test.sh
+++ b/tests/aiger/run-test.sh
@@ -55,5 +55,5 @@ done
for y in *.ys; do
echo "Running $y."
- ../../yosys $y -ql ${y%.*}.log
+ ../../yosys -ql ${y%.*}.log $y
done
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/dffs.ys b/tests/arch/anlogic/dffs.ys
index d3281ab89..deb90e051 100644
--- a/tests/arch/anlogic/dffs.ys
+++ b/tests/arch/anlogic/dffs.ys
@@ -15,6 +15,5 @@ proc
equiv_opt -assert -map +/anlogic/cells_sim.v synth_anlogic # 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:AL_MAP_LUT3
select -assert-count 1 t:AL_MAP_SEQ
-select -assert-none t:AL_MAP_LUT3 t:AL_MAP_SEQ %% t:* %D
+select -assert-none t:AL_MAP_SEQ %% t:* %D
diff --git a/tests/arch/anlogic/latches.ys b/tests/arch/anlogic/latches.ys
index 8d66f77b3..34a3b14d0 100644
--- a/tests/arch/anlogic/latches.ys
+++ b/tests/arch/anlogic/latches.ys
@@ -3,31 +3,33 @@ design -save read
hierarchy -top latchp
proc
-# Can't run any sort of equivalence check because latches are blown to LUTs
-synth_anlogic
+equiv_opt -assert -multiclock -map +/anlogic/cells_sim.v synth_anlogic
+design -load postopt
cd latchp # Constrain all select calls below inside the top module
-select -assert-count 1 t:AL_MAP_LUT3
-select -assert-none t:AL_MAP_LUT3 %% t:* %D
+select -assert-count 1 t:AL_MAP_SEQ
+select -assert-count 1 t:AL_MAP_LUT1
+select -assert-none t:AL_MAP_SEQ t:AL_MAP_LUT1 %% t:* %D
design -load read
hierarchy -top latchn
proc
-# Can't run any sort of equivalence check because latches are blown to LUTs
-synth_anlogic
+equiv_opt -assert -multiclock -map +/anlogic/cells_sim.v synth_anlogic
+design -load postopt
cd latchn # Constrain all select calls below inside the top module
-select -assert-count 1 t:AL_MAP_LUT3
-select -assert-none t:AL_MAP_LUT3 %% t:* %D
+select -assert-count 1 t:AL_MAP_SEQ
+select -assert-none t:AL_MAP_SEQ %% t:* %D
design -load read
hierarchy -top latchsr
proc
-# Can't run any sort of equivalence check because latches are blown to LUTs
-synth_anlogic
+equiv_opt -assert -multiclock -map +/anlogic/cells_sim.v synth_anlogic
+design -load postopt
cd latchsr # Constrain all select calls below inside the top module
-select -assert-count 1 t:AL_MAP_LUT5
-select -assert-none t:AL_MAP_LUT5 %% t:* %D
+select -assert-count 1 t:AL_MAP_SEQ
+select -assert-count 2 t:AL_MAP_LUT3
+select -assert-none t:AL_MAP_SEQ t:AL_MAP_LUT3 %% 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/anlogic/run-test.sh b/tests/arch/anlogic/run-test.sh
index bf19b887d..4be4b70ae 100755
--- a/tests/arch/anlogic/run-test.sh
+++ b/tests/arch/anlogic/run-test.sh
@@ -1,20 +1,4 @@
#!/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 -w 'Yosys has only limited support for tri-state logic at the moment.' $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
+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/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/mul.v b/tests/arch/common/mul.v
index 437a91cfc..baed64fcd 100644
--- a/tests/arch/common/mul.v
+++ b/tests/arch/common/mul.v
@@ -1,9 +1,10 @@
module top
+#(parameter X_WIDTH=6, Y_WIDTH=6, A_WIDTH=12)
(
- input [5:0] x,
- input [5:0] y,
+ input [X_WIDTH-1:0] x,
+ input [Y_WIDTH-1:0] y,
- output [11:0] A,
+ output [A_WIDTH-1:0] A,
);
assign A = x * y;
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/bug2409.ys b/tests/arch/ecp5/bug2409.ys
new file mode 100644
index 000000000..5ba9cec17
--- /dev/null
+++ b/tests/arch/ecp5/bug2409.ys
@@ -0,0 +1,24 @@
+read_verilog <<EOT
+module t (...);
+
+input CLK;
+input [10:0] A;
+input WE;
+input C;
+input [7:0] DI;
+output reg [7:0] DO;
+
+reg [7:0] mem[2047:0];
+
+always @(posedge CLK) begin
+ if (C)
+ if (WE)
+ mem[A] <= DI;
+ DO <= mem[A];
+end
+
+endmodule
+EOT
+
+synth_ecp5
+select -assert-count 1 t:DP16KD
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/fsm.ys b/tests/arch/ecp5/fsm.ys
index ba91e5fc0..a77986bbc 100644
--- a/tests/arch/ecp5/fsm.ys
+++ b/tests/arch/ecp5/fsm.ys
@@ -10,8 +10,8 @@ sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip
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:L6MUX21
-select -assert-count 15 t:LUT4
-select -assert-count 6 t:PFUMX
+select -assert-max 1 t:L6MUX21
+select -assert-max 16 t:LUT4
+select -assert-max 7 t:PFUMX
select -assert-count 6 t:TRELLIS_FF
select -assert-none t:L6MUX21 t:LUT4 t:PFUMX t:TRELLIS_FF %% t:* %D
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/ecp5/run-test.sh b/tests/arch/ecp5/run-test.sh
index bf19b887d..4be4b70ae 100755
--- a/tests/arch/ecp5/run-test.sh
+++ b/tests/arch/ecp5/run-test.sh
@@ -1,20 +1,4 @@
#!/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 -w 'Yosys has only limited support for tri-state logic at the moment.' $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
+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/efinix/adffs.ys b/tests/arch/efinix/adffs.ys
index 49dc7f256..86d446439 100644
--- a/tests/arch/efinix/adffs.ys
+++ b/tests/arch/efinix/adffs.ys
@@ -32,9 +32,8 @@ design -load postopt # load the post-opt design (otherwise equiv_opt loads the p
cd dffs # Constrain all select calls below inside the top module
select -assert-count 1 t:EFX_FF
select -assert-count 1 t:EFX_GBUFCE
-select -assert-count 1 t:EFX_LUT4
-select -assert-none t:EFX_FF t:EFX_GBUFCE t:EFX_LUT4 %% t:* %D
+select -assert-none t:EFX_FF t:EFX_GBUFCE %% t:* %D
design -load read
@@ -45,6 +44,5 @@ design -load postopt # load the post-opt design (otherwise equiv_opt loads the p
cd ndffnr # Constrain all select calls below inside the top module
select -assert-count 1 t:EFX_FF
select -assert-count 1 t:EFX_GBUFCE
-select -assert-count 1 t:EFX_LUT4
-select -assert-none t:EFX_FF t:EFX_GBUFCE t:EFX_LUT4 %% t:* %D
+select -assert-none t:EFX_FF t:EFX_GBUFCE %% t:* %D
diff --git a/tests/arch/efinix/dffs.ys b/tests/arch/efinix/dffs.ys
index af787ab67..f9111873c 100644
--- a/tests/arch/efinix/dffs.ys
+++ b/tests/arch/efinix/dffs.ys
@@ -19,6 +19,5 @@ design -load postopt # load the post-opt design (otherwise equiv_opt loads the p
cd dffe # Constrain all select calls below inside the top module
select -assert-count 1 t:EFX_FF
select -assert-count 1 t:EFX_GBUFCE
-select -assert-count 1 t:EFX_LUT4
-select -assert-none t:EFX_FF t:EFX_GBUFCE t:EFX_LUT4 %% t:* %D
+select -assert-none t:EFX_FF t:EFX_GBUFCE %% t:* %D
diff --git a/tests/arch/efinix/run-test.sh b/tests/arch/efinix/run-test.sh
index bf19b887d..4be4b70ae 100755
--- a/tests/arch/efinix/run-test.sh
+++ b/tests/arch/efinix/run-test.sh
@@ -1,20 +1,4 @@
#!/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 -w 'Yosys has only limited support for tri-state logic at the moment.' $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
+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/.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/init-error.ys b/tests/arch/gowin/init-error.ys
new file mode 100644
index 000000000..de3813d6f
--- /dev/null
+++ b/tests/arch/gowin/init-error.ys
@@ -0,0 +1,5 @@
+read_verilog init.v
+chparam -set INIT 0 myDFF*P*
+hierarchy -top myDFFP
+logger -expect error "unsupported initial value and async reset value combination" 1
+synth_gowin
diff --git a/tests/arch/gowin/init.ys b/tests/arch/gowin/init.ys
index ddc0e4757..fba7c2fa5 100644
--- a/tests/arch/gowin/init.ys
+++ b/tests/arch/gowin/init.ys
@@ -30,45 +30,40 @@ select -assert-count 1 t:DFFRE
select -assert-count 1 t:DFFS
select -assert-count 1 t:DFFSE
-delete
design -load read
# these should synth to a flop with reset
chparam -set INIT 1 myDFF myDFFN myDFFE myDFFNE
-# async should give a warning
+# async would give an error
# sync should synth to a mux
-chparam -set INIT 0 myDFF*S* myDFF*P*
-chparam -set INIT 1 myDFF*R* myDFF*C*
+chparam -set INIT 0 myDFF*S*
+chparam -set INIT 1 myDFF*R*
proc
flatten
synth_gowin -run coarse:
# check the flops mapped as expected
-select -assert-count 1 t:DFF
+select -assert-count 2 t:DFF
select -assert-count 1 t:DFFC
select -assert-count 1 t:DFFCE
-select -assert-count 1 t:DFFE
-select -assert-count 1 t:DFFN
+select -assert-count 0 t:DFFE
+select -assert-count 2 t:DFFN
select -assert-count 1 t:DFFNC
select -assert-count 1 t:DFFNCE
-select -assert-count 1 t:DFFNE
+select -assert-count 0 t:DFFNE
select -assert-count 1 t:DFFNP
select -assert-count 1 t:DFFNPE
select -assert-count 0 t:DFFNR
select -assert-count 0 t:DFFNRE
-select -assert-count 2 t:DFFNS
-select -assert-count 2 t:DFFNSE
+select -assert-count 3 t:DFFNS
+select -assert-count 1 t:DFFNSE
select -assert-count 1 t:DFFP
select -assert-count 1 t:DFFPE
select -assert-count 0 t:DFFR
select -assert-count 0 t:DFFRE
-select -assert-count 2 t:DFFS
-select -assert-count 2 t:DFFSE
-select -assert-count 12 t:LUT2
-
-# check the expected leftover init values
-# this would happen if your reset value is not the initial value
-# which would be weird
-select -assert-count 8 a:init
+select -assert-count 3 t:DFFS
+select -assert-count 1 t:DFFSE
+select -assert-count 4 t:LUT2
+select -assert-count 4 t:LUT4
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/run-test.sh b/tests/arch/gowin/run-test.sh
index bf19b887d..4be4b70ae 100755
--- a/tests/arch/gowin/run-test.sh
+++ b/tests/arch/gowin/run-test.sh
@@ -1,20 +1,4 @@
#!/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 -w 'Yosys has only limited support for tri-state logic at the moment.' $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
+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/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/fsm.ys b/tests/arch/ice40/fsm.ys
index 223ba070e..e3b746202 100644
--- a/tests/arch/ice40/fsm.ys
+++ b/tests/arch/ice40/fsm.ys
@@ -12,5 +12,5 @@ cd fsm # Constrain all select calls below inside the top module
select -assert-count 4 t:SB_DFF
select -assert-count 2 t:SB_DFFESR
-select -assert-count 15 t:SB_LUT4
+select -assert-max 15 t:SB_LUT4
select -assert-none t:SB_DFFESR t:SB_DFF t:SB_LUT4 %% t:* %D
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/ice40/run-test.sh b/tests/arch/ice40/run-test.sh
index bf19b887d..4be4b70ae 100755
--- a/tests/arch/ice40/run-test.sh
+++ b/tests/arch/ice40/run-test.sh
@@ -1,20 +1,4 @@
#!/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 -w 'Yosys has only limited support for tri-state logic at the moment.' $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
+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/intel_alm/add_sub.ys b/tests/arch/intel_alm/add_sub.ys
index 4cb2c2e0d..8f87adf27 100644
--- a/tests/arch/intel_alm/add_sub.ys
+++ b/tests/arch/intel_alm/add_sub.ys
@@ -1,8 +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 -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 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 5d8d3a220..d7487c40b 100644
--- a/tests/arch/intel_alm/adffs.ys
+++ b/tests/arch/intel_alm/adffs.ys
@@ -3,7 +3,19 @@ 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
+select -assert-count 1 t:MISTRAL_NOT
+
+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 -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 +27,18 @@ 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
+
+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 -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
@@ -26,7 +49,19 @@ 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
+select -assert-count 1 t:MISTRAL_ALUT2
+
+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 -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
@@ -38,11 +73,22 @@ 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
-select -assert-count 1 t:MISTRAL_NOT
-select -assert-count 1 t:MISTRAL_ALUT2
+select -assert-count 2 t:MISTRAL_NOT
-select -assert-none t:MISTRAL_FF t:MISTRAL_NOT t:MISTRAL_ALUT2 %% t:* %D
+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 -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
+select -assert-count 2 t:MISTRAL_NOT
+
+select -assert-none t:MISTRAL_FF t:MISTRAL_NOT %% t:* %D
diff --git a/tests/arch/intel_alm/blockram.ys b/tests/arch/intel_alm/blockram.ys
new file mode 100644
index 000000000..c157c3165
--- /dev/null
+++ b/tests/arch/intel_alm/blockram.ys
@@ -0,0 +1,6 @@
+read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 10 sync_ram_sdp
+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 945c318d8..56c9cabb3 100644
--- a/tests/arch/intel_alm/counter.ys
+++ b/tests/arch/intel_alm/counter.ys
@@ -2,12 +2,26 @@ 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
+
+design -reset
+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 -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 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 149b3121a..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
@@ -11,9 +11,31 @@ select -assert-count 1 t:MISTRAL_FF
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 -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
+
+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 -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
+
+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 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 67965569b..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
@@ -12,8 +12,33 @@ design -load postopt # load the post-opt design (otherwise equiv_opt loads the p
cd fsm # Constrain all select calls below inside the top module
select -assert-count 6 t:MISTRAL_FF
+select -assert-max 1 t:MISTRAL_NOT
select -assert-max 2 t:MISTRAL_ALUT2 # Clang returns 2, GCC returns 1
-select -assert-count 1 t:MISTRAL_ALUT3
-select -assert-count 5 t:MISTRAL_ALUT5
-select -assert-count 2 t:MISTRAL_ALUT6
-select -assert-none t:MISTRAL_FF t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_ALUT5 t:MISTRAL_ALUT6 %% t:* %D
+select -assert-max 1 t:MISTRAL_ALUT3
+select -assert-max 2 t:MISTRAL_ALUT4 # Clang returns 0, GCC returns 1
+select -assert-max 6 t:MISTRAL_ALUT5 # Clang returns 5, GCC returns 4
+select -assert-max 2 t:MISTRAL_ALUT6 # Clang returns 1, GCC returns 2
+select -assert-none t:MISTRAL_FF t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 t:MISTRAL_ALUT5 t:MISTRAL_ALUT6 %% t:* %D
+
+design -reset
+read_verilog ../common/fsm.v
+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 -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
+
+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 6 t:MISTRAL_FF
+select -assert-max 1 t:MISTRAL_NOT
+select -assert-max 2 t:MISTRAL_ALUT2 # Clang returns 2, GCC returns 1
+select -assert-max 2 t:MISTRAL_ALUT3 # Clang returns 2, GCC returns 1
+select -assert-max 2 t:MISTRAL_ALUT4 # Clang returns 0, GCC returns 1
+select -assert-max 6 t:MISTRAL_ALUT5 # Clang returns 5, GCC returns 4
+select -assert-max 2 t:MISTRAL_ALUT6 # Clang returns 1, GCC returns 2
+select -assert-none t:MISTRAL_FF t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_ALUT4 t:MISTRAL_ALUT5 t:MISTRAL_ALUT6 %% t:* %D
diff --git a/tests/arch/intel_alm/logic.ys b/tests/arch/intel_alm/logic.ys
index fad45db74..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
@@ -9,3 +9,17 @@ select -assert-count 1 t:MISTRAL_NOT
select -assert-count 6 t:MISTRAL_ALUT2
select -assert-count 2 t:MISTRAL_ALUT4
select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT4 %% t:* %D
+
+
+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 -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 1 t:MISTRAL_NOT
+select -assert-count 6 t:MISTRAL_ALUT2
+select -assert-count 2 t:MISTRAL_ALUT4
+select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT4 %% t:* %D \ No newline at end of file
diff --git a/tests/arch/intel_alm/lutram.ys b/tests/arch/intel_alm/lutram.ys
index 6f997b67b..9ddb1ec87 100644
--- a/tests/arch/intel_alm/lutram.ys
+++ b/tests/arch/intel_alm/lutram.ys
@@ -2,19 +2,38 @@ 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
miter -equiv -flatten -make_assert -make_outputs gold gate miter
-sat -verify -prove-asserts -seq 5 -set-init-zero -show-inputs -show-outputs miter
+sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter
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
+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 -noiopad -noclkbuf
+memory
+opt -full
+
+miter -equiv -flatten -make_assert -make_outputs gold gate miter
+sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter
+
+design -load postopt
+cd lutram_1w1r
+select -assert-count 16 t:MISTRAL_MLAB
+select -assert-count 2 t:MISTRAL_ALUT2
+select -assert-count 8 t:MISTRAL_ALUT3
+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
new file mode 100644
index 000000000..e147d93ac
--- /dev/null
+++ b/tests/arch/intel_alm/mul.ys
@@ -0,0 +1,60 @@
+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 -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 1 t:MISTRAL_MUL9X9
+select -assert-none t:MISTRAL_MUL9X9 %% t:* %D
+
+# Cyclone 10 GX does not have 9x9 multipliers.
+
+design -reset
+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 -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 1 t:MISTRAL_MUL18X18
+select -assert-none t:MISTRAL_MUL18X18 %% t:* %D
+
+design -reset
+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 -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 1 t:MISTRAL_MUL18X18
+select -assert-none t:MISTRAL_MUL18X18 %% t:* %D
+
+design -reset
+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 -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 1 t:MISTRAL_MUL27X27
+select -assert-none t:MISTRAL_MUL27X27 %% t:* %D
+
+design -reset
+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 -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 1 t:MISTRAL_MUL27X27
+select -assert-none t:MISTRAL_MUL27X27 %% t:* %D
diff --git a/tests/arch/intel_alm/mux.ys b/tests/arch/intel_alm/mux.ys
index 308e45268..6fb6ae80a 100644
--- a/tests/arch/intel_alm/mux.ys
+++ b/tests/arch/intel_alm/mux.ys
@@ -1,41 +1,84 @@
read_verilog ../common/mux.v
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
+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 -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
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
+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 -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
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 -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
+select -assert-count 2 t:MISTRAL_ALUT6
+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 cyclonev # 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
-select -assert-count 1 t:MISTRAL_ALUT5
select -assert-count 2 t:MISTRAL_ALUT6
+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 -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
+select -assert-max 2 t:MISTRAL_ALUT5
+select -assert-max 5 t:MISTRAL_ALUT6
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 cyclonev # 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 4b9b54d10..4e1896b82 100644
--- a/tests/arch/intel_alm/quartus_ice.ys
+++ b/tests/arch/intel_alm/quartus_ice.ys
@@ -10,3 +10,17 @@ EOT
synth_intel_alm -family cyclonev -quartus
select -assert-none w:*[* w:*]*
+
+design -reset
+read_verilog <<EOT
+// Verilog has syntax for raw identifiers, where you start it with \ and end it with a space.
+// This test crashes Quartus due to it parsing \a[10] as a wire slice and not a raw identifier.
+module top();
+ (* keep *) wire [31:0] \a[10] ;
+ (* keep *) wire b;
+ assign b = \a[10] [31];
+endmodule
+EOT
+
+synth_intel_alm -family cyclone10gx -quartus -noiopad -noclkbuf
+select -assert-none w:*[* w:*]*
diff --git a/tests/arch/intel_alm/run-test.sh b/tests/arch/intel_alm/run-test.sh
index bf19b887d..4be4b70ae 100755
--- a/tests/arch/intel_alm/run-test.sh
+++ b/tests/arch/intel_alm/run-test.sh
@@ -1,20 +1,4 @@
#!/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 -w 'Yosys has only limited support for tri-state logic at the moment.' $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
+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/intel_alm/shifter.ys b/tests/arch/intel_alm/shifter.ys
index 014dbd1a8..77ff98896 100644
--- a/tests/arch/intel_alm/shifter.ys
+++ b/tests/arch/intel_alm/shifter.ys
@@ -2,9 +2,20 @@ 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
+select -assert-none t:MISTRAL_FF %% t:* %D
+
+design -reset
+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 -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
select -assert-none t:MISTRAL_FF %% t:* %D
diff --git a/tests/arch/intel_alm/tribuf.ys b/tests/arch/intel_alm/tribuf.ys
index 71b05a747..fb5fecb78 100644
--- a/tests/arch/intel_alm/tribuf.ys
+++ b/tests/arch/intel_alm/tribuf.ys
@@ -4,10 +4,24 @@ 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.
select -assert-count 1 t:$_TBUF_
+select -assert-none t:$_TBUF_ %% t:* %D
+
+design -reset
+read_verilog ../common/tribuf.v
+hierarchy -top tristate
+proc
+tribuf
+flatten
+synth
+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.
+select -assert-count 1 t:$_TBUF_
select -assert-none t:$_TBUF_ %% t:* %D
diff --git a/tests/arch/machxo2/.gitignore b/tests/arch/machxo2/.gitignore
new file mode 100644
index 000000000..1d329c933
--- /dev/null
+++ b/tests/arch/machxo2/.gitignore
@@ -0,0 +1,2 @@
+*.log
+/run-test.mk
diff --git a/tests/arch/machxo2/add_sub.ys b/tests/arch/machxo2/add_sub.ys
new file mode 100644
index 000000000..d9497b818
--- /dev/null
+++ b/tests/arch/machxo2/add_sub.ys
@@ -0,0 +1,8 @@
+read_verilog ../common/add_sub.v
+hierarchy -top top
+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 top # Constrain all select calls below inside the top module
+select -assert-count 10 t:LUT4
+select -assert-none t:LUT4 t:FACADE_IO %% t:* %D
diff --git a/tests/arch/machxo2/dffs.ys b/tests/arch/machxo2/dffs.ys
new file mode 100644
index 000000000..83a79a9d6
--- /dev/null
+++ b/tests/arch/machxo2/dffs.ys
@@ -0,0 +1,19 @@
+read_verilog ../common/dffs.v
+design -save read
+
+hierarchy -top dff
+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 dff # Constrain all select calls below inside the top module
+select -assert-count 1 t:FACADE_FF
+select -assert-none t:FACADE_FF t:FACADE_IO %% t:* %D
+
+design -load read
+hierarchy -top dffe
+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 dffe # Constrain all select calls below inside the top module
+select -assert-count 2 t:FACADE_FF t:LUT4
+select -assert-none t:FACADE_FF t:LUT4 t:FACADE_IO %% t:* %D
diff --git a/tests/arch/machxo2/fsm.ys b/tests/arch/machxo2/fsm.ys
new file mode 100644
index 000000000..847a61161
--- /dev/null
+++ b/tests/arch/machxo2/fsm.ys
@@ -0,0 +1,15 @@
+read_verilog ../common/fsm.v
+hierarchy -top fsm
+proc
+flatten
+
+equiv_opt -run :prove -map +/machxo2/cells_sim.v synth_machxo2
+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-max 16 t:LUT4
+select -assert-count 6 t:FACADE_FF
+select -assert-none t:FACADE_FF t:LUT4 t:FACADE_IO %% t:* %D
diff --git a/tests/arch/machxo2/logic.ys b/tests/arch/machxo2/logic.ys
new file mode 100644
index 000000000..bf93ab128
--- /dev/null
+++ b/tests/arch/machxo2/logic.ys
@@ -0,0 +1,8 @@
+read_verilog ../common/logic.v
+hierarchy -top top
+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 top # Constrain all select calls below inside the top module
+select -assert-count 9 t:LUT4
+select -assert-none t:LUT4 t:FACADE_IO %% t:* %D
diff --git a/tests/arch/machxo2/mux.ys b/tests/arch/machxo2/mux.ys
new file mode 100644
index 000000000..7b7e62d4c
--- /dev/null
+++ b/tests/arch/machxo2/mux.ys
@@ -0,0 +1,40 @@
+read_verilog ../common/mux.v
+design -save read
+
+hierarchy -top mux2
+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 mux2 # Constrain all select calls below inside the top module
+select -assert-count 1 t:LUT4
+select -assert-none t:LUT4 t:FACADE_IO %% t:* %D
+
+design -load read
+hierarchy -top mux4
+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 mux4 # Constrain all select calls below inside the top module
+select -assert-count 2 t:LUT4
+
+select -assert-none t:LUT4 t:FACADE_IO %% t:* %D
+
+design -load read
+hierarchy -top mux8
+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 mux8 # Constrain all select calls below inside the top module
+select -assert-count 5 t:LUT4
+
+select -assert-none t:LUT4 t:FACADE_IO %% t:* %D
+
+design -load read
+hierarchy -top mux16
+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-max 12 t:LUT4
+
+select -assert-none t:LUT4 t:FACADE_IO %% t:* %D
diff --git a/tests/arch/machxo2/run-test.sh b/tests/arch/machxo2/run-test.sh
new file mode 100644
index 000000000..4be4b70ae
--- /dev/null
+++ b/tests/arch/machxo2/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/machxo2/shifter.ys b/tests/arch/machxo2/shifter.ys
new file mode 100644
index 000000000..87fdab0fa
--- /dev/null
+++ b/tests/arch/machxo2/shifter.ys
@@ -0,0 +1,10 @@
+read_verilog ../common/shifter.v
+hierarchy -top top
+proc
+flatten
+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 top # Constrain all select calls below inside the top module
+
+select -assert-count 8 t:FACADE_FF
+select -assert-none t:FACADE_FF t:FACADE_IO %% t:* %D
diff --git a/tests/arch/machxo2/tribuf.ys b/tests/arch/machxo2/tribuf.ys
new file mode 100644
index 000000000..fce342e18
--- /dev/null
+++ b/tests/arch/machxo2/tribuf.ys
@@ -0,0 +1,10 @@
+read_verilog ../common/tribuf.v
+hierarchy -top tristate
+proc
+flatten
+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:LUT4
+select -assert-none t:FACADE_IO t:LUT4 %% t:* %D
diff --git a/tests/arch/nexus/.gitignore b/tests/arch/nexus/.gitignore
new file mode 100644
index 000000000..ba42e1ee6
--- /dev/null
+++ b/tests/arch/nexus/.gitignore
@@ -0,0 +1,2 @@
+/*.log
+/run-test.mk
diff --git a/tests/arch/nexus/add_sub.ys b/tests/arch/nexus/add_sub.ys
new file mode 100644
index 000000000..4317bab81
--- /dev/null
+++ b/tests/arch/nexus/add_sub.ys
@@ -0,0 +1,21 @@
+read_verilog ../common/add_sub.v
+hierarchy -top top
+proc
+design -save orig
+
+equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # 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 10 t:LUT4
+select -assert-none t:IB t:OB t:VLO t:LUT4 %% t:* %D
+
+design -load orig
+
+equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus -abc9 # 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 6 t:LUT4
+select -assert-count 4 t:WIDEFN9
+select -assert-none t:IB t:OB t:VLO t:LUT4 t:WIDEFN9 %% t:* %D
diff --git a/tests/arch/nexus/adffs.ys b/tests/arch/nexus/adffs.ys
new file mode 100644
index 000000000..f8796425c
--- /dev/null
+++ b/tests/arch/nexus/adffs.ys
@@ -0,0 +1,44 @@
+read_verilog ../common/adffs.v
+design -save read
+
+hierarchy -top adff
+proc
+equiv_opt -async2sync -assert -map +/nexus/cells_sim.v synth_nexus # 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
+stat
+select -assert-count 1 t:FD1P3DX
+select -assert-none t:FD1P3DX t:IB t:OB t:VLO t:VHI %% t:* %D
+
+design -load read
+hierarchy -top adffn
+proc
+equiv_opt -async2sync -assert -map +/nexus/cells_sim.v synth_nexus # 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
+stat
+select -assert-count 1 t:FD1P3DX
+select -assert-count 1 t:INV
+select -assert-none t:FD1P3DX t:INV t:LUT4 t:IB t:OB t:VLO t:VHI %% t:* %D
+
+design -load read
+hierarchy -top dffs
+proc
+equiv_opt -async2sync -assert -map +/nexus/cells_sim.v synth_nexus # 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
+stat
+select -assert-count 1 t:FD1P3IX
+select -assert-count 1 t:LUT4
+select -assert-none t:FD1P3IX t:LUT4 t:IB t:OB t:VLO t:VHI %% t:* %D
+
+design -load read
+hierarchy -top ndffnr
+proc
+equiv_opt -async2sync -assert -map +/nexus/cells_sim.v synth_nexus # 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
+stat
+select -assert-count 1 t:FD1P3IX
+select -assert-count 2 t:INV
+select -assert-none t:FD1P3IX t:INV t:LUT4 t:IB t:OB t:VLO t:VHI %% t:* %D
diff --git a/tests/arch/nexus/blockram.ys b/tests/arch/nexus/blockram.ys
new file mode 100644
index 000000000..9540136d5
--- /dev/null
+++ b/tests/arch/nexus/blockram.ys
@@ -0,0 +1,18 @@
+read_verilog ../common/blockram.v
+design -save read
+
+# Check that we use the right dual and single clock variants
+
+chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 18 sync_ram_sdp
+synth_nexus -top sync_ram_sdp
+cd sync_ram_sdp
+select -assert-count 1 t:PDPSC16K
+select -assert-none t:PDPSC16K t:INV t:IB t:OB t:VLO t:VHI %% t:* %D
+
+design -reset
+read_verilog blockram_dc.v
+chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 18 sync_ram_sdp_dc
+synth_nexus -top sync_ram_sdp_dc
+cd sync_ram_sdp_dc
+select -assert-count 1 t:PDP16K
+select -assert-none t:PDP16K t:INV t:IB t:OB t:VLO t:VHI %% t:* %D
diff --git a/tests/arch/nexus/blockram_dc.v b/tests/arch/nexus/blockram_dc.v
new file mode 100644
index 000000000..4f5d4f5a6
--- /dev/null
+++ b/tests/arch/nexus/blockram_dc.v
@@ -0,0 +1,25 @@
+
+`default_nettype none
+module sync_ram_sdp_dc #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10)
+ (input wire clkw, clkr, write_enable,
+ input wire [DATA_WIDTH-1:0] data_in,
+ input wire [ADDRESS_WIDTH-1:0] address_in_r, address_in_w,
+ output wire [DATA_WIDTH-1:0] data_out);
+
+ localparam WORD = (DATA_WIDTH-1);
+ localparam DEPTH = (2**ADDRESS_WIDTH-1);
+
+ reg [WORD:0] data_out_r;
+ reg [WORD:0] memory [0:DEPTH];
+
+ always @(posedge clkw) begin
+ if (write_enable)
+ memory[address_in_w] <= data_in;
+ end
+ always @(posedge clkr) begin
+ data_out_r <= memory[address_in_r];
+ end
+
+ assign data_out = data_out_r;
+
+endmodule // sync_ram_sdp_dc
diff --git a/tests/arch/nexus/counter.ys b/tests/arch/nexus/counter.ys
new file mode 100644
index 000000000..44421e377
--- /dev/null
+++ b/tests/arch/nexus/counter.ys
@@ -0,0 +1,11 @@
+read_verilog ../common/counter.v
+hierarchy -top top
+proc
+flatten
+equiv_opt -assert -multiclock -map +/nexus/cells_sim.v synth_nexus # 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 5 t:CCU2
+select -assert-count 8 t:FD1P3DX
+select -assert-none t:CCU2 t:FD1P3DX t:IB t:OB t:VLO t:VHI %% t:* %D
diff --git a/tests/arch/nexus/dffs.ys b/tests/arch/nexus/dffs.ys
new file mode 100644
index 000000000..9ebf68bf4
--- /dev/null
+++ b/tests/arch/nexus/dffs.ys
@@ -0,0 +1,19 @@
+read_verilog ../common/dffs.v
+design -save read
+
+hierarchy -top dff
+proc
+equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # 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:FD1P3IX
+select -assert-none t:FD1P3IX t:IB t:OB t:VHI t:VLO %% t:* %D
+
+design -load read
+hierarchy -top dffe
+proc
+equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # 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:FD1P3IX
+select -assert-none t:FD1P3IX t:IB t:OB t:VHI t:VLO %% t:* %D
diff --git a/tests/arch/nexus/fsm.ys b/tests/arch/nexus/fsm.ys
new file mode 100644
index 000000000..24ad8fe5b
--- /dev/null
+++ b/tests/arch/nexus/fsm.ys
@@ -0,0 +1,19 @@
+read_verilog ../common/fsm.v
+hierarchy -top fsm
+proc
+flatten
+
+equiv_opt -run :prove -map +/nexus/cells_sim.v synth_nexus
+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
+
+stat
+
+select -assert-max 1 t:INV
+select -assert-max 2 t:LUT4
+select -assert-max 6 t:WIDEFN9
+select -assert-count 6 t:FD1P3IX
+select -assert-none t:LUT4 t:FD1P3IX t:WIDEFN9 t:INV t:IB t:OB t:VLO t:VHI %% t:* %D
diff --git a/tests/arch/nexus/logic.ys b/tests/arch/nexus/logic.ys
new file mode 100644
index 000000000..cff61b509
--- /dev/null
+++ b/tests/arch/nexus/logic.ys
@@ -0,0 +1,8 @@
+read_verilog ../common/logic.v
+hierarchy -top top
+proc
+equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # 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:LUT4
+select -assert-none t:LUT4 t:INV t:IB t:OB t:VLO t:VHI %% t:* %D
diff --git a/tests/arch/nexus/lutram.ys b/tests/arch/nexus/lutram.ys
new file mode 100644
index 000000000..6e33431b6
--- /dev/null
+++ b/tests/arch/nexus/lutram.ys
@@ -0,0 +1,19 @@
+read_verilog ../common/lutram.v
+hierarchy -top lutram_1w1r
+proc
+memory -nomap
+equiv_opt -run :prove -map +/nexus/cells_sim.v synth_nexus
+memory
+opt -full
+
+miter -equiv -flatten -make_assert -make_outputs gold gate miter
+sat -verify -prove-asserts -seq 5 -set-init-zero -show-inputs -show-outputs miter
+
+design -load postopt
+cd lutram_1w1r
+stat
+select -assert-count 8 t:WIDEFN9
+select -assert-count 12 t:LUT4
+select -assert-count 8 t:DPR16X4
+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/nexus/mul.ys b/tests/arch/nexus/mul.ys
new file mode 100644
index 000000000..65a2fd8c3
--- /dev/null
+++ b/tests/arch/nexus/mul.ys
@@ -0,0 +1,50 @@
+read_verilog ../common/mul.v
+chparam -set X_WIDTH 8 -set Y_WIDTH 8 -set A_WIDTH 16
+hierarchy -top top
+proc
+
+design -save read
+
+equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus
+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:MULT9X9
+
+select -assert-none t:IB t:OB t:VLO t:VHI t:MULT9X9 %% t:* %D
+
+
+design -reset
+read_verilog ../common/mul.v
+chparam -set X_WIDTH 16 -set Y_WIDTH 16 -set A_WIDTH 32
+hierarchy -top top
+proc
+# equivalence checking is too slow here
+synth_nexus
+cd top # Constrain all select calls below inside the top module
+select -assert-count 1 t:MULT18X18
+select -assert-none t:IB t:OB t:VLO t:VHI t:MULT18X18 %% t:* %D
+
+
+design -reset
+read_verilog ../common/mul.v
+chparam -set X_WIDTH 32 -set Y_WIDTH 16 -set A_WIDTH 48
+hierarchy -top top
+proc
+# equivalence checking is too slow here
+synth_nexus
+cd top # Constrain all select calls below inside the top module
+select -assert-count 1 t:MULT18X36
+select -assert-none t:IB t:OB t:VLO t:VHI t:MULT18X36 %% t:* %D
+
+
+design -reset
+read_verilog ../common/mul.v
+chparam -set X_WIDTH 32 -set Y_WIDTH 32 -set A_WIDTH 64
+hierarchy -top top
+proc
+# equivalence checking is too slow here
+synth_nexus
+cd top # Constrain all select calls below inside the top module
+select -assert-count 1 t:MULT36X36
+
+select -assert-none t:IB t:OB t:VLO t:VHI t:MULT36X36 %% t:* %D
diff --git a/tests/arch/nexus/mux.ys b/tests/arch/nexus/mux.ys
new file mode 100644
index 000000000..0e12d674a
--- /dev/null
+++ b/tests/arch/nexus/mux.ys
@@ -0,0 +1,43 @@
+read_verilog ../common/mux.v
+design -save read
+
+hierarchy -top mux2
+proc
+equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # 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:LUT4
+select -assert-none t:IB t:OB t:VLO t:VHI t:LUT4 t:WIDEFN9 %% t:* %D
+
+design -load read
+hierarchy -top mux4
+proc
+equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # 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:WIDEFN9
+
+select -assert-none t:IB t:OB t:VLO t:VHI t:LUT4 t:WIDEFN9 %% t:* %D
+
+design -load read
+hierarchy -top mux8
+proc
+equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # 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 4 t:LUT4
+select -assert-count 1 t:WIDEFN9
+
+select -assert-none t:IB t:OB t:VLO t:VHI t:LUT4 t:WIDEFN9 %% t:* %D
+
+design -load read
+hierarchy -top mux16
+proc
+equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # 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-min 11 t:LUT4
+select -assert-max 12 t:LUT4
+select -assert-count 1 t:WIDEFN9
+
+select -assert-none t:IB t:OB t:VLO t:VHI t:LUT4 t:WIDEFN9 %% t:* %D
diff --git a/tests/arch/nexus/run-test.sh b/tests/arch/nexus/run-test.sh
new file mode 100644
index 000000000..4be4b70ae
--- /dev/null
+++ b/tests/arch/nexus/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/nexus/shifter.ys b/tests/arch/nexus/shifter.ys
new file mode 100644
index 000000000..a8e34b0f9
--- /dev/null
+++ b/tests/arch/nexus/shifter.ys
@@ -0,0 +1,9 @@
+read_verilog ../common/shifter.v
+hierarchy -top top
+proc
+flatten
+equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # 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:FD1P3IX
+select -assert-none t:FD1P3IX t:WIDEFN9 t:INV t:IB t:OB t:VLO t:VHI %% t:* %D
diff --git a/tests/arch/nexus/tribuf.ys b/tests/arch/nexus/tribuf.ys
new file mode 100644
index 000000000..70fb7cb5f
--- /dev/null
+++ b/tests/arch/nexus/tribuf.ys
@@ -0,0 +1,12 @@
+read_verilog ../common/tribuf.v
+hierarchy -top tristate
+proc
+tribuf
+flatten
+synth
+equiv_opt -assert -map +/nexus/cells_sim.v -map +/simcells.v synth_nexus # 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 1 t:OBZ
+select -assert-count 1 t:INV
+select -assert-none t:OBZ 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/attributes_test.ys b/tests/arch/xilinx/attributes_test.ys
index 7bdd94a63..58552d8fb 100644
--- a/tests/arch/xilinx/attributes_test.ys
+++ b/tests/arch/xilinx/attributes_test.ys
@@ -16,8 +16,7 @@ select -assert-count 8 t:RAM32X1D
# Set ram_style distributed to blockram memory; will be implemented as distributed
design -reset
read_verilog ../common/memory_attributes/attributes_test.v
-prep
-setattr -mod -set ram_style "distributed" block_ram
+setattr -set ram_style "distributed" block_ram/m:*
synth_xilinx -top block_ram -noiopad
cd block_ram # Constrain all select calls below inside the top module
select -assert-count 32 t:RAM128X1D
@@ -25,8 +24,7 @@ select -assert-count 32 t:RAM128X1D
# Set synthesis, logic_block to blockram memory; will be implemented as distributed
design -reset
read_verilog ../common/memory_attributes/attributes_test.v
-prep
-setattr -mod -set logic_block 1 block_ram
+setattr -set logic_block 1 block_ram/m:*
synth_xilinx -top block_ram -noiopad
cd block_ram # Constrain all select calls below inside the top module
select -assert-count 0 t:RAMB18E1
diff --git a/tests/arch/xilinx/dsp_abc9.ys b/tests/arch/xilinx/dsp_abc9.ys
new file mode 100644
index 000000000..909e54149
--- /dev/null
+++ b/tests/arch/xilinx/dsp_abc9.ys
@@ -0,0 +1,37 @@
+read_verilog <<EOT
+module top(input [24:0] A, input [17:0] B, output [47:0] P);
+DSP48E1 #(.PREG(0)) dsp(.A(A), .B(B), .P(P));
+endmodule
+EOT
+techmap -autoproc -wb -map +/xilinx/cells_sim.v
+opt
+scc -expect 0
+
+
+design -reset
+read_verilog <<EOT
+module top(input signed [24:0] A, input signed [17:0] B, output [47:0] P);
+assign P = A * B;
+endmodule
+EOT
+synth_xilinx -abc9
+techmap -autoproc -wb -map +/xilinx/cells_sim.v
+opt -full -fine
+select -assert-count 1 t:$mul
+select -assert-count 0 t:* t:$mul %D
+
+
+design -reset
+read_verilog -icells -formal <<EOT
+module top(output [42:0] P);
+\$__MUL25X18 mul (.A(42), .B(42), .Y(P));
+assert property (P == 42*42);
+endmodule
+EOT
+techmap -map +/xilinx/xc7_dsp_map.v
+verilog_defaults -add -D ALLOW_WHITEBOX_DSP48E1
+synth_xilinx -abc9
+techmap -autoproc -wb -map +/xilinx/cells_sim.v
+opt -full -fine
+select -assert-count 0 t:* t:$assert %d
+sat -verify -prove-asserts
diff --git a/tests/arch/xilinx/fsm.ys b/tests/arch/xilinx/fsm.ys
index fec4c6082..3b1919627 100644
--- a/tests/arch/xilinx/fsm.ys
+++ b/tests/arch/xilinx/fsm.ys
@@ -13,12 +13,11 @@ design -load postopt # load the post-opt design (otherwise equiv_opt loads the p
cd fsm # Constrain all select calls below inside the top module
stat
select -assert-count 1 t:BUFG
-select -assert-count 4 t:FDRE
-select -assert-count 1 t:FDSE
-select -assert-count 1 t:LUT2
-select -assert-count 3 t:LUT5
+select -assert-count 6 t:FDRE
+select -assert-count 1 t:LUT4
+select -assert-count 4 t:LUT5
select -assert-count 1 t:LUT6
-select -assert-none t:BUFG t:FDRE t:FDSE t:LUT2 t:LUT5 t:LUT6 %% t:* %D
+select -assert-none t:BUFG t:FDRE t:LUT4 t:LUT5 t:LUT6 %% t:* %D
design -load orig
@@ -32,7 +31,7 @@ stat
select -assert-count 1 t:BUFG
select -assert-count 6 t:FDRE
select -assert-count 1 t:LUT1
-select -assert-count 3 t:LUT3
-select -assert-count 6 t:LUT4
-select -assert-count 6 t:MUXF5
+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:LUT3 t:LUT4 t:MUXF5 %% t:* %D
diff --git a/tests/arch/xilinx/latches.ys b/tests/arch/xilinx/latches.ys
index e226c2ec8..ee87fee21 100644
--- a/tests/arch/xilinx/latches.ys
+++ b/tests/arch/xilinx/latches.ys
@@ -18,9 +18,8 @@ equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad #
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:LDCE
-select -assert-count 1 t:INV
-select -assert-none t:LDCE t:INV %% t:* %D
+select -assert-none t:LDCE %% t:* %D
design -load read
diff --git a/tests/arch/xilinx/mux.ys b/tests/arch/xilinx/mux.ys
index 1b2788448..c2a23de6d 100644
--- a/tests/arch/xilinx/mux.ys
+++ b/tests/arch/xilinx/mux.ys
@@ -40,10 +40,11 @@ proc
equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # 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-max 2 t:LUT3
select -assert-max 2 t:LUT4
select -assert-min 4 t:LUT6
select -assert-max 7 t:LUT6
select -assert-max 2 t:MUXF7
dump
-select -assert-none t:LUT6 t:LUT4 t:MUXF7 %% t:* %D
+select -assert-none t:LUT6 t:LUT4 t:LUT3 t:MUXF7 %% t:* %D
diff --git a/tests/arch/xilinx/nosrl.ys b/tests/arch/xilinx/nosrl.ys
new file mode 100644
index 000000000..31bd5d377
--- /dev/null
+++ b/tests/arch/xilinx/nosrl.ys
@@ -0,0 +1,41 @@
+read_verilog <<EOT
+
+module xilinx_srl_static_test(input i, clk, output [1:0] q);
+reg head = 1'b0;
+reg [3:0] shift1 = 4'b0000;
+reg [3:0] shift2 = 4'b0000;
+
+always @(posedge clk) begin
+ head <= i;
+ shift1 <= {shift1[2:0], head};
+ shift2 <= {shift2[2:0], head};
+end
+
+assign q = {shift2[3], shift1[3]};
+endmodule
+
+EOT
+
+design -save read
+
+hierarchy -top xilinx_srl_static_test
+proc
+#equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check
+equiv_opt -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd xilinx_srl_static_test # Constrain all select calls below inside the top module
+stat
+select -assert-count 1 t:BUFG
+select -assert-count 1 t:SRL16E
+select -assert-none t:BUFG t:SRL16E %% t:* %D
+
+design -load read
+hierarchy -top xilinx_srl_static_test
+proc
+equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -nosrl -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd xilinx_srl_static_test # Constrain all select calls below inside the top module
+stat
+select -assert-count 1 t:BUFG
+select -assert-count 5 t:FDRE
+select -assert-none t:BUFG t:FDRE %% t:* %D
diff --git a/tests/arch/xilinx/pmgen_xilinx_srl.ys b/tests/arch/xilinx/pmgen_xilinx_srl.ys
index e76fb20ab..9a5e70ea9 100644
--- a/tests/arch/xilinx/pmgen_xilinx_srl.ys
+++ b/tests/arch/xilinx/pmgen_xilinx_srl.ys
@@ -35,7 +35,6 @@ design -stash gate
design -copy-from gold -as gold pmtest_xilinx_srl_pm_fixed
design -copy-from gate -as gate pmtest_xilinx_srl_pm_fixed
-dff2dffe -unmap # sat does not support flops-with-enable yet
miter -equiv -flatten -make_assert gold gate miter
sat -set-init-zero -seq 5 -verify -prove-asserts miter
@@ -52,6 +51,5 @@ design -stash gate
design -copy-from gold -as gold pmtest_xilinx_srl_pm_variable
design -copy-from gate -as gate pmtest_xilinx_srl_pm_variable
-dff2dffe -unmap # sat does not support flops-with-enable yet
miter -equiv -flatten -make_assert gold gate miter
sat -set-init-zero -seq 5 -verify -prove-asserts miter
diff --git a/tests/arch/xilinx/run-test.sh b/tests/arch/xilinx/run-test.sh
index bf19b887d..4be4b70ae 100755
--- a/tests/arch/xilinx/run-test.sh
+++ b/tests/arch/xilinx/run-test.sh
@@ -1,20 +1,4 @@
#!/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 -w 'Yosys has only limited support for tri-state logic at the moment.' $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
+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/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/arch/xilinx/xilinx_dffopt.ys b/tests/arch/xilinx/xilinx_dffopt.ys
index 2c729832e..c09699411 100644
--- a/tests/arch/xilinx/xilinx_dffopt.ys
+++ b/tests/arch/xilinx/xilinx_dffopt.ys
@@ -223,3 +223,49 @@ select -assert-count 1 t:LUT2
select -assert-none t:FDRSE t:LUT4 t:LUT2 %% t:* %D
design -reset
+
+
+read_verilog << EOT
+
+// FDSE_1, mergeable CE and S, but CE only not worth it.
+
+module t0 (...);
+input wire clk;
+input wire [7:0] i;
+output wire [7:0] o;
+
+wire [7:0] tmp ;
+
+LUT2 #(.INIT(4'h6)) lut0 (.I0(i[0]), .I1(i[1]), .O(tmp[0]));
+LUT2 #(.INIT(4'h6)) lut1 (.I0(i[1]), .I1(i[2]), .O(tmp[1]));
+
+FDSE_1 ff (.D(tmp[0]), .CE(i[7]), .S(tmp[1]), .Q(o[0]));
+
+endmodule
+
+EOT
+
+read_verilog -lib +/xilinx/cells_sim.v
+design -save t0
+
+equiv_opt -blacklist xilinx_dffopt_blacklist.txt -assert -map +/xilinx/cells_sim.v xilinx_dffopt
+design -load postopt
+clean
+
+cd t0
+select -assert-count 1 t:FDSE_1
+select -assert-count 1 t:LUT5
+select -assert-none t:FDSE_1 t:LUT5 %% t:* %D
+
+design -load t0
+
+equiv_opt -blacklist xilinx_dffopt_blacklist.txt -assert -map +/xilinx/cells_sim.v xilinx_dffopt -lut4
+design -load postopt
+clean
+
+cd t0
+select -assert-count 1 t:FDSE_1
+select -assert-count 2 t:LUT2
+select -assert-none t:FDSE_1 t:LUT2 %% t:* %D
+
+design -reset
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/gen-tests-makefile.sh b/tests/gen-tests-makefile.sh
new file mode 100755
index 000000000..ab8fb7013
--- /dev/null
+++ b/tests/gen-tests-makefile.sh
@@ -0,0 +1,94 @@
+set -eu
+
+YOSYS_BASEDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")"/../ >/dev/null 2>&1 && pwd)"
+
+# $ generate_target target_name test_command
+generate_target() {
+ target_name=$1
+ test_command=$2
+ echo "all: $target_name"
+ echo ".PHONY: $target_name"
+ echo "$target_name:"
+ printf "\t@%s\n" "$test_command"
+ printf "\t@echo 'Passed %s'\n" "$target_name"
+}
+
+# $ generate_ys_test ys_file [yosys_args]
+generate_ys_test() {
+ ys_file=$1
+ yosys_args=${2:-}
+ generate_target "$ys_file" "$YOSYS_BASEDIR/yosys -ql ${ys_file%.*}.log $yosys_args $ys_file"
+}
+
+# $ generate_bash_test bash_file
+generate_bash_test() {
+ bash_file=$1
+ generate_target "$bash_file" "bash -v $bash_file >${bash_file%.*}.log 2>&1"
+}
+
+# $ generate_tests [-y|--yosys-scripts] [-s|--prove-sv] [-b|--bash] [-a|--yosys-args yosys_args]
+generate_tests() {
+ do_ys=false
+ do_sv=false
+ do_sh=false
+ yosys_args=""
+
+ while [[ $# -gt 0 ]]; do
+ arg="$1"
+ case "$arg" in
+ -y|--yosys-scripts)
+ do_ys=true
+ shift
+ ;;
+ -s|--prove-sv)
+ do_sv=true
+ shift
+ ;;
+ -b|--bash)
+ do_sh=true
+ shift
+ ;;
+ -a|--yosys-args)
+ yosys_args+="$2"
+ shift
+ shift
+ ;;
+ *)
+ echo >&2 "Unknown argument: $1"
+ exit 1
+ esac
+ done
+
+ if [[ ! ( $do_ys = true || $do_sv = true || $do_sh = true ) ]]; then
+ echo >&2 "Error: No file types selected"
+ exit 1
+ fi
+
+ echo ".PHONY: all"
+ echo "all:"
+
+ if [[ $do_ys = true ]]; then
+ for x in *.ys; do
+ generate_ys_test "$x" "$yosys_args"
+ done
+ fi;
+ if [[ $do_sv = true ]]; then
+ for x in *.sv; do
+ if [ ! -f "${x%.sv}.ys" ]; then
+ generate_ys_test "$x" "-p \"prep -top top; sat -verify -prove-asserts\" $yosys_args"
+ fi;
+ done
+ fi;
+ if [[ $do_sh == true ]]; then
+ for s in *.sh; do
+ if [ "$s" != "run-test.sh" ]; then
+ generate_bash_test "$s"
+ fi
+ done
+ fi
+}
+
+run_tests() {
+ generate_tests "$@" > run-test.mk
+ exec ${MAKE:-make} -f run-test.mk
+}
diff --git a/tests/liberty/run-test.sh b/tests/liberty/run-test.sh
index 7e2ed2370..61f19b09b 100755
--- a/tests/liberty/run-test.sh
+++ b/tests/liberty/run-test.sh
@@ -5,6 +5,6 @@ for x in *.lib; do
echo "Running $x.."
echo "read_verilog small.v" > test.ys
echo "synth -top small" >> test.ys
- echo "dfflibmap -liberty ${x}" >> test.ys
+ echo "dfflibmap -info -liberty ${x}" >> test.ys
../../yosys -ql ${x%.lib}.log -s test.ys
done
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 8d1a8b413..c65066a9c 100755
--- a/tests/memories/run-test.sh
+++ b/tests/memories/run-test.sh
@@ -9,20 +9,24 @@ while getopts "A:S:" opt
do
case "$opt" in
A) abcopt="-A $OPTARG" ;;
- S) seed="-S $OPTARG" ;;
+ S) seed="$OPTARG" ;;
esac
done
shift "$((OPTIND-1))"
-bash ../tools/autotest.sh $abcopt $seed -G *.v
+${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/.gitignore b/tests/opt/.gitignore
index 397b4a762..8355de9dc 100644
--- a/tests/opt/.gitignore
+++ b/tests/opt/.gitignore
@@ -1 +1,2 @@
*.log
+run-test.mk
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/bug2221.ys b/tests/opt/bug2221.ys
new file mode 100644
index 000000000..8ac380243
--- /dev/null
+++ b/tests/opt/bug2221.ys
@@ -0,0 +1,16 @@
+read_verilog <<EOT
+module test (
+ input [1:0] a,
+ input [1:0] b,
+ output [5:0] y
+);
+
+wire [5:0] aa = {a, 4'h0};
+wire [5:0] bb = {b, 4'h0};
+
+assign y = aa * bb;
+
+endmodule
+EOT
+
+equiv_opt -assert opt_expr
diff --git a/tests/opt/bug2311.ys b/tests/opt/bug2311.ys
new file mode 100644
index 000000000..455147cd3
--- /dev/null
+++ b/tests/opt/bug2311.ys
@@ -0,0 +1,14 @@
+read_verilog -icells << EOT
+
+module top(...);
+
+input A;
+output Y;
+
+$_XNOR_ x (.A(A), .B(A), .Y(Y));
+
+endmodule
+
+EOT
+
+equiv_opt -assert opt_expr
diff --git a/tests/opt/bug2318.ys b/tests/opt/bug2318.ys
new file mode 100644
index 000000000..9de6f88ec
--- /dev/null
+++ b/tests/opt/bug2318.ys
@@ -0,0 +1,12 @@
+read_verilog <<EOT
+module t(input [3:0] A, input [3:0] B, output signed [3:0] Y);
+
+wire [7:0] P = A * B;
+wire signed [7:0] SP = P;
+wire signed [3:0] SB = B;
+assign Y = SP / SB;
+
+endmodule
+EOT
+
+equiv_opt -assert peepopt
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
new file mode 100644
index 000000000..71f9e0d7b
--- /dev/null
+++ b/tests/opt/opt_clean_mem.ys
@@ -0,0 +1,48 @@
+read_verilog <<EOT
+module top(...);
+
+input [7:0] wa;
+input [7:0] ra1;
+input [7:0] ra2;
+input [7:0] wd;
+input clk;
+wire [7:0] rd1;
+wire [7:0] rd2;
+
+reg [7:0] mem[0:7];
+
+always @(posedge clk)
+ mem[wa] <= wd;
+assign rd1 = mem[ra1];
+assign rd2 = mem[ra2];
+
+initial mem[8'h12] = 8'h34;
+
+endmodule
+EOT
+
+proc
+
+select -assert-count 2 t:$memrd
+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_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_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_v2
+select -assert-count 1 t:$meminit_v2
diff --git a/tests/opt/opt_dff_arst.ys b/tests/opt/opt_dff_arst.ys
new file mode 100644
index 000000000..2aa3b7a26
--- /dev/null
+++ b/tests/opt/opt_dff_arst.ys
@@ -0,0 +1,101 @@
+### Always-active ARST removal.
+
+read_verilog -icells <<EOT
+
+module top(...);
+
+input CLK;
+input [1:0] D;
+output [11:0] Q;
+input ARST;
+input EN;
+
+$adff #(.CLK_POLARITY(1'b1), .ARST_POLARITY(1'b1), .ARST_VALUE(2'h2), .WIDTH(2)) ff0 (.CLK(CLK), .ARST(1'b1), .D(D), .Q(Q[1:0]));
+$adffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .ARST_POLARITY(1'b0), .ARST_VALUE(2'h2), .WIDTH(2)) ff1 (.CLK(CLK), .ARST(1'b0), .EN(EN), .D(D), .Q(Q[3:2]));
+$adlatch #(.EN_POLARITY(1'b1), .ARST_POLARITY(1'b1), .ARST_VALUE(2'h2), .WIDTH(2)) ff2 (.EN(EN), .ARST(1'b1), .D(D), .Q(Q[5:4]));
+$adff #(.CLK_POLARITY(1'b1), .ARST_POLARITY(1'b1), .ARST_VALUE(2'h2), .WIDTH(2)) ff3 (.CLK(CLK), .ARST(1'bx), .D(D), .Q(Q[7:6]));
+$adffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .ARST_POLARITY(1'b0), .ARST_VALUE(2'h2), .WIDTH(2)) ff4 (.CLK(CLK), .ARST(1'bx), .EN(EN), .D(D), .Q(Q[9:8]));
+$adlatch #(.EN_POLARITY(1'b1), .ARST_POLARITY(1'b1), .ARST_VALUE(2'h2), .WIDTH(2)) ff5 (.EN(EN), .ARST(1'bx), .D(D), .Q(Q[11:10]));
+
+
+endmodule
+
+EOT
+
+design -save orig
+
+equiv_opt -undef -assert -multiclock opt_dff
+design -load postopt
+select -assert-none t:*
+
+design -load orig
+
+equiv_opt -undef -assert -multiclock opt_dff -keepdc
+design -load postopt
+select -assert-count 1 t:$adff
+select -assert-count 1 t:$adffe
+select -assert-count 1 t:$adlatch
+
+design -load orig
+simplemap
+
+equiv_opt -undef -assert -multiclock opt_dff
+design -load postopt
+select -assert-none t:*
+
+design -load orig
+simplemap
+
+equiv_opt -undef -assert -multiclock opt_dff -keepdc
+design -load postopt
+select -assert-count 2 t:$_DFF_???_
+select -assert-count 2 t:$_DFFE_????_
+select -assert-count 2 t:$_DLATCH_???_
+
+design -reset
+
+
+### Never-active ARST removal.
+
+read_verilog -icells <<EOT
+
+module top(...);
+
+input CLK;
+input [1:0] D;
+output [5:0] Q;
+input ARST;
+input EN;
+
+$adff #(.CLK_POLARITY(1'b1), .ARST_POLARITY(1'b1), .ARST_VALUE(2'h2), .WIDTH(2)) ff0 (.CLK(CLK), .ARST(1'b0), .D(D), .Q(Q[1:0]));
+$adffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .ARST_POLARITY(1'b0), .ARST_VALUE(2'h2), .WIDTH(2)) ff1 (.CLK(CLK), .ARST(1'b1), .EN(EN), .D(D), .Q(Q[3:2]));
+$adlatch #(.EN_POLARITY(1'b1), .ARST_POLARITY(1'b1), .ARST_VALUE(2'h2), .WIDTH(2)) ff2 (.EN(EN), .ARST(1'b0), .D(D), .Q(Q[5:4]));
+
+endmodule
+
+EOT
+
+design -save orig
+
+equiv_opt -undef -assert -multiclock opt_dff
+design -load postopt
+select -assert-none t:$adff
+select -assert-none t:$adffe
+select -assert-none t:$adlatch
+select -assert-count 1 t:$dff
+select -assert-count 1 t:$dffe
+select -assert-count 1 t:$dlatch
+
+design -load orig
+simplemap
+
+equiv_opt -undef -assert -multiclock opt_dff
+design -load postopt
+select -assert-none t:$_DFF_???_
+select -assert-none t:$_DFFE_????_
+select -assert-none t:$_DLATCH_???_
+select -assert-count 2 t:$_DFF_P_
+select -assert-count 2 t:$_DFFE_PP_
+select -assert-count 2 t:$_DLATCH_P_
+
+design -reset
diff --git a/tests/opt/opt_dff_clk.ys b/tests/opt/opt_dff_clk.ys
new file mode 100644
index 000000000..f3aefa406
--- /dev/null
+++ b/tests/opt/opt_dff_clk.ys
@@ -0,0 +1,45 @@
+### Never-toggling CLK removal.
+
+read_verilog -icells <<EOT
+
+module top(...);
+
+input EN;
+input [1:0] D;
+(* init = 18'h15555 *)
+output [17:0] Q;
+input SRST;
+input ARST;
+input [1:0] CLR;
+input [1:0] SET;
+
+$dff #(.CLK_POLARITY(1'b1), .WIDTH(2)) ff0 (.CLK(1'b0), .D(D), .Q(Q[1:0]));
+$dffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .WIDTH(2)) ff1 (.CLK(1'b1), .EN(EN), .D(D), .Q(Q[3:2]));
+$adff #(.CLK_POLARITY(1'b1), .ARST_POLARITY(1'b1), .ARST_VALUE(2'h2), .WIDTH(2)) ff2 (.CLK(1'bx), .ARST(ARST), .D(D), .Q(Q[5:4]));
+$adffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b0), .ARST_POLARITY(1'b1), .ARST_VALUE(2'h2), .WIDTH(2)) ff3 (.CLK(1'b0), .EN(EN), .ARST(ARST), .D(D), .Q(Q[7:6]));
+$sdff #(.CLK_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_VALUE(2'h2), .WIDTH(2)) ff4 (.CLK(1'b1), .SRST(SRST), .D(D), .Q(Q[9:8]));
+$sdffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_VALUE(2'h2), .WIDTH(2)) ff5 (.CLK(1'bx), .EN(EN), .SRST(SRST), .D(D), .Q(Q[11:10]));
+$sdffce #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_VALUE(2'h2), .WIDTH(2)) ff6 (.CLK(1'bx), .EN(EN), .SRST(SRST), .D(D), .Q(Q[13:12]));
+$dffsr #(.CLK_POLARITY(1'b1), .CLR_POLARITY(1'b1), .SET_POLARITY(1'b0), .WIDTH(2)) ff7 (.CLK(1'b1), .SET(SET), .CLR(CLR), .D(D), .Q(Q[15:14]));
+$dffsre #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b0), .CLR_POLARITY(1'b1), .SET_POLARITY(1'b0), .WIDTH(2)) ff8 (.CLK(1'bx), .EN(EN), .SET(SET), .CLR(CLR), .D(D), .Q(Q[17:16]));
+
+endmodule
+
+EOT
+
+design -save orig
+
+equiv_opt -undef -assert -multiclock opt_dff -keepdc
+design -load postopt
+select -assert-count 2 t:$dlatch
+select -assert-count 2 t:$sr
+select -assert-none t:$dlatch t:$sr %% %n t:* %i
+
+design -load orig
+simplemap
+
+equiv_opt -undef -assert -multiclock opt_dff -keepdc
+design -load postopt
+select -assert-count 4 t:$_DLATCH_?_
+select -assert-count 4 t:$_SR_??_
+select -assert-none t:$_DLATCH_?_ t:$_SR_??_ %% %n t:* %i
diff --git a/tests/opt/opt_dff_const.ys b/tests/opt/opt_dff_const.ys
new file mode 100644
index 000000000..6a7dec7fa
--- /dev/null
+++ b/tests/opt/opt_dff_const.ys
@@ -0,0 +1,49 @@
+### Replace FFs with a const.
+
+read_verilog -icells <<EOT
+
+module top(...);
+
+input CLK;
+input EN;
+(* init=84'haaaaaaaaaaaaaaaaaaaaa *)
+output [83:0] Q;
+input SRST;
+input ARST;
+input [3:0] CLR;
+input [3:0] SET;
+
+$dff #(.CLK_POLARITY(1'b1), .WIDTH(4)) ff0 (.CLK(CLK), .D(4'hc), .Q(Q[3:0]));
+$dffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .WIDTH(4)) ff1 (.CLK(CLK), .EN(EN), .D(4'hc), .Q(Q[7:4]));
+$adff #(.CLK_POLARITY(1'b1), .ARST_POLARITY(1'b1), .ARST_VALUE(8'hf0), .WIDTH(8)) ff2 (.CLK(CLK), .ARST(ARST), .D(8'hcc), .Q(Q[15:8]));
+$adffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b0), .ARST_POLARITY(1'b1), .ARST_VALUE(8'hf0), .WIDTH(8)) ff3 (.CLK(CLK), .EN(EN), .ARST(ARST), .D(8'hcc), .Q(Q[23:16]));
+$sdff #(.CLK_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_VALUE(8'hf0), .WIDTH(8)) ff4 (.CLK(CLK), .SRST(SRST), .D(8'hcc), .Q(Q[31:24]));
+$sdffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_VALUE(8'hf0), .WIDTH(8)) ff5 (.CLK(CLK), .EN(EN), .SRST(SRST), .D(8'hcc), .Q(Q[39:32]));
+$sdffce #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_VALUE(8'hf0), .WIDTH(8)) ff6 (.CLK(CLK), .EN(EN), .SRST(SRST), .D(8'hcc), .Q(Q[47:40]));
+$dffsr #(.CLK_POLARITY(1'b1), .CLR_POLARITY(1'b1), .SET_POLARITY(1'b0), .WIDTH(8)) ff7 (.CLK(CLK), .SET({SET, 4'hf}), .CLR({4'h0, CLR}), .D(8'hcc), .Q(Q[55:48]));
+$dffsre #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b0), .CLR_POLARITY(1'b0), .SET_POLARITY(1'b1), .WIDTH(8)) ff8 (.CLK(CLK), .EN(EN), .SET({SET, 4'h0}), .CLR({4'hf, CLR}), .D(8'hcc), .Q(Q[63:56]));
+
+$dlatch #(.EN_POLARITY(1'b1), .WIDTH(4)) ff9 (.EN(EN), .D(4'hc), .Q(Q[67:64]));
+$adlatch #(.EN_POLARITY(1'b0), .ARST_POLARITY(1'b1), .ARST_VALUE(8'hf0), .WIDTH(8)) ff10 (.EN(EN), .ARST(ARST), .D(8'hcc), .Q(Q[75:68]));
+$dlatchsr #(.EN_POLARITY(1'b0), .CLR_POLARITY(1'b1), .SET_POLARITY(1'b1), .WIDTH(8)) ff11 (.EN(EN), .SET({SET, 4'h0}), .CLR({4'h0, CLR}), .D(8'hcc), .Q(Q[83:76]));
+
+endmodule
+
+EOT
+
+design -save orig
+
+equiv_opt -undef -assert -multiclock opt_dff
+design -load postopt
+select -assert-count 1 t:$dff r:WIDTH=2 %i
+select -assert-count 1 t:$dffe r:WIDTH=2 %i
+select -assert-count 1 t:$adff r:WIDTH=6 %i
+select -assert-count 1 t:$adffe r:WIDTH=6 %i
+select -assert-count 1 t:$sdff r:WIDTH=6 %i
+select -assert-count 1 t:$sdffe r:WIDTH=6 %i
+select -assert-count 1 t:$sdffce r:WIDTH=6 %i
+select -assert-count 1 t:$dffsr r:WIDTH=6 %i
+select -assert-count 1 t:$dffsre r:WIDTH=6 %i
+select -assert-count 1 t:$dlatch r:WIDTH=2 %i
+select -assert-count 1 t:$adlatch r:WIDTH=6 %i
+select -assert-count 1 t:$dlatchsr r:WIDTH=6 %i
diff --git a/tests/opt/opt_dff_dffmux.ys b/tests/opt/opt_dff_dffmux.ys
new file mode 100644
index 000000000..43190cc31
--- /dev/null
+++ b/tests/opt/opt_dff_dffmux.ys
@@ -0,0 +1,129 @@
+design -reset
+read_verilog <<EOT
+module opt_dffmuxext_unsigned(input clk, ce, input [1:0] i, output reg [3:0] o);
+ always @(posedge clk) if (ce) o <= i;
+endmodule
+EOT
+
+proc
+equiv_opt -assert opt
+design -load postopt
+select -assert-count 1 t:$dffe r:WIDTH=2 %i
+select -assert-count 0 t:$dffe %% t:* %D
+
+####################
+
+design -reset
+read_verilog <<EOT
+module opt_dffmuxext_signed(input clk, ce, input signed [1:0] i, output reg signed [3:0] o);
+ always @(posedge clk) if (ce) o <= i;
+endmodule
+EOT
+
+proc
+equiv_opt -assert opt
+design -load postopt
+wreduce
+select -assert-count 1 t:$dffe r:WIDTH=2 %i
+select -assert-count 0 t:$dffe %% t:* %D
+
+###################
+
+design -reset
+read_verilog <<EOT
+module opt_dffmuxext_const(input clk, ce, input [1:0] i, output reg [5:0] o);
+ always @(posedge clk) if (ce) o <= {1'b0, i[1], 2'b1x, i[0], 1'bz};
+endmodule
+EOT
+
+proc
+equiv_opt -assert opt
+design -load postopt
+select -assert-count 1 t:$dffe r:WIDTH=2 %i
+select -assert-count 0 t:$dffe %% t:* %D
+
+###################
+
+design -reset
+read_verilog <<EOT
+module opt_dffmuxext_const_init(input clk, ce, input [1:0] i, (* init=6'b0x00x1 *) output reg [5:0] o);
+ always @(posedge clk) if (ce) o <= {1'b0, i[1], 2'b1x, i[0], 1'bz};
+endmodule
+EOT
+
+proc
+equiv_opt -assert opt
+design -load postopt
+select -assert-count 1 t:$dffe r:WIDTH=4 %i
+select -assert-count 0 t:$dffe %% t:* %D
+
+####################
+
+design -reset
+read_verilog <<EOT
+module opt_dffmuxext_unsigned_rst(input clk, ce, rst, input [1:0] i, output reg [3:0] o);
+ always @(posedge clk) if (rst) o <= 0; else if (ce) o <= i;
+endmodule
+EOT
+
+proc
+equiv_opt -assert opt
+design -load postopt
+wreduce
+select -assert-count 1 t:$sdffe r:WIDTH=2 %i
+select -assert-count 0 t:$sdffe %% t:* %D
+
+####################
+
+design -reset
+read_verilog <<EOT
+module opt_dffmuxext_signed_rst(input clk, ce, rstn, input signed [1:0] i, output reg signed [3:0] o);
+ always @(posedge clk) begin
+ if (ce) o <= i;
+ if (!rstn) o <= 4'b1111;
+ end
+endmodule
+EOT
+
+proc
+equiv_opt -assert opt
+design -load postopt
+wreduce
+select -assert-count 1 t:$sdffe r:WIDTH=2 %i
+select -assert-count 0 t:$sdffe %% t:* %D
+
+####################
+
+design -reset
+read_verilog <<EOT
+module opt_dffmuxext_signed_rst_init(input clk, ce, rstn, input signed [1:0] i, output reg signed [3:0] o);
+ initial o <= 4'b0010;
+ always @(posedge clk) begin
+ if (ce) o <= i;
+ if (!rstn) o <= 4'b1111;
+ end
+endmodule
+EOT
+
+proc
+# NB: equiv_opt uses equiv_induct which covers
+# only the induction half of temporal induction
+# --- missing the base-case half
+# This makes it akin to `sat -tempinduct-inductonly`
+# instead of `sat -tempinduct-baseonly` or
+# `sat -tempinduct` which is necessary for this
+# testcase
+#equiv_opt -assert opt
+
+design -save gold
+opt
+wreduce
+design -stash gate
+design -import gold -as gold
+design -import gate -as gate
+miter -equiv -flatten -make_assert -make_outputs gold gate miter
+sat -tempinduct -verify -prove-asserts -show-ports miter
+
+design -load gate
+select -assert-count 1 t:$sdffe r:WIDTH=3 %i
+select -assert-count 0 t:$sdffe %% t:* %D
diff --git a/tests/opt/opt_dff_en.ys b/tests/opt/opt_dff_en.ys
new file mode 100644
index 000000000..06ee6c63d
--- /dev/null
+++ b/tests/opt/opt_dff_en.ys
@@ -0,0 +1,157 @@
+### Always-active EN removal.
+
+read_verilog -icells <<EOT
+
+module top(...);
+
+input CLK;
+input [1:0] D;
+output [15:0] Q;
+input SRST;
+input ARST;
+input [1:0] CLR;
+input [1:0] SET;
+
+$dffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .WIDTH(2)) ff0 (.CLK(CLK), .EN(1'b1), .D(D), .Q(Q[1:0]));
+$adffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b0), .ARST_POLARITY(1'b1), .ARST_VALUE(2'h2), .WIDTH(2)) ff1 (.CLK(CLK), .EN(1'b0), .ARST(ARST), .D(D), .Q(Q[3:2]));
+$sdffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_VALUE(2'h2), .WIDTH(2)) ff2 (.CLK(CLK), .EN(1'b1), .SRST(SRST), .D(D), .Q(Q[5:4]));
+$sdffce #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_VALUE(2'h2), .WIDTH(2)) ff3 (.CLK(CLK), .EN(1'b1), .SRST(SRST), .D(D), .Q(Q[7:6]));
+$dffsre #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b0), .CLR_POLARITY(1'b1), .SET_POLARITY(1'b0), .WIDTH(2)) ff4 (.CLK(CLK), .EN(1'b0), .SET(SET), .CLR(CLR), .D(D), .Q(Q[9:8]));
+
+$dlatch #(.EN_POLARITY(1'b1), .WIDTH(2)) ff5 (.EN(1'b1), .D(D), .Q(Q[11:10]));
+$adlatch #(.EN_POLARITY(1'b0), .ARST_POLARITY(1'b1), .ARST_VALUE(2'h2), .WIDTH(2)) ff6 (.EN(1'b0), .ARST(ARST), .D(D), .Q(Q[13:12]));
+$dlatchsr #(.EN_POLARITY(1'b0), .CLR_POLARITY(1'b1), .SET_POLARITY(1'b0), .WIDTH(2)) ff7 (.EN(1'b0), .SET(SET), .CLR(CLR), .D(D), .Q(Q[15:14]));
+
+endmodule
+
+EOT
+
+design -save orig
+
+# Equivalence check will fail for unmapped adlatch and dlatchsr due to negative hold hack.
+delete top/ff6 top/ff7
+equiv_opt -undef -assert -multiclock opt_dff
+
+design -load orig
+delete top/ff6 top/ff7
+simplemap
+equiv_opt -undef -assert -multiclock opt_dff
+
+design -load orig
+opt_dff
+select -assert-count 0 t:$dffe
+select -assert-count 0 t:$adffe
+select -assert-count 0 t:$sdffe
+select -assert-count 0 t:$sdffce
+select -assert-count 0 t:$dffsre
+select -assert-count 0 t:$dlatch
+select -assert-count 0 t:$adlatch
+select -assert-count 0 t:$dlatchsr
+select -assert-count 1 t:$dff
+select -assert-count 2 t:$sdff
+select -assert-count 1 t:$adff
+select -assert-count 1 t:$dffsr
+
+design -load orig
+simplemap
+opt_dff
+select -assert-count 0 t:$_DFFE_*
+select -assert-count 0 t:$_SDFFE_*
+select -assert-count 0 t:$_SDFFCE_*
+select -assert-count 0 t:$_DFFSRE_*
+select -assert-count 0 t:$_DLATCH*
+select -assert-count 2 t:$_DFF_P_
+select -assert-count 4 t:$_SDFF_PP?_
+select -assert-count 2 t:$_DFF_PP?_
+select -assert-count 2 t:$_DFFSR_PNP_
+
+design -reset
+
+
+
+### Never-active EN removal.
+
+read_verilog -icells <<EOT
+
+module top(...);
+
+input CLK;
+input [1:0] D;
+(* init = 32'h55555555 *)
+output [31:0] Q;
+input SRST;
+input ARST;
+input [1:0] CLR;
+input [1:0] SET;
+
+$dffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .WIDTH(2)) ff0 (.CLK(CLK), .EN(1'b0), .D(D), .Q(Q[1:0]));
+$adffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b0), .ARST_POLARITY(1'b1), .ARST_VALUE(2'h2), .WIDTH(2)) ff1 (.CLK(CLK), .EN(1'b1), .ARST(ARST), .D(D), .Q(Q[3:2]));
+$sdffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_VALUE(2'h2), .WIDTH(2)) ff2 (.CLK(CLK), .EN(1'b0), .SRST(SRST), .D(D), .Q(Q[5:4]));
+$sdffce #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_VALUE(2'h2), .WIDTH(2)) ff3 (.CLK(CLK), .EN(1'b0), .SRST(SRST), .D(D), .Q(Q[7:6]));
+$dffsre #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b0), .CLR_POLARITY(1'b1), .SET_POLARITY(1'b0), .WIDTH(2)) ff4 (.CLK(CLK), .EN(1'b1), .SET(SET), .CLR(CLR), .D(D), .Q(Q[9:8]));
+
+$dlatch #(.EN_POLARITY(1'b1), .WIDTH(2)) ff5 (.EN(1'b0), .D(D), .Q(Q[11:10]));
+$adlatch #(.EN_POLARITY(1'b0), .ARST_POLARITY(1'b1), .ARST_VALUE(2'h2), .WIDTH(2)) ff6 (.EN(1'b1), .ARST(ARST), .D(D), .Q(Q[13:12]));
+$dlatchsr #(.EN_POLARITY(1'b0), .CLR_POLARITY(1'b1), .SET_POLARITY(1'b0), .WIDTH(2)) ff7 (.EN(1'b1), .SET(SET), .CLR(CLR), .D(D), .Q(Q[15:14]));
+
+$dffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .WIDTH(2)) ff8 (.CLK(CLK), .EN(1'bx), .D(D), .Q(Q[17:16]));
+$adffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b0), .ARST_POLARITY(1'b1), .ARST_VALUE(2'h2), .WIDTH(2)) ff9 (.CLK(CLK), .EN(1'bx), .ARST(ARST), .D(D), .Q(Q[19:18]));
+$sdffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_VALUE(2'h2), .WIDTH(2)) ff10 (.CLK(CLK), .EN(1'bx), .SRST(SRST), .D(D), .Q(Q[21:20]));
+$sdffce #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_VALUE(2'h2), .WIDTH(2)) ff11 (.CLK(CLK), .EN(1'bx), .SRST(SRST), .D(D), .Q(Q[23:22]));
+$dffsre #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b0), .CLR_POLARITY(1'b1), .SET_POLARITY(1'b0), .WIDTH(2)) ff12 (.CLK(CLK), .EN(1'bx), .SET(SET), .CLR(CLR), .D(D), .Q(Q[25:24]));
+
+$dlatch #(.EN_POLARITY(1'b1), .WIDTH(2)) ff13 (.EN(1'bx), .D(D), .Q(Q[27:26]));
+$adlatch #(.EN_POLARITY(1'b0), .ARST_POLARITY(1'b1), .ARST_VALUE(2'h2), .WIDTH(2)) ff14 (.EN(1'bx), .ARST(ARST), .D(D), .Q(Q[29:28]));
+$dlatchsr #(.EN_POLARITY(1'b0), .CLR_POLARITY(1'b1), .SET_POLARITY(1'b0), .WIDTH(2)) ff15 (.EN(1'bx), .SET(SET), .CLR(CLR), .D(D), .Q(Q[31:30]));
+
+endmodule
+
+EOT
+
+design -save orig
+
+equiv_opt -undef -assert -multiclock opt_dff
+design -load postopt
+select -assert-count 2 t:$dffe
+select -assert-count 4 t:$dlatch
+select -assert-count 4 t:$sr
+select -assert-none t:$dffe t:$dlatch t:$sr %% %n t:* %i
+
+design -load orig
+
+equiv_opt -undef -assert -multiclock opt_dff -keepdc
+design -load postopt
+select -assert-count 2 t:$dffe
+select -assert-count 1 t:$adffe
+select -assert-count 1 t:$sdffe
+select -assert-count 1 t:$sdffce
+select -assert-count 1 t:$dffsre
+select -assert-count 3 t:$dlatch
+select -assert-count 1 t:$adlatch
+select -assert-count 1 t:$dlatchsr
+select -assert-count 2 t:$sr
+
+design -load orig
+simplemap
+
+equiv_opt -undef -assert -multiclock opt_dff
+design -load postopt
+select -assert-count 4 t:$_DFFE_??_
+select -assert-count 8 t:$_DLATCH_?_
+select -assert-count 8 t:$_SR_??_
+select -assert-none t:$_DFFE_??_ t:$_DLATCH_?_ t:$_SR_??_ %% %n t:* %i
+
+design -load orig
+simplemap
+
+equiv_opt -undef -assert -multiclock opt_dff -keepdc
+design -load postopt
+select -assert-count 4 t:$_DFFE_??_
+select -assert-count 2 t:$_DFFE_????_
+select -assert-count 2 t:$_SDFFE_????_
+select -assert-count 2 t:$_SDFFCE_????_
+select -assert-count 2 t:$_DFFSRE_????_
+select -assert-count 6 t:$_DLATCH_?_
+select -assert-count 2 t:$_DLATCH_???_
+select -assert-count 2 t:$_DLATCHSR_???_
+select -assert-count 4 t:$_SR_??_
diff --git a/tests/opt/opt_dff_mux.ys b/tests/opt/opt_dff_mux.ys
new file mode 100644
index 000000000..ed01bed59
--- /dev/null
+++ b/tests/opt/opt_dff_mux.ys
@@ -0,0 +1,86 @@
+### CE and SRST matching.
+
+read_verilog -icells <<EOT
+
+module top(...);
+
+input CLK;
+input NE, NS;
+input EN;
+output [23:0] Q;
+input [23:0] D;
+input SRST;
+input ARST;
+input [1:0] CLR;
+input [1:0] SET;
+
+$dff #(.CLK_POLARITY(1'b1), .WIDTH(2)) ff0 (.CLK(CLK), .D(NS ? 2'h2 : NE ? D[1:0] : Q[1:0]), .Q(Q[1:0]));
+$dffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .WIDTH(2)) ff1 (.CLK(CLK), .EN(EN), .D(NS ? 2'h2 : NE ? D[3:2] : Q[3:2]), .Q(Q[3:2]));
+$adff #(.CLK_POLARITY(1'b1), .ARST_POLARITY(1'b1), .ARST_VALUE(2'h2), .WIDTH(2)) ff2 (.CLK(CLK), .ARST(ARST), .D(NS ? 2'h2 : NE ? D[5:4] : Q[5:4]), .Q(Q[5:4]));
+$adffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b0), .ARST_POLARITY(1'b1), .ARST_VALUE(2'h2), .WIDTH(2)) ff3 (.CLK(CLK), .EN(EN), .ARST(ARST), .D(NS ? 2'h2 : NE ? D[7:6] : Q[7:6]), .Q(Q[7:6]));
+$sdff #(.CLK_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_VALUE(2'h2), .WIDTH(2)) ff4 (.CLK(CLK), .SRST(SRST), .D(NS ? 2'h2 : NE ? D[9:8] : Q[9:8]), .Q(Q[9:8]));
+$sdffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_VALUE(2'h2), .WIDTH(2)) ff5 (.CLK(CLK), .EN(EN), .SRST(SRST), .D(NS ? 2'h2 : NE ? D[11:10] : Q[11:10]), .Q(Q[11:10]));
+$sdffce #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_VALUE(2'h2), .WIDTH(2)) ff6 (.CLK(CLK), .EN(EN), .SRST(SRST), .D(NS ? 2'h2 : NE ? D[13:12] : Q[13:12]), .Q(Q[13:12]));
+$dffsr #(.CLK_POLARITY(1'b1), .CLR_POLARITY(1'b1), .SET_POLARITY(1'b0), .WIDTH(2)) ff7 (.CLK(CLK), .SET(SET), .CLR(CLR), .D(NS ? 2'h2 : NE ? D[15:14] : Q[15:14]), .Q(Q[15:14]));
+$dffsre #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b0), .CLR_POLARITY(1'b1), .SET_POLARITY(1'b0), .WIDTH(2)) ff8 (.CLK(CLK), .EN(EN), .SET(SET), .CLR(CLR), .D(NS ? 2'h2 : NE ? D[17:16] : Q[17:16]), .Q(Q[17:16]));
+
+endmodule
+
+EOT
+
+design -save orig
+
+equiv_opt -undef -assert -multiclock opt_dff -keepdc
+design -load postopt
+clean
+select -assert-count 0 t:$dff
+select -assert-count 0 t:$dffe
+select -assert-count 0 t:$adff
+select -assert-count 2 t:$adffe
+select -assert-count 0 t:$dffsr
+select -assert-count 2 t:$dffsre
+select -assert-count 0 t:$sdff
+select -assert-count 3 t:$sdffe
+select -assert-count 2 t:$sdffce
+
+design -load orig
+
+equiv_opt -undef -assert -multiclock opt_dff -nodffe -nosdff
+design -load postopt
+clean
+select -assert-count 1 t:$dff
+select -assert-count 1 t:$dffe
+select -assert-count 1 t:$adff
+select -assert-count 1 t:$adffe
+select -assert-count 1 t:$dffsr
+select -assert-count 1 t:$dffsre
+select -assert-count 1 t:$sdff
+select -assert-count 1 t:$sdffe
+select -assert-count 1 t:$sdffce
+equiv_opt -undef -assert -multiclock opt_dff -nodffe
+design -load postopt
+clean
+select -assert-count 0 t:$dff
+select -assert-count 0 t:$dffe
+select -assert-count 1 t:$adff
+select -assert-count 1 t:$adffe
+select -assert-count 1 t:$dffsr
+select -assert-count 1 t:$dffsre
+select -assert-count 2 t:$sdff
+select -assert-count 1 t:$sdffe
+select -assert-count 2 t:$sdffce
+
+design -load orig
+
+equiv_opt -undef -assert -multiclock opt_dff -nosdff
+design -load postopt
+clean
+select -assert-count 0 t:$dff
+select -assert-count 2 t:$dffe
+select -assert-count 0 t:$adff
+select -assert-count 2 t:$adffe
+select -assert-count 0 t:$dffsr
+select -assert-count 2 t:$dffsre
+select -assert-count 0 t:$sdff
+select -assert-count 2 t:$sdffe
+select -assert-count 1 t:$sdffce
diff --git a/tests/opt/opt_dff_qd.ys b/tests/opt/opt_dff_qd.ys
new file mode 100644
index 000000000..afc96c42f
--- /dev/null
+++ b/tests/opt/opt_dff_qd.ys
@@ -0,0 +1,56 @@
+### Q = D case.
+
+read_verilog -icells <<EOT
+
+module top(...);
+
+input CLK;
+input EN;
+(* init = 24'h555555 *)
+output [23:0] Q;
+input SRST;
+input ARST;
+input [1:0] CLR;
+input [1:0] SET;
+
+$dff #(.CLK_POLARITY(1'b1), .WIDTH(2)) ff0 (.CLK(CLK), .D(Q[1:0]), .Q(Q[1:0]));
+$dffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .WIDTH(2)) ff1 (.CLK(CLK), .EN(EN), .D(Q[3:2]), .Q(Q[3:2]));
+$adff #(.CLK_POLARITY(1'b1), .ARST_POLARITY(1'b1), .ARST_VALUE(2'h2), .WIDTH(2)) ff2 (.CLK(CLK), .ARST(ARST), .D(Q[5:4]), .Q(Q[5:4]));
+$adffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b0), .ARST_POLARITY(1'b1), .ARST_VALUE(2'h2), .WIDTH(2)) ff3 (.CLK(CLK), .EN(EN), .ARST(ARST), .D(Q[7:6]), .Q(Q[7:6]));
+$sdff #(.CLK_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_VALUE(2'h2), .WIDTH(2)) ff4 (.CLK(CLK), .SRST(SRST), .D(Q[9:8]), .Q(Q[9:8]));
+$sdffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_VALUE(2'h2), .WIDTH(2)) ff5 (.CLK(CLK), .EN(EN), .SRST(SRST), .D(Q[11:10]), .Q(Q[11:10]));
+$sdffce #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_VALUE(2'h2), .WIDTH(2)) ff6 (.CLK(CLK), .EN(EN), .SRST(SRST), .D(Q[13:12]), .Q(Q[13:12]));
+$dffsr #(.CLK_POLARITY(1'b1), .CLR_POLARITY(1'b1), .SET_POLARITY(1'b0), .WIDTH(2)) ff7 (.CLK(CLK), .SET(SET), .CLR(CLR), .D(Q[15:14]), .Q(Q[15:14]));
+$dffsre #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b0), .CLR_POLARITY(1'b1), .SET_POLARITY(1'b0), .WIDTH(2)) ff8 (.CLK(CLK), .EN(EN), .SET(SET), .CLR(CLR), .D(Q[17:16]), .Q(Q[17:16]));
+
+$dlatch #(.EN_POLARITY(1'b1), .WIDTH(2)) ff9 (.EN(EN), .D(Q[19:18]), .Q(Q[19:18]));
+$adlatch #(.EN_POLARITY(1'b0), .ARST_POLARITY(1'b1), .ARST_VALUE(2'h2), .WIDTH(2)) ff10 (.EN(EN), .ARST(ARST), .D(Q[21:20]), .Q(Q[21:20]));
+$dlatchsr #(.EN_POLARITY(1'b0), .CLR_POLARITY(1'b1), .SET_POLARITY(1'b0), .WIDTH(2)) ff11 (.EN(EN), .SET(SET), .CLR(CLR), .D(Q[23:22]), .Q(Q[23:22]));
+
+endmodule
+
+EOT
+
+design -save orig
+
+# Equivalence check will fail for unmapped adlatch and dlatchsr due to negative hold hack.
+delete top/ff10 top/ff11
+equiv_opt -undef -assert -multiclock opt_dff -keepdc
+
+design -load orig
+opt_dff -keepdc
+select -assert-count 1 t:$and
+select -assert-count 3 t:$dffe
+select -assert-count 3 t:$dlatch
+select -assert-count 3 t:$sr
+select -assert-none t:$and t:$dffe t:$dlatch t:$sr %% %n t:* %i
+
+design -load orig
+simplemap
+opt_dff -keepdc
+select -assert-count 2 t:$_AND_
+select -assert-count 6 t:$_DFFE_??_
+select -assert-count 6 t:$_DLATCH_?_
+select -assert-count 6 t:$_SR_??_
+select -assert-none t:$_AND_ t:$_DFFE_??_ t:$_DLATCH_?_ t:$_SR_??_ %% %n t:* %i
+
diff --git a/tests/opt/opt_dff_sr.ys b/tests/opt/opt_dff_sr.ys
new file mode 100644
index 000000000..0961cb11e
--- /dev/null
+++ b/tests/opt/opt_dff_sr.ys
@@ -0,0 +1,309 @@
+### Always-active SET/CLR removal.
+
+read_verilog -icells <<EOT
+
+module top(...);
+
+input CLK;
+input [5:0] D;
+output [23:0] Q;
+input CLR;
+input SET;
+input EN;
+
+$dffsr #(.CLK_POLARITY(1'b1), .SET_POLARITY(1'b1), .CLR_POLARITY(1'b1), .WIDTH(6)) ff0 (.CLK(CLK), .CLR({CLR, CLR, CLR, 1'b1, 1'b0, 1'bx}), .SET({1'b1, 1'b0, 1'bx, SET, SET, SET}), .D(D), .Q(Q[5:0]));
+$dffsre #(.CLK_POLARITY(1'b1), .SET_POLARITY(1'b0), .CLR_POLARITY(1'b0), .EN_POLARITY(1'b1), .WIDTH(6)) ff1 (.CLK(CLK), .EN(EN), .CLR({CLR, CLR, CLR, 1'b1, 1'b0, 1'bx}), .SET({1'b1, 1'b0, 1'bx, SET, SET, SET}), .D(D), .Q(Q[11:6]));
+$dlatchsr #(.SET_POLARITY(1'b0), .CLR_POLARITY(1'b1), .EN_POLARITY(1'b1), .WIDTH(6)) ff2 (.EN(EN), .CLR({CLR, CLR, CLR, 1'b1, 1'b0, 1'bx}), .SET({1'b1, 1'b0, 1'bx, SET, SET, SET}), .D(D), .Q(Q[17:12]));
+$sr #(.SET_POLARITY(1'b1), .CLR_POLARITY(1'b0), .WIDTH(6)) ff3 (.CLR({CLR, CLR, CLR, 1'b1, 1'b0, 1'bx}), .SET({1'b1, 1'b0, 1'bx, SET, SET, SET}), .Q(Q[23:18]));
+
+endmodule
+
+EOT
+
+design -save orig
+
+# 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
+select -assert-count 1 t:$dffsre r:WIDTH=2 %i
+select -assert-count 1 t:$dlatchsr
+select -assert-count 1 t:$dlatchsr r:WIDTH=2 %i
+select -assert-none t:$sr
+
+design -load orig
+
+#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
+select -assert-count 1 t:$dffsre r:WIDTH=4 %i
+select -assert-count 1 t:$dlatchsr
+select -assert-count 1 t:$dlatchsr r:WIDTH=4 %i
+select -assert-count 1 t:$sr
+select -assert-count 1 t:$sr r:WIDTH=4 %i
+
+design -load orig
+simplemap
+
+#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_
+select -assert-count 1 t:$_DFFE_PN1P_
+select -assert-count 1 t:$_DLATCH_PP0_
+select -assert-count 1 t:$_DLATCH_PN1_
+select -assert-none t:$_DFF_PP0_ t:$_DFF_PP1_ t:$_DFFE_PN0P_ t:$_DFFE_PN1P_ t:$_DLATCH_PP0_ t:$_DLATCH_PN1_ t:$_NOT_ %% %n t:* %i
+
+design -load orig
+simplemap
+
+#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_
+select -assert-count 1 t:$_DFFE_PN0P_
+select -assert-count 1 t:$_DFFE_PN1P_
+select -assert-count 2 t:$_DFFSRE_PNNP_
+select -assert-count 1 t:$_DLATCH_PP0_
+select -assert-count 1 t:$_DLATCH_PN1_
+select -assert-count 2 t:$_DLATCHSR_PNP_
+select -assert-count 1 t:$_DLATCH_P_
+select -assert-count 1 t:$_DLATCH_N_
+select -assert-count 2 t:$_SR_PN_
+select -assert-none t:$_DFF_PP0_ t:$_DFF_PP1_ t:$_DFFSR_PPP_ t:$_DFFE_PN0P_ t:$_DFFE_PN1P_ t:$_DFFSRE_PNNP_ t:$_DLATCH_PP0_ t:$_DLATCH_PN1_ t:$_DLATCHSR_PNP_ t:$_NOT_ t:$_DLATCH_N_ t:$_DLATCH_P_ t:$_SR_PN_ %% %n t:* %i
+
+design -reset
+
+
+
+### Never-active CLR removal.
+
+read_verilog -icells <<EOT
+
+module top(...);
+
+input CLK;
+input [5:0] D;
+output [23:0] Q;
+input CLR;
+input SET;
+input EN;
+
+$dffsr #(.CLK_POLARITY(1'b1), .SET_POLARITY(1'b1), .CLR_POLARITY(1'b1), .WIDTH(6)) ff0 (.CLK(CLK), .CLR(6'h00), .SET({6{SET}}), .D(D), .Q(Q[5:0]));
+$dffsre #(.CLK_POLARITY(1'b1), .SET_POLARITY(1'b0), .CLR_POLARITY(1'b0), .EN_POLARITY(1'b1), .WIDTH(6)) ff1 (.CLK(CLK), .EN(EN), .D(D), .CLR(6'h3f), .SET({6{SET}}), .Q(Q[11:6]));
+$dlatchsr #(.SET_POLARITY(1'b0), .CLR_POLARITY(1'b1), .EN_POLARITY(1'b1), .WIDTH(6)) ff2 (.EN(EN), .D(D), .CLR(6'h00), .SET({6{SET}}), .Q(Q[17:12]));
+$sr #(.SET_POLARITY(1'b1), .CLR_POLARITY(1'b0), .WIDTH(6)) ff3 (.CLR(6'h3f), .SET({6{SET}}), .Q(Q[23:18]));
+
+endmodule
+
+EOT
+
+design -save orig
+
+equiv_opt -undef -assert -multiclock opt_dff -keepdc
+design -load postopt
+select -assert-count 0 t:$dffsr
+select -assert-count 0 t:$dffsre
+select -assert-count 0 t:$dlatchsr
+select -assert-count 0 t:$sr
+select -assert-count 1 t:$adff
+select -assert-count 1 t:$adffe
+select -assert-count 1 t:$adlatch
+select -assert-count 1 t:$dlatch
+
+design -reset
+
+
+
+### Never-active CLR removal (not applicable).
+
+read_verilog -icells <<EOT
+
+module top(...);
+
+input CLK;
+input [5:0] D;
+output [23:0] Q;
+input CLR;
+input SET;
+input ALT;
+input EN;
+
+$dffsr #(.CLK_POLARITY(1'b1), .SET_POLARITY(1'b1), .CLR_POLARITY(1'b1), .WIDTH(6)) ff0 (.CLK(CLK), .CLR(6'h00), .SET({{5{SET}}, ALT}), .D(D), .Q(Q[5:0]));
+$dffsre #(.CLK_POLARITY(1'b1), .SET_POLARITY(1'b0), .CLR_POLARITY(1'b0), .EN_POLARITY(1'b1), .WIDTH(6)) ff1 (.CLK(CLK), .EN(EN), .D(D), .CLR(6'h3f), .SET({{5{SET}}, ALT}), .Q(Q[11:6]));
+$dlatchsr #(.SET_POLARITY(1'b0), .CLR_POLARITY(1'b1), .EN_POLARITY(1'b1), .WIDTH(6)) ff2 (.EN(EN), .D(D), .CLR(6'h00), .SET({{5{SET}}, ALT}), .Q(Q[17:12]));
+$sr #(.SET_POLARITY(1'b1), .CLR_POLARITY(1'b0), .WIDTH(6)) ff3 (.CLR(6'h3f), .SET({{5{SET}}, ALT}), .Q(Q[23:18]));
+
+endmodule
+
+EOT
+
+design -save orig
+
+equiv_opt -undef -assert -multiclock opt_dff -keepdc
+design -load postopt
+select -assert-count 1 t:$dffsr
+select -assert-count 1 t:$dffsre
+select -assert-count 1 t:$dlatchsr
+select -assert-count 1 t:$sr
+select -assert-count 0 t:$adff
+select -assert-count 0 t:$adffe
+select -assert-count 0 t:$adlatch
+select -assert-count 0 t:$dlatch
+
+design -load orig
+simplemap
+
+equiv_opt -undef -assert -multiclock opt_dff -keepdc
+design -load postopt
+select -assert-count 0 t:$_DFFSR_*
+select -assert-count 0 t:$_DFFSRE_*
+select -assert-count 0 t:$_DLATCHSR_*
+select -assert-count 0 t:$_SR_*
+select -assert-count 6 t:$_DFF_PP1_
+select -assert-count 6 t:$_DFFE_PN1P_
+select -assert-count 6 t:$_DLATCH_PN1_
+select -assert-count 6 t:$_DLATCH_P_
+
+design -reset
+
+
+
+### Never-active SET removal.
+
+read_verilog -icells <<EOT
+
+module top(...);
+
+input CLK;
+input [5:0] D;
+output [23:0] Q;
+input CLR;
+input SET;
+input EN;
+
+$dffsr #(.CLK_POLARITY(1'b1), .SET_POLARITY(1'b1), .CLR_POLARITY(1'b1), .WIDTH(6)) ff0 (.CLK(CLK), .CLR({6{CLR}}), .SET(6'h00), .D(D), .Q(Q[5:0]));
+$dffsre #(.CLK_POLARITY(1'b1), .SET_POLARITY(1'b0), .CLR_POLARITY(1'b0), .EN_POLARITY(1'b1), .WIDTH(6)) ff1 (.CLK(CLK), .EN(EN), .D(D), .CLR({6{CLR}}), .SET(6'h3f), .Q(Q[11:6]));
+$dlatchsr #(.SET_POLARITY(1'b0), .CLR_POLARITY(1'b1), .EN_POLARITY(1'b1), .WIDTH(6)) ff2 (.EN(EN), .D(D), .CLR({6{CLR}}), .SET(6'h3f), .Q(Q[17:12]));
+$sr #(.SET_POLARITY(1'b1), .CLR_POLARITY(1'b0), .WIDTH(6)) ff3 (.CLR({6{CLR}}), .SET(6'h00), .Q(Q[23:18]));
+
+endmodule
+
+EOT
+
+design -save orig
+
+equiv_opt -undef -assert -multiclock opt_dff -keepdc
+design -load postopt
+select -assert-count 0 t:$dffsr
+select -assert-count 0 t:$dffsre
+select -assert-count 0 t:$dlatchsr
+select -assert-count 0 t:$sr
+select -assert-count 1 t:$adff
+select -assert-count 1 t:$adffe
+select -assert-count 1 t:$adlatch
+select -assert-count 1 t:$dlatch
+
+design -reset
+
+
+
+### Never-active CLR removal (not applicable).
+
+read_verilog -icells <<EOT
+
+module top(...);
+
+input CLK;
+input [5:0] D;
+output [23:0] Q;
+input CLR;
+input SET;
+input ALT;
+input EN;
+
+$dffsr #(.CLK_POLARITY(1'b1), .SET_POLARITY(1'b1), .CLR_POLARITY(1'b1), .WIDTH(6)) ff0 (.CLK(CLK), .CLR({{5{CLR}}, ALT}), .SET(6'h00), .D(D), .Q(Q[5:0]));
+$dffsre #(.CLK_POLARITY(1'b1), .SET_POLARITY(1'b0), .CLR_POLARITY(1'b0), .EN_POLARITY(1'b1), .WIDTH(6)) ff1 (.CLK(CLK), .EN(EN), .D(D), .CLR({{5{CLR}}, ALT}), .SET(6'h3f), .Q(Q[11:6]));
+$dlatchsr #(.SET_POLARITY(1'b0), .CLR_POLARITY(1'b1), .EN_POLARITY(1'b1), .WIDTH(6)) ff2 (.EN(EN), .D(D), .CLR({{5{CLR}}, ALT}), .SET(6'h3f), .Q(Q[17:12]));
+$sr #(.SET_POLARITY(1'b1), .CLR_POLARITY(1'b0), .WIDTH(6)) ff3 (.CLR({{5{CLR}}, ALT}), .SET(6'h00), .Q(Q[23:18]));
+
+endmodule
+
+EOT
+
+design -save orig
+
+equiv_opt -undef -assert -multiclock opt_dff -keepdc
+design -load postopt
+select -assert-count 1 t:$dffsr
+select -assert-count 1 t:$dffsre
+select -assert-count 1 t:$dlatchsr
+select -assert-count 1 t:$sr
+select -assert-count 0 t:$adff
+select -assert-count 0 t:$adffe
+select -assert-count 0 t:$adlatch
+select -assert-count 0 t:$dlatch
+
+design -load orig
+simplemap
+
+equiv_opt -undef -assert -multiclock opt_dff -keepdc
+design -load postopt
+select -assert-count 0 t:$_DFFSR_*
+select -assert-count 0 t:$_DFFSRE_*
+select -assert-count 0 t:$_DLATCHSR_*
+select -assert-count 0 t:$_SR_*
+select -assert-count 6 t:$_DFF_PP0_
+select -assert-count 6 t:$_DFFE_PN0P_
+select -assert-count 6 t:$_DLATCH_PP0_
+select -assert-count 6 t:$_DLATCH_N_
+
+design -reset
+
+
+
+### SET/CLR merge into ARST.
+
+read_verilog -icells <<EOT
+
+module top(...);
+
+input CLK;
+input [5:0] D;
+output [23:0] Q;
+input ARST;
+input EN;
+
+$dffsr #(.CLK_POLARITY(1'b1), .SET_POLARITY(1'b1), .CLR_POLARITY(1'b1), .WIDTH(6)) ff0 (.CLK(CLK), .CLR({ARST, 5'h00}), .SET({1'b0, {5{ARST}}}), .D(D), .Q(Q[5:0]));
+$dffsre #(.CLK_POLARITY(1'b1), .SET_POLARITY(1'b0), .CLR_POLARITY(1'b0), .EN_POLARITY(1'b1), .WIDTH(6)) ff1 (.CLK(CLK), .EN(EN), .D(D), .CLR({ARST, 5'h1f}), .SET({1'b1, {5{ARST}}}), .Q(Q[11:6]));
+$dlatchsr #(.SET_POLARITY(1'b0), .CLR_POLARITY(1'b1), .EN_POLARITY(1'b1), .WIDTH(6)) ff2 (.EN(EN), .D(D), .CLR({ARST, 5'h00}), .SET({1'b1, {5{ARST}}}), .Q(Q[17:12]));
+$sr #(.SET_POLARITY(1'b1), .CLR_POLARITY(1'b0), .WIDTH(6)) ff3 (.CLR({ARST, 5'h1f}), .SET({1'b0, {5{ARST}}}), .Q(Q[23:18]));
+
+endmodule
+
+EOT
+
+design -save orig
+
+equiv_opt -undef -assert -multiclock opt_dff -keepdc
+design -load postopt
+select -assert-count 0 t:$dffsr
+select -assert-count 0 t:$dffsre
+select -assert-count 1 t:$dlatchsr
+select -assert-count 1 t:$sr
+select -assert-count 1 t:$adff
+select -assert-count 1 t:$adff r:ARST_VALUE=6'h1f %i
+select -assert-count 1 t:$adffe
+select -assert-count 1 t:$adffe r:ARST_VALUE=6'h1f %i
+select -assert-count 0 t:$adlatch
+select -assert-count 0 t:$dlatch
diff --git a/tests/opt/opt_dff_srst.ys b/tests/opt/opt_dff_srst.ys
new file mode 100644
index 000000000..4a77de0b8
--- /dev/null
+++ b/tests/opt/opt_dff_srst.ys
@@ -0,0 +1,113 @@
+### Always-active SRST removal.
+
+read_verilog -icells <<EOT
+
+module top(...);
+
+input CLK;
+input [1:0] D;
+(* init=12'h555 *)
+output [11:0] Q;
+input SRST;
+input EN;
+
+$sdff #(.CLK_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_VALUE(2'h2), .WIDTH(2)) ff0 (.CLK(CLK), .SRST(1'b1), .D(D), .Q(Q[1:0]));
+$sdffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .SRST_POLARITY(1'b0), .SRST_VALUE(2'h2), .WIDTH(2)) ff1 (.CLK(CLK), .SRST(1'b0), .EN(EN), .D(D), .Q(Q[3:2]));
+$sdffce #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .SRST_POLARITY(1'b0), .SRST_VALUE(2'h2), .WIDTH(2)) ff2 (.CLK(CLK), .SRST(1'b0), .EN(EN), .D(D), .Q(Q[5:4]));
+$sdff #(.CLK_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_VALUE(2'h2), .WIDTH(2)) ff3 (.CLK(CLK), .SRST(1'bx), .D(D), .Q(Q[7:6]));
+$sdffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .SRST_POLARITY(1'b0), .SRST_VALUE(2'h2), .WIDTH(2)) ff4 (.CLK(CLK), .SRST(1'bx), .EN(EN), .D(D), .Q(Q[9:8]));
+$sdffce #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .SRST_POLARITY(1'b0), .SRST_VALUE(2'h2), .WIDTH(2)) ff5 (.CLK(CLK), .SRST(1'bx), .EN(EN), .D(D), .Q(Q[11:10]));
+
+
+endmodule
+
+EOT
+
+design -save orig
+
+equiv_opt -undef -assert -multiclock opt_dff
+design -load postopt
+select -assert-count 0 t:$sdff
+select -assert-count 0 t:$sdffe
+select -assert-count 0 t:$sdffce
+select -assert-count 4 t:$dff
+select -assert-count 2 t:$dffe
+
+design -load orig
+
+equiv_opt -undef -assert -multiclock opt_dff -keepdc
+design -load postopt
+select -assert-count 1 t:$sdff
+select -assert-count 1 t:$sdffe
+select -assert-count 1 t:$sdffce
+select -assert-count 2 t:$dff
+select -assert-count 1 t:$dffe
+
+design -load orig
+simplemap
+
+equiv_opt -undef -assert -multiclock opt_dff
+design -load postopt
+select -assert-none t:$_SDFF_???_
+select -assert-none t:$_SDFFE_????_
+select -assert-none t:$_SDFFCE_????_
+select -assert-count 8 t:$_DFF_?_
+select -assert-count 4 t:$_DFFE_??_
+
+design -load orig
+simplemap
+
+equiv_opt -undef -assert -multiclock opt_dff -keepdc
+design -load postopt
+select -assert-count 2 t:$_SDFF_???_
+select -assert-count 2 t:$_SDFFE_????_
+select -assert-count 2 t:$_SDFFCE_????_
+select -assert-count 4 t:$_DFF_?_
+select -assert-count 2 t:$_DFFE_??_
+
+design -reset
+
+
+### Never-active SRST removal.
+
+read_verilog -icells <<EOT
+
+module top(...);
+
+input CLK;
+input [1:0] D;
+output [5:0] Q;
+input SRST;
+input EN;
+
+$sdff #(.CLK_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_VALUE(2'h2), .WIDTH(2)) ff0 (.CLK(CLK), .SRST(1'b0), .D(D), .Q(Q[1:0]));
+$sdffe #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .SRST_POLARITY(1'b0), .SRST_VALUE(2'h2), .WIDTH(2)) ff1 (.CLK(CLK), .SRST(1'b1), .EN(EN), .D(D), .Q(Q[3:2]));
+$sdffce #(.CLK_POLARITY(1'b1), .EN_POLARITY(1'b1), .SRST_POLARITY(1'b0), .SRST_VALUE(2'h2), .WIDTH(2)) ff2 (.CLK(CLK), .SRST(1'b1), .EN(EN), .D(D), .Q(Q[5:4]));
+
+endmodule
+
+EOT
+
+design -save orig
+
+equiv_opt -undef -assert -multiclock opt_dff
+design -load postopt
+select -assert-none t:$sdff
+select -assert-none t:$sdffe
+select -assert-none t:$sdffce
+select -assert-count 1 t:$dff
+select -assert-count 2 t:$dffe
+
+design -load orig
+simplemap
+
+equiv_opt -undef -assert -multiclock opt_dff
+design -load postopt
+select -assert-none t:$_SDFF_???_
+select -assert-none t:$_SDFFE_????_
+select -assert-none t:$_SDFFCE_????_
+select -assert-count 2 t:$_DFF_P_
+select -assert-count 4 t:$_DFFE_PP_
+
+design -reset
+
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/opt/opt_rmdff.ys b/tests/opt/opt_rmdff.ys
index 7e11bc73f..998414597 100644
--- a/tests/opt/opt_rmdff.ys
+++ b/tests/opt/opt_rmdff.ys
@@ -4,7 +4,7 @@ design -stash gold
read_verilog -icells opt_rmdff.v
proc
-opt_rmdff
+opt_dff
select -assert-count 0 c:remove*
select -assert-min 7 c:keep*
@@ -23,7 +23,6 @@ connect -port remove6 EN 1'b1
connect -port remove15 E 1'b1
cd ..
-dff2dffe -unmap
clk2fflogic
opt_clean
diff --git a/tests/opt/opt_rmdff_sat.ys b/tests/opt/opt_rmdff_sat.ys
index 1c3dd9c05..231c43ecb 100644
--- a/tests/opt/opt_rmdff_sat.ys
+++ b/tests/opt/opt_rmdff_sat.ys
@@ -1,5 +1,5 @@
read_verilog opt_rmdff_sat.v
prep -flatten
-opt_rmdff -sat
-synth
+opt_dff -sat -nosdff
+simplemap
select -assert-count 5 t:$_DFF_P_
diff --git a/tests/opt/opt_share_bug2334.ys b/tests/opt/opt_share_bug2334.ys
new file mode 100644
index 000000000..004d98349
--- /dev/null
+++ b/tests/opt/opt_share_bug2334.ys
@@ -0,0 +1,13 @@
+read_verilog <<EOT
+
+module t(input [3:0] A, input [3:0] B, input [3:0] C, input S, output [3:0] Y);
+
+wire [3:0] t = A + C;
+
+assign Y = S ? A + B : {4{t[0]}};
+
+endmodule
+
+EOT
+
+equiv_opt -assert opt_share
diff --git a/tests/opt/opt_share_bug2335.ys b/tests/opt/opt_share_bug2335.ys
new file mode 100644
index 000000000..0846a9ec3
--- /dev/null
+++ b/tests/opt/opt_share_bug2335.ys
@@ -0,0 +1,27 @@
+read_verilog <<EOT
+
+module top(...);
+
+input [3:0] A, B, C;
+input S;
+input [1:0] T;
+output [3:0] X;
+output reg [3:0] Y;
+
+wire [3:0] D = A + B;
+
+assign X = S ? D : A + C;
+always @* begin
+ case(T)
+ 2'b01: Y <= A;
+ 2'b10: Y <= B;
+ default: Y <= D;
+ endcase
+end
+
+endmodule
+
+EOT
+
+proc
+equiv_opt -assert opt_share
diff --git a/tests/opt/opt_share_bug2336.ys b/tests/opt/opt_share_bug2336.ys
new file mode 100644
index 000000000..cd472ef46
--- /dev/null
+++ b/tests/opt/opt_share_bug2336.ys
@@ -0,0 +1,14 @@
+read_verilog <<EOT
+
+module top(input [3:0] A, B, C, input S, output [2:0] O);
+
+wire [3:0] tb = A + B;
+wire [3:0] tc = A + C;
+
+assign O = S ? tb[3:1] : tc[3:1];
+
+endmodule
+
+EOT
+
+equiv_opt -assert opt_share
diff --git a/tests/opt/opt_share_bug2538.ys b/tests/opt/opt_share_bug2538.ys
new file mode 100644
index 000000000..7261c6695
--- /dev/null
+++ b/tests/opt/opt_share_bug2538.ys
@@ -0,0 +1,20 @@
+read_verilog <<EOT
+
+module top(...);
+
+input [3:0] A;
+input S;
+output [1:0] Y;
+
+wire [3:0] A1 = A + 1;
+wire [3:0] A2 = A + 2;
+assign Y = S ? A1[3:2] : A2[3:2];
+
+endmodule
+
+EOT
+
+proc
+alumacc
+equiv_opt -assert opt_share
+
diff --git a/tests/opt/run-test.sh b/tests/opt/run-test.sh
index 44ce7e674..2007cd6e4 100755
--- a/tests/opt/run-test.sh
+++ b/tests/opt/run-test.sh
@@ -1,6 +1,4 @@
#!/bin/bash
-set -e
-for x in *.ys; do
- echo "Running $x.."
- ../../yosys -ql ${x%.ys}.log $x
-done
+set -eu
+source ../gen-tests-makefile.sh
+run_tests --yosys-scripts
diff --git a/tests/opt_share/run-test.sh b/tests/opt_share/run-test.sh
index e01552646..e0008a259 100755
--- a/tests/opt_share/run-test.sh
+++ b/tests/opt_share/run-test.sh
@@ -22,12 +22,23 @@ mkdir -p temp
echo "generating tests.."
python3 generate.py -c $count $seed
+{
+ echo ".PHONY: all"
+ echo "all:"
+
+ for i in $( ls temp/*.ys | sed 's,[^0-9],,g; s,^0*\(.\),\1,g;' ); do
+ idx=$( printf "%05d" $i )
+ echo ".PHONY: test-$idx"
+ echo "all: test-$idx"
+ echo "test-$idx:"
+ printf "\t@%s\n" \
+ "echo -n [$i]" \
+ "../../yosys -ql temp/uut_${idx}.log temp/uut_${idx}.ys"
+ done
+} > temp/makefile
+
echo "running tests.."
-for i in $( ls temp/*.ys | sed 's,[^0-9],,g; s,^0*\(.\),\1,g;' ); do
- echo -n "[$i]"
- idx=$( printf "%05d" $i )
- ../../yosys -ql temp/uut_${idx}.log temp/uut_${idx}.ys
-done
+${MAKE:-make} -f temp/makefile
echo
failed_share=$( echo $( gawk '/^#job#/ { j=$2; db[j]=0; } /^Removing [246] cells/ { delete db[j]; } END { for (j in db) print(j); }' temp/all_share_log.txt ) )
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 397b4a762..664425d73 100644
--- a/tests/sat/.gitignore
+++ b/tests/sat/.gitignore
@@ -1 +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/bug2595.ys b/tests/sat/bug2595.ys
new file mode 100644
index 000000000..f668fd747
--- /dev/null
+++ b/tests/sat/bug2595.ys
@@ -0,0 +1,18 @@
+read_ilang <<EOT
+module \top
+ wire input 3 \A
+ wire width 2 input 2 \B
+ wire width 2 input 1 \S
+ wire \Y
+ cell $pmux \my_pmux
+ parameter signed \S_WIDTH 2
+ parameter signed \WIDTH 1
+ connect \A \A
+ connect \B \B
+ connect \S \S
+ connect \Y \Y
+ end
+end
+EOT
+
+assertpmux
diff --git a/tests/sat/dff.ys b/tests/sat/dff.ys
new file mode 100644
index 000000000..ba3625871
--- /dev/null
+++ b/tests/sat/dff.ys
@@ -0,0 +1,21 @@
+# Ensure all sync-only DFFs have usable SAT models.
+
+read_verilog -icells <<EOT
+
+module top(...);
+
+input C, D, R, E;
+output [4:0] Q;
+
+\$dff #(.WIDTH(1), .CLK_POLARITY(1'b1)) ff0 (.CLK(C), .D(D), .Q(Q[0]));
+\$dffe #(.WIDTH(1), .CLK_POLARITY(1'b1), .EN_POLARITY(1'b1)) ff1 (.CLK(C), .D(D), .EN(E), .Q(Q[1]));
+\$sdff #(.WIDTH(1), .CLK_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_VALUE(1'b0)) ff2 (.CLK(C), .D(D), .SRST(R), .Q(Q[2]));
+\$sdffe #(.WIDTH(1), .CLK_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_VALUE(1'b0), .EN_POLARITY(1'b1)) ff3 (.CLK(C), .D(D), .EN(E), .SRST(R), .Q(Q[3]));
+\$sdffce #(.WIDTH(1), .CLK_POLARITY(1'b1), .SRST_POLARITY(1'b1), .SRST_VALUE(1'b0), .EN_POLARITY(1'b1)) ff4 (.CLK(C), .D(D), .EN(E), .SRST(R), .Q(Q[4]));
+
+endmodule
+
+EOT
+
+# This ensures that 1) coarse cells have SAT models, 2) fine cells have SAT models, 3) they're equivalent
+equiv_opt -assert simplemap
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/run-test.sh b/tests/sat/run-test.sh
index 67e1beb23..74589dfeb 100755
--- a/tests/sat/run-test.sh
+++ b/tests/sat/run-test.sh
@@ -1,6 +1,4 @@
-#!/bin/bash
-set -e
-for x in *.ys; do
- echo "Running $x.."
- ../../yosys -ql ${x%.ys}.log $x
-done
+#!/usr/bin/env bash
+set -eu
+source ../gen-tests-makefile.sh
+run_tests --yosys-scripts
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/sat/sizebits.sv b/tests/sat/sizebits.sv
index d7ce2326e..87fa08f89 100644
--- a/tests/sat/sizebits.sv
+++ b/tests/sat/sizebits.sv
@@ -1,5 +1,6 @@
module functions01;
+wire t;
wire [5:2]x;
wire [3:0]y[2:7];
wire [3:0]z[7:2][2:9];
@@ -9,24 +10,84 @@ wire [3:0]z[7:2][2:9];
//wire [$size(y)-1:0]y_size;
//wire [$size(z)-1:0]z_size;
+assert property ($size(t) == 1);
assert property ($size(x) == 4);
assert property ($size({3{x}}) == 3*4);
assert property ($size(y) == 6);
assert property ($size(y, 1) == 6);
assert property ($size(y, (1+1)) == 4);
+// This is unsupported at the moment
+//assert property ($size(y[2], 1) == 4);
+//assert property ($size(y[2][1], 1) == 1);
assert property ($size(z) == 6);
assert property ($size(z, 1) == 6);
assert property ($size(z, 2) == 8);
assert property ($size(z, 3) == 4);
+// This is unsupported at the moment
+assert property ($size(z[3], 1) == 8);
+assert property ($size(z[3][3], 1) == 4);
+//assert property ($size(z[3][3][3], 1) == 1);
// This should trigger an error if enabled (it does).
//assert property ($size(z, 4) == 4);
//wire [$bits(x)-1:0]x_bits;
//wire [$bits({x, x})-1:0]xx_bits;
+assert property ($bits(t) == 1);
assert property ($bits(x) == 4);
assert property ($bits(y) == 4*6);
assert property ($bits(z) == 4*6*8);
+assert property ($high(x) == 5);
+assert property ($high(y) == 7);
+assert property ($high(y, 1) == 7);
+assert property ($high(y, (1+1)) == 3);
+
+assert property ($high(z) == 7);
+assert property ($high(z, 1) == 7);
+assert property ($high(z, 2) == 9);
+assert property ($high(z, 3) == 3);
+assert property ($high(z[3]) == 9);
+assert property ($high(z[3][3]) == 3);
+assert property ($high(z[3], 2) == 3);
+
+assert property ($low(x) == 2);
+assert property ($low(y) == 2);
+assert property ($low(y, 1) == 2);
+assert property ($low(y, (1+1)) == 0);
+
+assert property ($low(z) == 2);
+assert property ($low(z, 1) == 2);
+assert property ($low(z, 2) == 2);
+assert property ($low(z, 3) == 0);
+assert property ($low(z[3]) == 2);
+assert property ($low(z[3][3]) == 0);
+assert property ($low(z[3], 2) == 0);
+
+assert property ($left(x) == 5);
+assert property ($left(y) == 2);
+assert property ($left(y, 1) == 2);
+assert property ($left(y, (1+1)) == 3);
+
+assert property ($left(z) == 7);
+assert property ($left(z, 1) == 7);
+assert property ($left(z, 2) == 2);
+assert property ($left(z, 3) == 3);
+assert property ($left(z[3]) == 2);
+assert property ($left(z[3][3]) == 3);
+assert property ($left(z[3], 2) == 3);
+
+assert property ($right(x) == 2);
+assert property ($right(y) == 7);
+assert property ($right(y, 1) == 7);
+assert property ($right(y, (1+1)) == 0);
+
+assert property ($right(z) == 2);
+assert property ($right(z, 1) == 2);
+assert property ($right(z, 2) == 9);
+assert property ($right(z, 3) == 0);
+assert property ($right(z[3]) == 9);
+assert property ($right(z[3][3]) == 0);
+assert property ($right(z[3], 2) == 0);
endmodule
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
new file mode 100644
index 000000000..7e365eeb4
--- /dev/null
+++ b/tests/simple/const_branch_finish.v
@@ -0,0 +1,36 @@
+`define CONSTANT_CHECK \
+ if (WIDTH === 'bx) begin \
+ $display("FAIL"); \
+ $finish; \
+ end
+
+module case_branch_finish_top;
+ parameter WIDTH = 32;
+ integer j;
+ initial begin
+ `CONSTANT_CHECK
+ if (WIDTH == 32) begin : procedural_conditional_block
+ `CONSTANT_CHECK
+ end
+ case (WIDTH)
+ 32: `CONSTANT_CHECK
+ default: ;
+ endcase
+ for (j = 0; j < 2; j = j + 1) begin : procedural_loop_block
+ `CONSTANT_CHECK
+ end
+ end
+ generate
+ if (WIDTH == 32) begin : conditional_block
+ initial `CONSTANT_CHECK
+ end
+ case (WIDTH)
+ 32: initial `CONSTANT_CHECK
+ default: ;
+ endcase
+ genvar i;
+ for (i = 0; i < 2; i = i + 1) begin : loop_block
+ initial `CONSTANT_CHECK
+ end
+ endgenerate
+endmodule
diff --git a/tests/simple/const_fold_func.v b/tests/simple/const_fold_func.v
new file mode 100644
index 000000000..b3f476ce3
--- /dev/null
+++ b/tests/simple/const_fold_func.v
@@ -0,0 +1,61 @@
+module const_fold_func_top(
+ input wire [3:0] inp,
+ output wire [3:0] out1, out2, out3, out4, out5,
+ output reg [3:0] out6
+);
+ function automatic [3:0] flip;
+ input [3:0] inp;
+ flip = ~inp;
+ endfunction
+
+ function automatic [3:0] help;
+ input [3:0] inp;
+ help = flip(inp);
+ endfunction
+
+ // while loops are const-eval-only
+ function automatic [3:0] loop;
+ input [3:0] inp;
+ reg [3:0] val;
+ begin
+ val = inp;
+ loop = 1;
+ while (val != inp) begin
+ loop = loop * 2;
+ val = val + 1;
+ end
+ end
+ endfunction
+
+ // not const-eval-only, despite calling a const-eval-only function
+ function automatic [3:0] help_mul;
+ input [3:0] inp;
+ help_mul = inp * loop(2);
+ endfunction
+
+ // can be elaborated so long as exp is a constant
+ function automatic [3:0] pow_flip_a;
+ input [3:0] base, exp;
+ begin
+ pow_flip_a = 1;
+ if (exp > 0)
+ pow_flip_a = base * pow_flip_a(flip(base), exp - 1);
+ end
+ endfunction
+
+ function automatic [3:0] pow_flip_b;
+ input [3:0] base, exp;
+ begin
+ out6[exp] = base & 1;
+ pow_flip_b = 1;
+ if (exp > 0)
+ pow_flip_b = base * pow_flip_b(flip(base), exp - 1);
+ end
+ endfunction
+
+ assign out1 = flip(flip(inp));
+ assign out2 = help(flip(inp));
+ assign out3 = help_mul(inp);
+ assign out4 = pow_flip_a(flip(inp), 3);
+ assign out5 = pow_flip_b(2, 2);
+endmodule
diff --git a/tests/simple/const_func_shadow.v b/tests/simple/const_func_shadow.v
new file mode 100644
index 000000000..fb4f148f6
--- /dev/null
+++ b/tests/simple/const_func_shadow.v
@@ -0,0 +1,33 @@
+module const_func_shadow_top(w, x, y, z);
+ function [11:0] func;
+ input reg [2:0] x;
+ input reg [2:0] y;
+ begin
+ x = x * (y + 1);
+ begin : foo
+ reg [2:0] y;
+ y = x + 1;
+ begin : bar
+ reg [2:0] x;
+ x = y + 1;
+ begin : blah
+ reg [2:0] y;
+ y = x + 1;
+ func[2:0] = y;
+ end
+ func[5:3] = x;
+ end
+ func[8:6] = y;
+ end
+ func[11:9] = x;
+ end
+ endfunction
+ output wire [func(2, 3) - 1:0] w;
+ output wire [func(1, 3) - 1:0] x;
+ output wire [func(3, 1) - 1:0] y;
+ output wire [func(5, 2) - 1:0] z;
+ assign w = 1'sb1;
+ assign x = 1'sb1;
+ assign y = 1'sb1;
+ assign z = 1'sb1;
+endmodule
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
new file mode 100644
index 000000000..0ac7ca3bf
--- /dev/null
+++ b/tests/simple/func_block.v
@@ -0,0 +1,33 @@
+`default_nettype none
+
+module func_block_top(inp, out1, out2, out3);
+ input wire [31:0] inp;
+
+ function automatic [31:0] func1;
+ input [31:0] inp;
+ reg [31:0] idx;
+ for (idx = 0; idx < 32; idx = idx + 1) begin : blk
+ func1[idx] = (idx & 1'b1) ^ inp[idx];
+ end
+ endfunction
+
+ function automatic [31:0] func2;
+ input [31:0] inp;
+ reg [31:0] idx;
+ for (idx = 0; idx < 32; idx = idx + 1) begin : blk
+ func2[idx] = (idx & 1'b1) ^ inp[idx];
+ end
+ endfunction
+
+ function automatic [31:0] func3;
+ localparam A = 32 - 1;
+ parameter B = 1 - 0;
+ input [31:0] inp;
+ func3[A:B] = inp[A:B];
+ endfunction
+
+ output wire [31:0] out1, out2, out3;
+ assign out1 = func1(inp);
+ assign out2 = func2(inp);
+ assign out3 = func3(inp);
+endmodule
diff --git a/tests/simple/func_recurse.v b/tests/simple/func_recurse.v
new file mode 100644
index 000000000..02cfbcddf
--- /dev/null
+++ b/tests/simple/func_recurse.v
@@ -0,0 +1,25 @@
+module func_recurse_top(
+ input wire [3:0] inp,
+ output wire [3:0] out1, out2
+);
+ function automatic [3:0] pow_a;
+ input [3:0] base, exp;
+ begin
+ pow_a = 1;
+ if (exp > 0)
+ pow_a = base * pow_a(base, exp - 1);
+ end
+ endfunction
+
+ function automatic [3:0] pow_b;
+ input [3:0] base, exp;
+ begin
+ pow_b = 1;
+ if (exp > 0)
+ pow_b = base * pow_b(base, exp - 1);
+ end
+ endfunction
+
+ assign out1 = pow_a(inp, 3);
+ assign out2 = pow_b(2, 2);
+endmodule
diff --git a/tests/simple/func_width_scope.v b/tests/simple/func_width_scope.v
new file mode 100644
index 000000000..2f82988ae
--- /dev/null
+++ b/tests/simple/func_width_scope.v
@@ -0,0 +1,41 @@
+module func_width_scope_top(inp, out1, out2);
+ input wire signed inp;
+
+ localparam WIDTH_A = 5;
+ function automatic [WIDTH_A-1:0] func1;
+ input reg [WIDTH_A-1:0] inp;
+ func1 = ~inp;
+ endfunction
+ wire [func1(0)-1:0] xc;
+ assign xc = 1'sb1;
+ wire [WIDTH_A-1:0] xn;
+ assign xn = func1(inp);
+
+ generate
+ if (1) begin : blk
+ localparam WIDTH_A = 6;
+ function automatic [WIDTH_A-1:0] func2;
+ input reg [WIDTH_A-1:0] inp;
+ func2 = ~inp;
+ endfunction
+ wire [func2(0)-1:0] yc;
+ assign yc = 1'sb1;
+ wire [WIDTH_A-1:0] yn;
+ assign yn = func2(inp);
+
+ localparam WIDTH_B = 7;
+ function automatic [WIDTH_B-1:0] func3;
+ input reg [WIDTH_B-1:0] inp;
+ func3 = ~inp;
+ endfunction
+ wire [func3(0)-1:0] zc;
+ assign zc = 1'sb1;
+ wire [WIDTH_B-1:0] zn;
+ assign zn = func3(inp);
+ end
+ endgenerate
+
+ output wire [1023:0] out1, out2;
+ assign out1 = {xc, 1'b0, blk.yc, 1'b0, blk.zc};
+ assign out2 = {xn, 1'b0, blk.yn, 1'b0, blk.zn};
+endmodule
diff --git a/tests/simple/genblk_collide.v b/tests/simple/genblk_collide.v
new file mode 100644
index 000000000..118c0b008
--- /dev/null
+++ b/tests/simple/genblk_collide.v
@@ -0,0 +1,27 @@
+`default_nettype none
+
+module genblock_collide_top1;
+ generate
+ if (1) begin : foo
+ if (1) begin : bar
+ wire x;
+ end
+ assign bar.x = 1;
+ wire y;
+ end
+ endgenerate
+endmodule
+
+module genblock_collide_top2;
+ genvar i;
+ generate
+ if (1) begin : foo
+ wire x;
+ for (i = 0; i < 1; i = i + 1) begin : foo
+ if (1) begin : foo
+ assign x = 1;
+ end
+ end
+ end
+ endgenerate
+endmodule
diff --git a/tests/simple/genblk_dive.v b/tests/simple/genblk_dive.v
new file mode 100644
index 000000000..ca0c0d4a1
--- /dev/null
+++ b/tests/simple/genblk_dive.v
@@ -0,0 +1,21 @@
+`default_nettype none
+module genblk_dive_top(output wire x);
+ generate
+ if (1) begin : Z
+ if (1) begin : A
+ wire x;
+ if (1) begin : B
+ wire x;
+ if (1) begin : C
+ wire x;
+ assign B.x = 0;
+ wire z = A.B.C.x;
+ end
+ assign A.x = A.B.C.x;
+ end
+ assign B.C.x = B.x;
+ end
+ end
+ endgenerate
+ assign x = Z.A.x;
+endmodule
diff --git a/tests/simple/genblk_order.v b/tests/simple/genblk_order.v
new file mode 100644
index 000000000..c80c1ac1a
--- /dev/null
+++ b/tests/simple/genblk_order.v
@@ -0,0 +1,18 @@
+`default_nettype none
+module genblk_order_top(
+ output wire out1,
+ output wire out2
+);
+ generate
+ if (1) begin : outer
+ if (1) begin : foo
+ wire x = 0;
+ if (1) begin : foo
+ wire x = 1;
+ assign out1 = foo.x;
+ end
+ assign out2 = foo.x;
+ end
+ end
+ endgenerate
+endmodule
diff --git a/tests/simple/genblk_port_shadow.v b/tests/simple/genblk_port_shadow.v
new file mode 100644
index 000000000..c1348632c
--- /dev/null
+++ b/tests/simple/genblk_port_shadow.v
@@ -0,0 +1,10 @@
+module genblock_port_shadow_top(x);
+ generate
+ if (1) begin : blk
+ wire x;
+ assign x = 0;
+ end
+ endgenerate
+ output wire x;
+ assign x = blk.x;
+endmodule
diff --git a/tests/simple/generate.v b/tests/simple/generate.v
index 0e353ad9b..445c88ba8 100644
--- a/tests/simple/generate.v
+++ b/tests/simple/generate.v
@@ -159,3 +159,167 @@ generate
end
endgenerate
endmodule
+
+// ------------------------------------------
+
+module gen_test7;
+ reg [2:0] out1;
+ reg [2:0] out2;
+ wire [2:0] out3;
+ generate
+ if (1) begin : cond
+ reg [2:0] sub_out1;
+ reg [2:0] sub_out2;
+ wire [2:0] sub_out3;
+ initial begin : init
+ reg signed [31:0] x;
+ x = 2 ** 2;
+ out1 = x;
+ sub_out1 = x;
+ end
+ always @* begin : proc
+ reg signed [31:0] x;
+ x = 2 ** 1;
+ out2 = x;
+ sub_out2 = x;
+ end
+ genvar x;
+ for (x = 0; x < 3; x = x + 1) begin
+ assign out3[x] = 1;
+ assign sub_out3[x] = 1;
+ end
+ end
+ endgenerate
+
+// `define VERIFY
+`ifdef VERIFY
+ assert property (out1 == 4);
+ assert property (out2 == 2);
+ assert property (out3 == 7);
+ assert property (cond.sub_out1 == 4);
+ assert property (cond.sub_out2 == 2);
+ assert property (cond.sub_out3 == 7);
+`endif
+endmodule
+
+// ------------------------------------------
+
+module gen_test8;
+
+// `define VERIFY
+`ifdef VERIFY
+ `define ASSERT(expr) assert property (expr);
+`else
+ `define ASSERT(expr)
+`endif
+
+ wire [1:0] x = 2'b11;
+ generate
+ if (1) begin : A
+ wire [1:0] x;
+ if (1) begin : B
+ wire [1:0] x = 2'b00;
+ `ASSERT(x == 0)
+ `ASSERT(A.x == 2)
+ `ASSERT(A.C.x == 1)
+ `ASSERT(A.B.x == 0)
+ `ASSERT(gen_test8.x == 3)
+ `ASSERT(gen_test8.A.x == 2)
+ `ASSERT(gen_test8.A.C.x == 1)
+ `ASSERT(gen_test8.A.B.x == 0)
+ end
+ if (1) begin : C
+ wire [1:0] x = 2'b01;
+ `ASSERT(x == 1)
+ `ASSERT(A.x == 2)
+ `ASSERT(A.C.x == 1)
+ `ASSERT(A.B.x == 0)
+ `ASSERT(gen_test8.x == 3)
+ `ASSERT(gen_test8.A.x == 2)
+ `ASSERT(gen_test8.A.C.x == 1)
+ `ASSERT(gen_test8.A.B.x == 0)
+ end
+ assign x = B.x ^ 2'b11 ^ C.x;
+ `ASSERT(x == 2)
+ `ASSERT(A.x == 2)
+ `ASSERT(A.C.x == 1)
+ `ASSERT(A.B.x == 0)
+ `ASSERT(gen_test8.x == 3)
+ `ASSERT(gen_test8.A.x == 2)
+ `ASSERT(gen_test8.A.C.x == 1)
+ `ASSERT(gen_test8.A.B.x == 0)
+ end
+ endgenerate
+
+ `ASSERT(x == 3)
+ `ASSERT(A.x == 2)
+ `ASSERT(A.C.x == 1)
+ `ASSERT(A.B.x == 0)
+ `ASSERT(gen_test8.x == 3)
+ `ASSERT(gen_test8.A.x == 2)
+ `ASSERT(gen_test8.A.C.x == 1)
+ `ASSERT(gen_test8.A.B.x == 0)
+endmodule
+
+// ------------------------------------------
+
+module gen_test9;
+
+// `define VERIFY
+`ifdef VERIFY
+ `define ASSERT(expr) assert property (expr);
+`else
+ `define ASSERT(expr)
+`endif
+
+ wire [1:0] w = 2'b11;
+ generate
+ begin : A
+ wire [1:0] x;
+ begin : B
+ wire [1:0] y = 2'b00;
+ `ASSERT(w == 3)
+ `ASSERT(x == 2)
+ `ASSERT(y == 0)
+ `ASSERT(A.x == 2)
+ `ASSERT(A.C.z == 1)
+ `ASSERT(A.B.y == 0)
+ `ASSERT(gen_test9.w == 3)
+ `ASSERT(gen_test9.A.x == 2)
+ `ASSERT(gen_test9.A.C.z == 1)
+ `ASSERT(gen_test9.A.B.y == 0)
+ end
+ begin : C
+ wire [1:0] z = 2'b01;
+ `ASSERT(w == 3)
+ `ASSERT(x == 2)
+ `ASSERT(z == 1)
+ `ASSERT(A.x == 2)
+ `ASSERT(A.C.z == 1)
+ `ASSERT(A.B.y == 0)
+ `ASSERT(gen_test9.w == 3)
+ `ASSERT(gen_test9.A.x == 2)
+ `ASSERT(gen_test9.A.C.z == 1)
+ `ASSERT(gen_test9.A.B.y == 0)
+ end
+ assign x = B.y ^ 2'b11 ^ C.z;
+ `ASSERT(x == 2)
+ `ASSERT(A.x == 2)
+ `ASSERT(A.C.z == 1)
+ `ASSERT(A.B.y == 0)
+ `ASSERT(gen_test9.w == 3)
+ `ASSERT(gen_test9.A.x == 2)
+ `ASSERT(gen_test9.A.C.z == 1)
+ `ASSERT(gen_test9.A.B.y == 0)
+ end
+ endgenerate
+
+ `ASSERT(w == 3)
+ `ASSERT(A.x == 2)
+ `ASSERT(A.C.z == 1)
+ `ASSERT(A.B.y == 0)
+ `ASSERT(gen_test9.w == 3)
+ `ASSERT(gen_test9.A.x == 2)
+ `ASSERT(gen_test9.A.C.z == 1)
+ `ASSERT(gen_test9.A.B.y == 0)
+endmodule
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
new file mode 100644
index 000000000..f1358185c
--- /dev/null
+++ b/tests/simple/ifdef_1.v
@@ -0,0 +1,88 @@
+module ifdef_1_top(o1, o2, o3, o4);
+
+`define FAIL input wire not_a_port;
+
+`ifdef COND_1
+ `FAIL
+`elsif COND_2
+ `FAIL
+`elsif COND_3
+ `FAIL
+`elsif COND_4
+ `FAIL
+`else
+
+ `define COND_4
+ output wire o4;
+
+ `ifdef COND_1
+ `FAIL
+ `elsif COND_2
+ `FAIL
+ `elsif COND_3
+ `FAIL
+ `elsif COND_4
+
+ `define COND_3
+ output wire o3;
+
+ `ifdef COND_1
+ `FAIL
+ `elsif COND_2
+ `FAIL
+ `elsif COND_3
+
+ `define COND_2
+ output wire o2;
+
+ `ifdef COND_1
+ `FAIL
+ `elsif COND_2
+
+ `define COND_1
+ output wire o1;
+
+ `ifdef COND_1
+
+ `ifdef COND_1
+ `elsif COND_2
+ `FAIL
+ `elsif COND_3
+ `FAIL
+ `elsif COND_4
+ `FAIL
+ `else
+ `FAIL
+ `endif
+
+ `elsif COND_2
+ `FAIL
+ `elsif COND_3
+ `FAIL
+ `elsif COND_4
+ `FAIL
+ `else
+ `FAIL
+ `endif
+
+ `elsif COND_3
+ `FAIL
+ `elsif COND_4
+ `FAIL
+ `else
+ `FAIL
+ `endif
+
+ `elsif COND_4
+ `FAIL
+ `else
+ `FAIL
+ `endif
+
+ `else
+ `FAIL
+ `endif
+
+`endif
+
+endmodule
diff --git a/tests/simple/ifdef_2.v b/tests/simple/ifdef_2.v
new file mode 100644
index 000000000..9fae7570d
--- /dev/null
+++ b/tests/simple/ifdef_2.v
@@ -0,0 +1,21 @@
+module ifdef_2_top(o1, o2, o3);
+
+output wire o1;
+
+`define COND_1
+`define COND_2
+`define COND_3
+
+`ifdef COND_1
+ output wire o2;
+`elsif COND_2
+ input wire dne1;
+`elsif COND_3
+ input wire dne2;
+`else
+ input wire dne3;
+`endif
+
+output wire o3;
+
+endmodule
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
new file mode 100644
index 000000000..42860e218
--- /dev/null
+++ b/tests/simple/local_loop_var.sv
@@ -0,0 +1,11 @@
+module local_loop_top(out);
+ output integer out;
+ initial begin
+ integer i;
+ for (i = 0; i < 5; i = i + 1)
+ if (i == 0)
+ out = 1;
+ else
+ out += 2 ** i;
+ end
+endmodule
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
new file mode 100644
index 000000000..b75a15ab0
--- /dev/null
+++ b/tests/simple/loop_var_shadow.v
@@ -0,0 +1,15 @@
+module loop_var_shadow_top(out);
+ genvar i;
+ generate
+ for (i = 0; i < 2; i = i + 1) begin : loop
+ localparam j = i + 1;
+ if (1) begin : blk
+ localparam i = j + 1;
+ wire [i:0] x;
+ assign x = 1'sb1;
+ end
+ end
+ endgenerate
+ output wire [63:0] out;
+ assign out = {loop[0].blk.x, loop[1].blk.x};
+endmodule
diff --git a/tests/simple/macro_arg_spaces.sv b/tests/simple/macro_arg_spaces.sv
new file mode 100644
index 000000000..5fc9e2881
--- /dev/null
+++ b/tests/simple/macro_arg_spaces.sv
@@ -0,0 +1,28 @@
+module macro_arg_spaces_top(
+ input wire [31:0] i,
+ output wire [31:0] x, y, z
+);
+
+`define BAR(a) a
+`define FOO(a = function automatic [31:0] f) a
+
+`BAR(function automatic [31:0] a);
+ input [31:0] i;
+ a = i * 2;
+endfunction
+
+`FOO();
+ input [31:0] i;
+ f = i * 3;
+endfunction
+
+`FOO(function automatic [31:0] b);
+ input [31:0] i;
+ b = i * 5;
+endfunction
+
+assign x = a(i);
+assign y = f(i);
+assign z = b(i);
+
+endmodule
diff --git a/tests/simple/macro_arg_surrounding_spaces.v b/tests/simple/macro_arg_surrounding_spaces.v
new file mode 100644
index 000000000..e0239c08b
--- /dev/null
+++ b/tests/simple/macro_arg_surrounding_spaces.v
@@ -0,0 +1,20 @@
+module macr_arg_surrounding_spaces_top(
+ IDENT_V_,
+ IDENT_W_,
+ IDENT_X_,
+ IDENT_Y_,
+ IDENT_Z_,
+ IDENT_A_,
+ IDENT_B_,
+ IDENT_C_
+);
+ `define MACRO(dummy, x) IDENT_``x``_
+ output wire IDENT_V_;
+ output wire `MACRO(_,W);
+ output wire `MACRO(_, X);
+ output wire `MACRO(_,Y );
+ output wire `MACRO(_, Z );
+ output wire `MACRO(_, A);
+ output wire `MACRO(_,B );
+ output wire `MACRO(_, C );
+endmodule
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
new file mode 100644
index 000000000..b98b7c8ce
--- /dev/null
+++ b/tests/simple/named_genblk.v
@@ -0,0 +1,27 @@
+`default_nettype none
+module named_genblk_top;
+ generate
+ if (1) begin
+ wire t;
+ begin : foo
+ wire x;
+ end
+ wire u;
+ end
+ begin : bar
+ wire x;
+ wire y;
+ begin : baz
+ wire x;
+ wire z;
+ end
+ end
+ endgenerate
+ assign genblk1.t = 1;
+ assign genblk1.foo.x = 1;
+ assign genblk1.u = 1;
+ assign bar.x = 1;
+ assign bar.y = 1;
+ assign bar.baz.x = 1;
+ assign bar.baz.z = 1;
+endmodule
diff --git a/tests/simple/nested_genblk_resolve.v b/tests/simple/nested_genblk_resolve.v
new file mode 100644
index 000000000..70bbc611b
--- /dev/null
+++ b/tests/simple/nested_genblk_resolve.v
@@ -0,0 +1,14 @@
+`default_nettype none
+module nested_genblk_resolve_top;
+ generate
+ if (1) begin
+ wire x;
+ genvar i;
+ for (i = 0; i < 1; i = i + 1) begin
+ if (1) begin
+ assign x = 1;
+ end
+ end
+ end
+ endgenerate
+endmodule
diff --git a/tests/simple/run-test.sh b/tests/simple/run-test.sh
index f20fd0d30..47bcfd6da 100755
--- a/tests/simple/run-test.sh
+++ b/tests/simple/run-test.sh
@@ -17,5 +17,4 @@ if ! command -v iverilog > /dev/null ; then
exit 1
fi
-shopt -s nullglob
exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.{sv,v}
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
new file mode 100644
index 000000000..cb7b419ac
--- /dev/null
+++ b/tests/simple/string_format.v
@@ -0,0 +1,7 @@
+module string_format_top;
+ parameter STR = "something interesting";
+ initial begin
+ $display("A: %s", STR);
+ $display("B: %0s", STR);
+ end
+endmodule
diff --git a/tests/simple/unnamed_block_decl.sv b/tests/simple/unnamed_block_decl.sv
new file mode 100644
index 000000000..e78c577da
--- /dev/null
+++ b/tests/simple/unnamed_block_decl.sv
@@ -0,0 +1,17 @@
+module unnamed_block_decl(z);
+ output integer z;
+ initial begin
+ integer x;
+ x = 1;
+ begin
+ integer y;
+ y = x + 1;
+ begin
+ integer z;
+ z = y + 1;
+ y = z + 1;
+ end
+ z = y + 1;
+ end
+ end
+endmodule
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/.gitignore b/tests/simple_abc9/.gitignore
index 2355aea29..fda60e577 100644
--- a/tests/simple_abc9/.gitignore
+++ b/tests/simple_abc9/.gitignore
@@ -2,3 +2,4 @@
*.sv
*.log
*.out
+*.bak
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 650e42fca..4a5bf01a3 100755
--- a/tests/simple_abc9/run-test.sh
+++ b/tests/simple_abc9/run-test.sh
@@ -17,16 +17,38 @@ if ! command -v iverilog > /dev/null ; then
exit 1
fi
+for file in `ls *.v *.sv`; do
+ if [ ! -f "../simple/$file" -a "$file" != "abc9.v" ]; then
+ echo "Warning: $file is in simple_abc9/, but not in simple/"
+ backup="$file.bak"
+ if [ -f "$backup" ]; then
+ if cmp "$file" "$backup" > /dev/null; then
+ echo " => $backup already exists and matches; removing $file"
+ rm "$file"
+ else
+ echo " => $backup already exists but differs; leaving $file in place"
+ fi
+ else
+ echo " => moving $file to $backup"
+ mv -i "$file" "$backup"
+ fi
+ fi
+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/multirange_array.sv b/tests/svtypes/multirange_array.sv
new file mode 100644
index 000000000..be0d3dfc2
--- /dev/null
+++ b/tests/svtypes/multirange_array.sv
@@ -0,0 +1,16 @@
+// test for multirange arrays
+
+`define STRINGIFY(x) `"x`"
+`define STATIC_ASSERT(x) if(!(x)) $error({"assert failed: ", `STRINGIFY(x)})
+
+module top;
+
+ logic a [3];
+ logic b [3][5];
+ logic c [3][5][7];
+
+ `STATIC_ASSERT($bits(a) == 3);
+ `STATIC_ASSERT($bits(b) == 15);
+ `STATIC_ASSERT($bits(c) == 105);
+
+endmodule
diff --git a/tests/svtypes/multirange_subarray_access.ys b/tests/svtypes/multirange_subarray_access.ys
new file mode 100644
index 000000000..de57d1423
--- /dev/null
+++ b/tests/svtypes/multirange_subarray_access.ys
@@ -0,0 +1,12 @@
+logger -expect error "Insufficient number of array indices for a." 1
+read_verilog -sv <<EOT
+module foo;
+logic a [6:0][4:0][1:0];
+logic b [1:0];
+
+assign a[0][0][0] = 1'b0;
+assign a[0][0][1] = 1'b1;
+assign b = a[0][0];
+
+endmodule
+EOT
diff --git a/tests/svtypes/run-test.sh b/tests/svtypes/run-test.sh
index 09a30eed1..91ceae227 100755
--- a/tests/svtypes/run-test.sh
+++ b/tests/svtypes/run-test.sh
@@ -1,20 +1,4 @@
#!/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 x in *.sv; do
- if [ ! -f "${x%.sv}.ys" ]; then
- echo "all:: check-$x"
- echo "check-$x:"
- echo " @echo 'Checking $x..'"
- echo " @../../yosys -ql ${x%.sv}.log -p \"prep -top top; sat -verify -prove-asserts\" $x"
- fi
-done
-} > run-test.mk
-exec ${MAKE:-make} -f run-test.mk
+set -eu
+source ../gen-tests-makefile.sh
+run_tests --yosys-scripts --prove-sv
diff --git a/tests/svtypes/struct_array.sv b/tests/svtypes/struct_array.sv
index 022ad56c6..873f7befd 100644
--- a/tests/svtypes/struct_array.sv
+++ b/tests/svtypes/struct_array.sv
@@ -1,7 +1,7 @@
// test for array indexing in structures
module top;
-
+
struct packed {
bit [5:0] [7:0] a; // 6 element packed array of bytes
bit [15:0] b; // filler for non-zero offset
@@ -19,4 +19,24 @@ module top;
always_comb assert(s==64'h4200_0012_3400_FFFC);
+ struct packed {
+ bit [7:0] [7:0] a; // 8 element packed array of bytes
+ bit [15:0] b; // filler for non-zero offset
+ } s2;
+
+ initial begin
+ s2 = '0;
+
+ s2.a[2:1] = 16'h1234;
+ s2.a[5] = 8'h42;
+
+ s2.a[7] = '1;
+ s2.a[7][1:0] = '0;
+
+ s2.b = '1;
+ s2.b[1:0] = '0;
+ end
+
+ always_comb assert(s2==80'hFC00_4200_0012_3400_FFFC);
+
endmodule
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/svtypes/typedef_struct_port.sv b/tests/svtypes/typedef_struct_port.sv
new file mode 100644
index 000000000..ecc03bee8
--- /dev/null
+++ b/tests/svtypes/typedef_struct_port.sv
@@ -0,0 +1,111 @@
+package p;
+
+typedef struct packed {
+ byte a;
+ byte b;
+} p_t;
+
+typedef logic [31:0] l_t;
+
+endpackage
+
+module foo1(
+ input p::p_t p,
+ output p::p_t o
+);
+ assign o = p;
+endmodule
+
+module foo2(p, o);
+ input p::p_t p;
+ output p::p_t o;
+ assign o = p;
+endmodule
+
+module foo3(input p::l_t p, input p::l_t o);
+ assign o = p;
+endmodule
+
+module foo4(input logic [15:0] p, input logic [15:0] o);
+ assign o = p;
+endmodule
+
+module test_parser(a,b,c,d,e,f,g,h,i);
+input [7:0] a; // no explicit net declaration - net is unsigned
+input [7:0] b;
+input signed [7:0] c;
+input signed [7:0] d; // no explicit net declaration - net is signed
+output [7:0] e; // no explicit net declaration - net is unsigned
+output [7:0] f;
+output signed [7:0] g;
+output signed [7:0] h; // no explicit net declaration - net is signed
+output unsigned [7:0] i;
+wire signed [7:0] b; // port b inherits signed attribute from net decl.
+wire [7:0] c; // net c inherits signed attribute from port
+logic signed [7:0] f;// port f inherits signed attribute from logic decl.
+logic [7:0] g; // logic g inherits signed attribute from port
+
+ assign a = 8'b10001111;
+ assign b = 8'b10001111;
+ assign c = 8'b10001111;
+ assign d = 8'b10001111;
+ assign e = 8'b10001111;
+ assign f = 8'b10001111;
+ assign g = 8'b10001111;
+ assign h = 8'b10001111;
+ assign i = 8'b10001111;
+ always_comb begin
+ assert($unsigned(143) == a);
+ assert($signed(-113) == b);
+ assert($signed(-113) == c);
+ assert($signed(-113) == d);
+ assert($unsigned(143) == e);
+ assert($unsigned(143) == f);
+ assert($signed(-113) == g);
+ assert($signed(-113) == h);
+ assert($unsigned(143) == i);
+ end
+endmodule
+
+module top;
+ p::p_t ps;
+ assign ps.a = 8'hAA;
+ assign ps.b = 8'h55;
+ foo1 foo(.p(ps));
+
+ p::p_t body;
+ assign body.a = 8'hBB;
+ assign body.b = 8'h66;
+ foo2 foo_b(.p(body));
+
+ typedef p::l_t local_alias;
+
+ local_alias l_s;
+ assign l_s = 32'hAAAAAAAA;
+ foo3 foo_l(.p(l_s));
+
+ typedef logic [15:0] sl_t;
+
+ sl_t sl_s;
+ assign sl_s = 16'hBBBB;
+ foo4 foo_sl(.p(sl_s));
+
+ typedef sl_t local_alias_st;
+
+ local_alias_st lsl_s;
+ assign lsl_s = 16'hCCCC;
+ foo4 foo_lsl(.p(lsl_s));
+
+ const logic j = 1'b1;
+
+ always_comb begin
+ assert(8'hAA == ps.a);
+ assert(8'h55 == ps.b);
+ assert(8'hBB == body.a);
+ assert(8'h66 == body.b);
+ assert(32'hAAAAAAAA == l_s);
+ assert(16'hBBBB == sl_s);
+ assert(16'hCCCC == lsl_s);
+ assert(1'b1 == j);
+ end
+endmodule
diff --git a/tests/svtypes/typedef_struct_port.ys b/tests/svtypes/typedef_struct_port.ys
new file mode 100644
index 000000000..5b75c3105
--- /dev/null
+++ b/tests/svtypes/typedef_struct_port.ys
@@ -0,0 +1,6 @@
+read_verilog -sv typedef_struct_port.sv
+hierarchy; proc; opt
+select -module top
+sat -verify -seq 1 -tempinduct -prove-asserts -show-all
+select -module test_parser
+sat -verify -seq 1 -tempinduct -prove-asserts -show-all
diff --git a/tests/techmap/adff2dff.ys b/tests/techmap/adff2dff.ys
new file mode 100644
index 000000000..53f7d2f08
--- /dev/null
+++ b/tests/techmap/adff2dff.ys
@@ -0,0 +1,19 @@
+read_verilog -icells << EOT
+module top(...);
+
+input [1:0] D;
+input C, R;
+output [1:0] Q;
+
+always @(posedge C, posedge R)
+ if (R)
+ Q <= 0;
+ else
+ Q <= D;
+
+endmodule
+EOT
+
+proc
+
+equiv_opt -async2sync techmap -map +/adff2dff.v
diff --git a/tests/techmap/bug2183.ys b/tests/techmap/bug2183.ys
new file mode 100644
index 000000000..8dd09458e
--- /dev/null
+++ b/tests/techmap/bug2183.ys
@@ -0,0 +1,11 @@
+read_verilog <<EOT
+module foo(inout a, b);
+ assign a = b;
+endmodule
+module bar(output c);
+ foo f(c, 1'b0);
+endmodule
+EOT
+
+hierarchy -auto-top
+flatten
diff --git a/tests/techmap/bug2321.ys b/tests/techmap/bug2321.ys
new file mode 100644
index 000000000..637528b21
--- /dev/null
+++ b/tests/techmap/bug2321.ys
@@ -0,0 +1,15 @@
+read_verilog <<EOT
+module m (input i, output o);
+wire [1023:0] _TECHMAP_DO_00_ = "CONSTMAP; ";
+endmodule
+EOT
+
+design -stash map
+
+read_verilog <<EOT
+module top(output o);
+m m (.o(o), .i(o));
+endmodule
+EOT
+
+techmap -map %map
diff --git a/tests/techmap/bug2332.ys b/tests/techmap/bug2332.ys
new file mode 100644
index 000000000..ed6b35eb2
--- /dev/null
+++ b/tests/techmap/bug2332.ys
@@ -0,0 +1,11 @@
+read_verilog <<EOT
+module top(input [31:0] a, input signed [2:0] x, output [2:0] o);
+
+wire [5:0] t = x * 3;
+assign o = a >> t;
+
+endmodule
+EOT
+
+wreduce
+equiv_opt -assert peepopt
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/cellname.ys b/tests/techmap/cellname.ys
new file mode 100644
index 000000000..2edd6a9fd
--- /dev/null
+++ b/tests/techmap/cellname.ys
@@ -0,0 +1,41 @@
+read_verilog << EOT
+
+module sub (input i, output o);
+parameter _TECHMAP_CELLNAME_ = "";
+namedsub #(.name(_TECHMAP_CELLNAME_)) _TECHMAP_REPLACE_ (i, o);
+endmodule
+
+EOT
+
+design -stash map
+
+read_verilog << EOT
+
+(* blackbox *)
+module sub (input i, output o);
+endmodule
+
+(* blackbox *)
+module namedsub (input i, output o);
+parameter name = "";
+endmodule
+
+module top(input [3:0] i, output [3:0] o);
+
+sub s1 (i[0], o[0]);
+sub subsubsub (i[1], o[1]);
+sub s2 (i[2], o[2]);
+sub xxx (i[3], o[3]);
+
+endmodule
+
+EOT
+
+techmap -map %map
+
+select -assert-count 4 t:namedsub
+select -assert-count 0 t:sub
+select -assert-count 1 t:namedsub r:name=s1 %i
+select -assert-count 1 t:namedsub r:name=subsubsub %i
+select -assert-count 1 t:namedsub r:name=s2 %i
+select -assert-count 1 t:namedsub r:name=xxx %i
diff --git a/tests/techmap/clkbufmap.ys b/tests/techmap/clkbufmap.ys
index b81a35e74..abe830109 100644
--- a/tests/techmap/clkbufmap.ys
+++ b/tests/techmap/clkbufmap.ys
@@ -1,5 +1,7 @@
read_verilog <<EOT
module clkbuf (input i, (* clkbuf_driver *) output o); endmodule
+module inbuf (input i, output o); endmodule
+module clkinbuf (input i, (* clkbuf_driver *) output o); endmodule
module dff ((* clkbuf_sink *) input clk, input d, output q); endmodule
module dffe ((* clkbuf_sink *) input c, input d, e, output q); endmodule
module latch (input e, d, output q); endmodule
@@ -105,3 +107,80 @@ select -assert-count 0 w:clk1 %a %co t:clkbuf %i
select -assert-count 0 w:clk2 %a %co t:clkbuf %i
select -assert-count 0 top/t:clkbuf
select -assert-count 2 sub/t:clkbuf
+
+# ----------------------
+
+design -load ref
+clkbufmap -buf clkbuf o:i -inpad inbuf o:i
+select -assert-count 3 top/t:clkbuf
+select -assert-count 3 sub/t:clkbuf
+select -assert-count 2 top/t:inbuf
+select -assert-count 0 sub/t:inbuf
+select -set clk1 w:clk1 %a %co t:inbuf %i
+select -assert-count 1 @clk1
+select -assert-count 1 @clk1 %x:+[o] %co t:clkbuf %i
+select -set clk1b @clk1 %x:+[o] %co t:clkbuf %i
+select -assert-count 1 @clk1b %x:+[o] %co c:s* %i
+select -assert-count 1 @clk1b %x:+[o] %co c:s0 %i
+select -set clk2 w:clk2 %a %co t:inbuf %i
+select -assert-count 1 @clk2
+select -assert-count 1 @clk2 %x:+[o] %co t:clkbuf %i
+select -set clk2b @clk2 %x:+[o] %co t:clkbuf %i
+select -assert-count 1 @clk2b %x:+[o] %co c:s* %i
+select -assert-count 1 @clk2b %x:+[o] %co c:s1 %i
+select -set clk5 w:clk5 %a %ci t:clkbuf %i
+select -assert-count 1 @clk5
+select -assert-count 1 @clk5 %x:+[o] %co c:s5 %i
+select -assert-count 1 @clk5 %x:+[i] %ci c:s3 %i
+select -set sclk4 w:sclk4 %a %ci t:clkbuf %i
+select -assert-count 1 @sclk4
+select -assert-count 1 @sclk4 %x:+[o] %co c:s11 %i
+select -assert-count 1 @sclk4 %x:+[i] %ci c:s7 %i
+select -set sclk8 w:sclk8 %a %ci t:clkbuf %i
+select -assert-count 1 @sclk8
+select -assert-count 1 @sclk8 %x:+[o] %co c:s13 %i
+select -assert-count 1 @sclk8 %x:+[i] %ci c:s12 %i
+
+# ----------------------
+
+design -load ref
+clkbufmap -inpad inbuf o:i
+select -assert-count 2 top/t:inbuf
+select -assert-count 0 sub/t:inbuf
+select -set clk1 w:clk1 %a %co t:inbuf %i
+select -assert-count 1 @clk1
+select -assert-count 1 @clk1 %x:+[o] %co c:s* %i
+select -assert-count 1 @clk1 %x:+[o] %co c:s0 %i
+select -set clk2 w:clk2 %a %co t:inbuf %i
+select -assert-count 1 @clk2
+select -assert-count 1 @clk2 %x:+[o] %co c:s* %i
+select -assert-count 1 @clk2 %x:+[o] %co c:s1 %i
+
+# ----------------------
+
+design -load ref
+clkbufmap -buf clkbuf o:i -inpad clkinbuf o:i
+select -assert-count 1 top/t:clkbuf
+select -assert-count 3 sub/t:clkbuf
+select -assert-count 2 top/t:clkinbuf
+select -assert-count 0 sub/t:clkinbuf
+select -set clk1 w:clk1 %a %co t:clkinbuf %i
+select -assert-count 1 @clk1
+select -assert-count 1 @clk1 %x:+[o] %co c:s* %i
+select -assert-count 1 @clk1 %x:+[o] %co c:s0 %i
+select -set clk2 w:clk2 %a %co t:clkinbuf %i
+select -assert-count 1 @clk2
+select -assert-count 1 @clk2 %x:+[o] %co c:s* %i
+select -assert-count 1 @clk2 %x:+[o] %co c:s1 %i
+select -set clk5 w:clk5 %a %ci t:clkbuf %i
+select -assert-count 1 @clk5
+select -assert-count 1 @clk5 %x:+[o] %co c:s5 %i
+select -assert-count 1 @clk5 %x:+[i] %ci c:s3 %i
+select -set sclk4 w:sclk4 %a %ci t:clkbuf %i
+select -assert-count 1 @sclk4
+select -assert-count 1 @sclk4 %x:+[o] %co c:s11 %i
+select -assert-count 1 @sclk4 %x:+[i] %ci c:s7 %i
+select -set sclk8 w:sclk8 %a %ci t:clkbuf %i
+select -assert-count 1 @sclk8
+select -assert-count 1 @sclk8 %x:+[o] %co c:s13 %i
+select -assert-count 1 @sclk8 %x:+[i] %ci c:s12 %i
diff --git a/tests/techmap/dff2dffs.ys b/tests/techmap/dff2dffs.ys
deleted file mode 100644
index 105a89400..000000000
--- a/tests/techmap/dff2dffs.ys
+++ /dev/null
@@ -1,50 +0,0 @@
-read_verilog << EOT
-module top(...);
-input clk;
-input d;
-input sr;
-output reg q0, q1, q2, q3, q4, q5;
-
-initial q0 = 1'b0;
-initial q1 = 1'b0;
-initial q2 = 1'b1;
-initial q3 = 1'b1;
-initial q4 = 1'bx;
-initial q5 = 1'bx;
-
-always @(posedge clk) begin
- q0 <= sr ? 1'b0 : d;
- q1 <= sr ? 1'b1 : d;
- q2 <= sr ? 1'b0 : d;
- q3 <= sr ? 1'b1 : d;
- q4 <= sr ? 1'b0 : d;
- q5 <= sr ? 1'b1 : d;
-end
-
-endmodule
-EOT
-
-proc
-simplemap
-design -save ref
-
-dff2dffs
-clean
-
-select -assert-count 1 w:q0 %x t:$_SDFF_PP0_ %i
-select -assert-count 1 w:q1 %x t:$_SDFF_PP1_ %i
-select -assert-count 1 w:q2 %x t:$_SDFF_PP0_ %i
-select -assert-count 1 w:q3 %x t:$_SDFF_PP1_ %i
-select -assert-count 1 w:q4 %x t:$_SDFF_PP0_ %i
-select -assert-count 1 w:q5 %x t:$_SDFF_PP1_ %i
-
-design -load ref
-dff2dffs -match-init
-clean
-
-select -assert-count 1 w:q0 %x t:$_SDFF_PP0_ %i
-select -assert-count 0 w:q1 %x t:$_SDFF_PP1_ %i
-select -assert-count 0 w:q2 %x t:$_SDFF_PP0_ %i
-select -assert-count 1 w:q3 %x t:$_SDFF_PP1_ %i
-select -assert-count 1 w:q4 %x t:$_SDFF_PP0_ %i
-select -assert-count 1 w:q5 %x t:$_SDFF_PP1_ %i
diff --git a/tests/techmap/dff2ff.ys b/tests/techmap/dff2ff.ys
new file mode 100644
index 000000000..5adf14b07
--- /dev/null
+++ b/tests/techmap/dff2ff.ys
@@ -0,0 +1,16 @@
+read_verilog -icells << EOT
+module top(...);
+
+input [1:0] D;
+input C;
+output [1:0] Q;
+
+always @(posedge C)
+ Q <= D;
+
+endmodule
+EOT
+
+proc
+
+equiv_opt techmap -map +/dff2ff.v
diff --git a/tests/techmap/dfflegalize_adff.ys b/tests/techmap/dfflegalize_adff.ys
new file mode 100644
index 000000000..fc579e7d6
--- /dev/null
+++ b/tests/techmap/dfflegalize_adff.ys
@@ -0,0 +1,135 @@
+read_verilog -icells <<EOT
+
+module adff0(input C, R, D, output [2:0] Q);
+$_DFF_PP0_ ff0 (.C(C), .R(R), .D(D), .Q(Q[0]));
+$_DFF_PN0_ ff1 (.C(C), .R(R), .D(D), .Q(Q[1]));
+$_DFF_NP0_ ff2 (.C(C), .R(R), .D(D), .Q(Q[2]));
+endmodule
+
+module adff1(input C, R, D, output [2:0] Q);
+$_DFF_PP1_ ff0 (.C(C), .R(R), .D(D), .Q(Q[0]));
+$_DFF_PN1_ ff1 (.C(C), .R(R), .D(D), .Q(Q[1]));
+$_DFF_NP1_ ff2 (.C(C), .R(R), .D(D), .Q(Q[2]));
+endmodule
+
+module adffe0(input C, E, R, D, output [3:0] Q);
+$_DFFE_PP0P_ ff0 (.C(C), .R(R), .E(E), .D(D), .Q(Q[0]));
+$_DFFE_PP0N_ ff1 (.C(C), .R(R), .E(E), .D(D), .Q(Q[1]));
+$_DFFE_PN0P_ ff2 (.C(C), .R(R), .E(E), .D(D), .Q(Q[2]));
+$_DFFE_NP0P_ ff3 (.C(C), .R(R), .E(E), .D(D), .Q(Q[3]));
+endmodule
+
+module adffe1(input C, E, R, D, output [3:0] Q);
+$_DFFE_PP1P_ ff0 (.C(C), .R(R), .E(E), .D(D), .Q(Q[0]));
+$_DFFE_PP1N_ ff1 (.C(C), .R(R), .E(E), .D(D), .Q(Q[1]));
+$_DFFE_PN1P_ ff2 (.C(C), .R(R), .E(E), .D(D), .Q(Q[2]));
+$_DFFE_NP1P_ ff3 (.C(C), .R(R), .E(E), .D(D), .Q(Q[3]));
+endmodule
+
+module top(input C, E, R, D, output [13:0] Q);
+adff0 adff0_(.C(C), .R(R), .D(D), .Q(Q[2:0]));
+adff1 adff1_(.C(C), .R(R), .D(D), .Q(Q[5:3]));
+adffe0 adffe0_(.C(C), .R(R), .E(E), .D(D), .Q(Q[9:6]));
+adffe1 adffe1_(.C(C), .R(R), .E(E), .D(D), .Q(Q[13:10]));
+endmodule
+
+EOT
+
+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
+
+
+# Convert everything to ADFFs.
+
+design -load orig
+dfflegalize -cell $_DFF_PP0_ x
+
+select -assert-count 2 adff0/t:$_NOT_
+select -assert-count 8 adff1/t:$_NOT_
+select -assert-count 2 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:$_DFF_PP0_
+select -assert-none t:$_DFF_PP0_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to ADFFEs.
+
+design -load orig
+dfflegalize -cell $_DFFE_PP0P_ x
+
+select -assert-count 2 adff0/t:$_NOT_
+select -assert-count 8 adff1/t:$_NOT_
+select -assert-count 3 adffe0/t:$_NOT_
+select -assert-count 11 adffe1/t:$_NOT_
+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
+dfflegalize -cell $_DFFSR_PPP_ 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:$_DFFSR_PPP_
+select -assert-none t:$_DFFSR_PPP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to DFFSREs.
+
+design -load orig
+dfflegalize -cell $_DFFSRE_PPPP_ 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:$_DFFSRE_PPPP_
+select -assert-none t:$_DFFSRE_PPPP_ t:$_NOT_ top/* %% %n t:* %i
diff --git a/tests/techmap/dfflegalize_adff_init.ys b/tests/techmap/dfflegalize_adff_init.ys
new file mode 100644
index 000000000..25ed59307
--- /dev/null
+++ b/tests/techmap/dfflegalize_adff_init.ys
@@ -0,0 +1,333 @@
+read_verilog -icells <<EOT
+
+module adff0(input C, R, D, (* init = 3'b000 *) output [2:0] Q);
+$_DFF_PP0_ ff0 (.C(C), .R(R), .D(D), .Q(Q[0]));
+$_DFF_PN0_ ff1 (.C(C), .R(R), .D(D), .Q(Q[1]));
+$_DFF_NP0_ ff2 (.C(C), .R(R), .D(D), .Q(Q[2]));
+endmodule
+
+module adff1(input C, R, D, (* init = 3'b000 *) output [2:0] Q);
+$_DFF_PP1_ ff0 (.C(C), .R(R), .D(D), .Q(Q[0]));
+$_DFF_PN1_ ff1 (.C(C), .R(R), .D(D), .Q(Q[1]));
+$_DFF_NP1_ ff2 (.C(C), .R(R), .D(D), .Q(Q[2]));
+endmodule
+
+module adffe0(input C, E, R, D, (* init = 4'b0000 *) output [3:0] Q);
+$_DFFE_PP0P_ ff0 (.C(C), .R(R), .E(E), .D(D), .Q(Q[0]));
+$_DFFE_PP0N_ ff1 (.C(C), .R(R), .E(E), .D(D), .Q(Q[1]));
+$_DFFE_PN0P_ ff2 (.C(C), .R(R), .E(E), .D(D), .Q(Q[2]));
+$_DFFE_NP0P_ ff3 (.C(C), .R(R), .E(E), .D(D), .Q(Q[3]));
+endmodule
+
+module adffe1(input C, E, R, D, (* init = 4'b0000 *) output [3:0] Q);
+$_DFFE_PP1P_ ff0 (.C(C), .R(R), .E(E), .D(D), .Q(Q[0]));
+$_DFFE_PP1N_ ff1 (.C(C), .R(R), .E(E), .D(D), .Q(Q[1]));
+$_DFFE_PN1P_ ff2 (.C(C), .R(R), .E(E), .D(D), .Q(Q[2]));
+$_DFFE_NP1P_ ff3 (.C(C), .R(R), .E(E), .D(D), .Q(Q[3]));
+endmodule
+
+module top(input C, E, R, D, output [13:0] Q);
+adff0 adff0_(.C(C), .R(R), .D(D), .Q(Q[2:0]));
+adff1 adff1_(.C(C), .R(R), .D(D), .Q(Q[5:3]));
+adffe0 adffe0_(.C(C), .R(R), .E(E), .D(D), .Q(Q[9:6]));
+adffe1 adffe1_(.C(C), .R(R), .E(E), .D(D), .Q(Q[13:10]));
+endmodule
+
+EOT
+
+design -save orig
+flatten
+equiv_opt -assert -multiclock dfflegalize -cell $_DFF_PP0_ 0 -cell $_DLATCH_P_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_DFF_PP0_ 1 -cell $_DLATCH_P_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_DFF_PP1_ 0 -cell $_DLATCH_P_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_DFF_PP1_ 1 -cell $_DLATCH_P_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_DFFE_PP0P_ 0 -cell $_DLATCH_P_ 1
+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
+equiv_opt -assert -multiclock dfflegalize -cell $_DFFSRE_PPPP_ 1
+
+
+# Convert everything to ADFFs.
+
+design -load orig
+dfflegalize -cell $_DFF_PP0_ 0 -cell $_DLATCH_P_ 0
+
+select -assert-count 2 adff0/t:$_NOT_
+select -assert-count 10 adff1/t:$_NOT_
+select -assert-count 2 adffe0/t:$_NOT_
+select -assert-count 12 adffe1/t:$_NOT_
+select -assert-count 0 adff0/t:$_MUX_
+select -assert-count 3 adff1/t:$_MUX_
+select -assert-count 4 adffe0/t:$_MUX_
+select -assert-count 8 adffe1/t:$_MUX_
+select -assert-count 3 adff0/t:$_DFF_PP0_
+select -assert-count 6 adff1/t:$_DFF_PP0_
+select -assert-count 4 adffe0/t:$_DFF_PP0_
+select -assert-count 8 adffe1/t:$_DFF_PP0_
+select -assert-count 0 adff0/t:$_DLATCH_P_
+select -assert-count 3 adff1/t:$_DLATCH_P_
+select -assert-count 0 adffe0/t:$_DLATCH_P_
+select -assert-count 4 adffe1/t:$_DLATCH_P_
+select -assert-none t:$_DFF_PP0_ t:$_DLATCH_P_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFF_PP0_ 1 -cell $_DLATCH_P_ 0
+
+select -assert-count 10 adff0/t:$_NOT_
+select -assert-count 8 adff1/t:$_NOT_
+select -assert-count 12 adffe0/t:$_NOT_
+select -assert-count 10 adffe1/t:$_NOT_
+select -assert-count 3 adff0/t:$_MUX_
+select -assert-count 0 adff1/t:$_MUX_
+select -assert-count 8 adffe0/t:$_MUX_
+select -assert-count 4 adffe1/t:$_MUX_
+select -assert-count 6 adff0/t:$_DFF_PP0_
+select -assert-count 3 adff1/t:$_DFF_PP0_
+select -assert-count 8 adffe0/t:$_DFF_PP0_
+select -assert-count 4 adffe1/t:$_DFF_PP0_
+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:$_DFF_PP0_ t:$_DLATCH_P_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFF_PP1_ 0 -cell $_DLATCH_P_ 0
+
+select -assert-count 10 adff0/t:$_NOT_
+select -assert-count 2 adff1/t:$_NOT_
+select -assert-count 12 adffe0/t:$_NOT_
+select -assert-count 2 adffe1/t:$_NOT_
+select -assert-count 3 adff0/t:$_MUX_
+select -assert-count 0 adff1/t:$_MUX_
+select -assert-count 8 adffe0/t:$_MUX_
+select -assert-count 4 adffe1/t:$_MUX_
+select -assert-count 6 adff0/t:$_DFF_PP1_
+select -assert-count 3 adff1/t:$_DFF_PP1_
+select -assert-count 8 adffe0/t:$_DFF_PP1_
+select -assert-count 4 adffe1/t:$_DFF_PP1_
+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:$_DFF_PP1_ t:$_DLATCH_P_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFF_PP1_ 1 -cell $_DLATCH_P_ 0
+
+select -assert-count 8 adff0/t:$_NOT_
+select -assert-count 10 adff1/t:$_NOT_
+select -assert-count 10 adffe0/t:$_NOT_
+select -assert-count 12 adffe1/t:$_NOT_
+select -assert-count 0 adff0/t:$_MUX_
+select -assert-count 3 adff1/t:$_MUX_
+select -assert-count 4 adffe0/t:$_MUX_
+select -assert-count 8 adffe1/t:$_MUX_
+select -assert-count 3 adff0/t:$_DFF_PP1_
+select -assert-count 6 adff1/t:$_DFF_PP1_
+select -assert-count 4 adffe0/t:$_DFF_PP1_
+select -assert-count 8 adffe1/t:$_DFF_PP1_
+select -assert-count 0 adff0/t:$_DLATCH_P_
+select -assert-count 3 adff1/t:$_DLATCH_P_
+select -assert-count 0 adffe0/t:$_DLATCH_P_
+select -assert-count 4 adffe1/t:$_DLATCH_P_
+select -assert-none t:$_DFF_PP1_ t:$_DLATCH_P_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to ADFFEs.
+
+design -load orig
+dfflegalize -cell $_DFFE_PP0P_ 0 -cell $_DLATCH_P_ 1
+
+select -assert-count 2 adff0/t:$_NOT_
+select -assert-count 13 adff1/t:$_NOT_
+select -assert-count 3 adffe0/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_
+select -assert-count 4 adffe1/t:$_MUX_
+select -assert-count 3 adff0/t:$_DFFE_PP0P_
+select -assert-count 6 adff1/t:$_DFFE_PP0P_
+select -assert-count 4 adffe0/t:$_DFFE_PP0P_
+select -assert-count 8 adffe1/t:$_DFFE_PP0P_
+select -assert-count 0 adff0/t:$_DLATCH_P_
+select -assert-count 3 adff1/t:$_DLATCH_P_
+select -assert-count 0 adffe0/t:$_DLATCH_P_
+select -assert-count 4 adffe1/t:$_DLATCH_P_
+select -assert-none t:$_DFFE_PP0P_ t:$_DLATCH_P_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFFE_PP0P_ 1 -cell $_DLATCH_P_ 1
+
+select -assert-count 13 adff0/t:$_NOT_
+select -assert-count 8 adff1/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_
+select -assert-count 4 adffe0/t:$_MUX_
+select -assert-count 0 adffe1/t:$_MUX_
+select -assert-count 6 adff0/t:$_DFFE_PP0P_
+select -assert-count 3 adff1/t:$_DFFE_PP0P_
+select -assert-count 8 adffe0/t:$_DFFE_PP0P_
+select -assert-count 4 adffe1/t:$_DFFE_PP0P_
+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_PP0P_ t:$_DLATCH_P_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFFE_PP1P_ 0 -cell $_DLATCH_P_ 1
+
+select -assert-count 10 adff0/t:$_NOT_
+select -assert-count 2 adff1/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 9 adff0/t:$_DFFE_PP1P_
+select -assert-count 3 adff1/t:$_DFFE_PP1P_
+select -assert-count 12 adffe0/t:$_DFFE_PP1P_
+select -assert-count 4 adffe1/t:$_DFFE_PP1P_
+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 13 adff1/t:$_NOT_
+select -assert-count 11 adffe0/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_
+select -assert-count 4 adffe1/t:$_MUX_
+select -assert-count 3 adff0/t:$_DFFE_PP1P_
+select -assert-count 6 adff1/t:$_DFFE_PP1P_
+select -assert-count 4 adffe0/t:$_DFFE_PP1P_
+select -assert-count 8 adffe1/t:$_DFFE_PP1P_
+select -assert-count 0 adff0/t:$_DLATCH_P_
+select -assert-count 3 adff1/t:$_DLATCH_P_
+select -assert-count 0 adffe0/t:$_DLATCH_P_
+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
+dfflegalize -cell $_DFFSR_PPP_ 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:$_DFFSR_PPP_
+select -assert-none t:$_DFFSR_PPP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFFSR_PPP_ 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:$_DFFSR_PPP_
+select -assert-none t:$_DFFSR_PPP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to DFFSREs.
+
+design -load orig
+dfflegalize -cell $_DFFSRE_PPPP_ 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:$_DFFSRE_PPPP_
+select -assert-none t:$_DFFSRE_PPPP_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFFSRE_PPPP_ 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:$_DFFSRE_PPPP_
+select -assert-none t:$_DFFSRE_PPPP_ t:$_NOT_ top/* %% %n t:* %i
diff --git a/tests/techmap/dfflegalize_adlatch.ys b/tests/techmap/dfflegalize_adlatch.ys
new file mode 100644
index 000000000..b242cc809
--- /dev/null
+++ b/tests/techmap/dfflegalize_adlatch.ys
@@ -0,0 +1,51 @@
+read_verilog -icells <<EOT
+
+module adlatch0(input E, R, D, output [2:0] Q);
+$_DLATCH_PP0_ ff0 (.E(E), .R(R), .D(D), .Q(Q[0]));
+$_DLATCH_PN0_ ff1 (.E(E), .R(R), .D(D), .Q(Q[1]));
+$_DLATCH_NP0_ ff2 (.E(E), .R(R), .D(D), .Q(Q[2]));
+endmodule
+
+module adlatch1(input E, R, D, output [2:0] Q);
+$_DLATCH_PP1_ ff0 (.E(E), .R(R), .D(D), .Q(Q[0]));
+$_DLATCH_PN1_ ff1 (.E(E), .R(R), .D(D), .Q(Q[1]));
+$_DLATCH_NP1_ ff2 (.E(E), .R(R), .D(D), .Q(Q[2]));
+endmodule
+
+module top(input C, E, R, D, output [13:0] Q);
+adlatch0 adlatch0_(.E(E), .R(R), .D(D), .Q(Q[2:0]));
+adlatch1 adlatch1_(.E(E), .R(R), .D(D), .Q(Q[5:3]));
+endmodule
+
+EOT
+
+design -save orig
+flatten
+equiv_opt -assert -multiclock dfflegalize -cell $_DLATCH_PP0_ x
+equiv_opt -assert -multiclock dfflegalize -cell $_DLATCHSR_PPP_ x
+
+
+# Convert everything to ADLATCHs.
+
+design -load orig
+dfflegalize -cell $_DLATCH_PP0_ x
+
+select -assert-count 2 adlatch0/t:$_NOT_
+select -assert-count 8 adlatch1/t:$_NOT_
+select -assert-count 0 adlatch0/t:$_MUX_
+select -assert-count 0 adlatch1/t:$_MUX_
+select -assert-count 6 t:$_DLATCH_PP0_
+select -assert-none t:$_DLATCH_PP0_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to DLATCHSRs.
+
+design -load orig
+dfflegalize -cell $_DLATCHSR_PPP_ x
+
+select -assert-count 2 adlatch0/t:$_NOT_
+select -assert-count 2 adlatch1/t:$_NOT_
+select -assert-count 0 adlatch0/t:$_MUX_
+select -assert-count 0 adlatch1/t:$_MUX_
+select -assert-count 6 t:$_DLATCHSR_PPP_
+select -assert-none t:$_DLATCHSR_PPP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
diff --git a/tests/techmap/dfflegalize_adlatch_init.ys b/tests/techmap/dfflegalize_adlatch_init.ys
new file mode 100644
index 000000000..a55082d1d
--- /dev/null
+++ b/tests/techmap/dfflegalize_adlatch_init.ys
@@ -0,0 +1,99 @@
+read_verilog -icells <<EOT
+
+module adlatch0(input E, R, D, (* init = 3'b000 *) output [2:0] Q);
+$_DLATCH_PP0_ ff0 (.E(E), .R(R), .D(D), .Q(Q[0]));
+$_DLATCH_PN0_ ff1 (.E(E), .R(R), .D(D), .Q(Q[1]));
+$_DLATCH_NP0_ ff2 (.E(E), .R(R), .D(D), .Q(Q[2]));
+endmodule
+
+module adlatch1(input E, R, D, (* init = 3'b000 *) output [2:0] Q);
+$_DLATCH_PP1_ ff0 (.E(E), .R(R), .D(D), .Q(Q[0]));
+$_DLATCH_PN1_ ff1 (.E(E), .R(R), .D(D), .Q(Q[1]));
+$_DLATCH_NP1_ ff2 (.E(E), .R(R), .D(D), .Q(Q[2]));
+endmodule
+
+module top(input C, E, R, D, output [13:0] Q);
+adlatch0 adlatch0_(.E(E), .R(R), .D(D), .Q(Q[2:0]));
+adlatch1 adlatch1_(.E(E), .R(R), .D(D), .Q(Q[5:3]));
+endmodule
+
+EOT
+
+design -save orig
+flatten
+equiv_opt -assert -multiclock dfflegalize -cell $_DLATCH_PP0_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_DLATCH_PP0_ 1
+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
+
+
+# Convert everything to ADLATCHs.
+
+design -load orig
+dfflegalize -cell $_DLATCH_PP0_ 0
+
+select -assert-count 2 adlatch0/t:$_NOT_
+select -assert-count 10 adlatch1/t:$_NOT_
+select -assert-count 0 adlatch0/t:$_MUX_
+select -assert-count 3 adlatch1/t:$_MUX_
+select -assert-count 3 adlatch0/t:$_DLATCH_PP0_
+select -assert-count 9 adlatch1/t:$_DLATCH_PP0_
+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 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_
+select -assert-count 9 adlatch0/t:$_DLATCH_PP0_
+select -assert-count 3 adlatch1/t:$_DLATCH_PP0_
+select -assert-none t:$_DLATCH_PP0_ t:$_DLATCH_P_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DLATCH_PP1_ 0
+
+select -assert-count 10 adlatch0/t:$_NOT_
+select -assert-count 2 adlatch1/t:$_NOT_
+select -assert-count 3 adlatch0/t:$_MUX_
+select -assert-count 0 adlatch1/t:$_MUX_
+select -assert-count 9 adlatch0/t:$_DLATCH_PP1_
+select -assert-count 3 adlatch1/t:$_DLATCH_PP1_
+select -assert-none t:$_DLATCH_PP1_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DLATCH_PP1_ 1
+
+select -assert-count 8 adlatch0/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_
+select -assert-count 9 adlatch1/t:$_DLATCH_PP1_
+select -assert-none t:$_DLATCH_PP1_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to DLATCHSRs.
+
+design -load orig
+dfflegalize -cell $_DLATCHSR_PPP_ 0
+
+select -assert-count 2 adlatch0/t:$_NOT_
+select -assert-count 2 adlatch1/t:$_NOT_
+select -assert-count 0 adlatch0/t:$_MUX_
+select -assert-count 0 adlatch1/t:$_MUX_
+select -assert-count 6 t:$_DLATCHSR_PPP_
+select -assert-none t:$_DLATCHSR_PPP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DLATCHSR_PPP_ 1
+
+select -assert-count 8 adlatch0/t:$_NOT_
+select -assert-count 8 adlatch1/t:$_NOT_
+select -assert-count 0 adlatch0/t:$_MUX_
+select -assert-count 0 adlatch1/t:$_MUX_
+select -assert-count 6 t:$_DLATCHSR_PPP_
+select -assert-none t:$_DLATCHSR_PPP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
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
new file mode 100644
index 000000000..374289678
--- /dev/null
+++ b/tests/techmap/dfflegalize_dff.ys
@@ -0,0 +1,351 @@
+read_verilog -icells <<EOT
+
+module dff(input C, D, output [1:0] Q);
+$_DFF_P_ ff0 (.C(C), .D(D), .Q(Q[0]));
+$_DFF_N_ ff1 (.C(C), .D(D), .Q(Q[1]));
+endmodule
+
+module dffe(input C, E, D, output [2:0] Q);
+$_DFFE_PP_ ff0 (.C(C), .E(E), .D(D), .Q(Q[0]));
+$_DFFE_PN_ ff1 (.C(C), .E(E), .D(D), .Q(Q[1]));
+$_DFFE_NP_ ff2 (.C(C), .E(E), .D(D), .Q(Q[2]));
+endmodule
+
+module sdff0(input C, R, D, output [2:0] Q);
+$_SDFF_PP0_ ff0 (.C(C), .R(R), .D(D), .Q(Q[0]));
+$_SDFF_PN0_ ff1 (.C(C), .R(R), .D(D), .Q(Q[1]));
+$_SDFF_NP0_ ff2 (.C(C), .R(R), .D(D), .Q(Q[2]));
+endmodule
+
+module sdff1(input C, R, D, output [2:0] Q);
+$_SDFF_PP1_ ff0 (.C(C), .R(R), .D(D), .Q(Q[0]));
+$_SDFF_PN1_ ff1 (.C(C), .R(R), .D(D), .Q(Q[1]));
+$_SDFF_NP1_ ff2 (.C(C), .R(R), .D(D), .Q(Q[2]));
+endmodule
+
+module sdffe0(input C, E, R, D, output [3:0] Q);
+$_SDFFE_PP0P_ ff0 (.C(C), .R(R), .E(E), .D(D), .Q(Q[0]));
+$_SDFFE_PP0N_ ff1 (.C(C), .R(R), .E(E), .D(D), .Q(Q[1]));
+$_SDFFE_PN0P_ ff2 (.C(C), .R(R), .E(E), .D(D), .Q(Q[2]));
+$_SDFFE_NP0P_ ff3 (.C(C), .R(R), .E(E), .D(D), .Q(Q[3]));
+endmodule
+
+module sdffe1(input C, E, R, D, output [3:0] Q);
+$_SDFFE_PP1P_ ff0 (.C(C), .R(R), .E(E), .D(D), .Q(Q[0]));
+$_SDFFE_PP1N_ ff1 (.C(C), .R(R), .E(E), .D(D), .Q(Q[1]));
+$_SDFFE_PN1P_ ff2 (.C(C), .R(R), .E(E), .D(D), .Q(Q[2]));
+$_SDFFE_NP1P_ ff3 (.C(C), .R(R), .E(E), .D(D), .Q(Q[3]));
+endmodule
+
+module sdffce0(input C, E, R, D, output [3:0] Q);
+$_SDFFCE_PP0P_ ff0 (.C(C), .R(R), .E(E), .D(D), .Q(Q[0]));
+$_SDFFCE_PP0N_ ff1 (.C(C), .R(R), .E(E), .D(D), .Q(Q[1]));
+$_SDFFCE_PN0P_ ff2 (.C(C), .R(R), .E(E), .D(D), .Q(Q[2]));
+$_SDFFCE_NP0P_ ff3 (.C(C), .R(R), .E(E), .D(D), .Q(Q[3]));
+endmodule
+
+module sdffce1(input C, E, R, D, output [3:0] Q);
+$_SDFFCE_PP1P_ ff0 (.C(C), .R(R), .E(E), .D(D), .Q(Q[0]));
+$_SDFFCE_PP1N_ ff1 (.C(C), .R(R), .E(E), .D(D), .Q(Q[1]));
+$_SDFFCE_PN1P_ ff2 (.C(C), .R(R), .E(E), .D(D), .Q(Q[2]));
+$_SDFFCE_NP1P_ ff3 (.C(C), .R(R), .E(E), .D(D), .Q(Q[3]));
+endmodule
+
+module top(input C, E, R, D, output [26:0] Q);
+dff dff_(.C(C), .D(D), .Q(Q[1:0]));
+dffe dffe_(.C(C), .E(E), .D(D), .Q(Q[4:2]));
+sdff0 sdff0_(.C(C), .R(R), .D(D), .Q(Q[7:5]));
+sdff1 sdff1_(.C(C), .R(R), .D(D), .Q(Q[10:8]));
+sdffe0 sdffe0_(.C(C), .R(R), .E(E), .D(D), .Q(Q[14:11]));
+sdffe1 sdffe1_(.C(C), .R(R), .E(E), .D(D), .Q(Q[18:15]));
+sdffce0 sdffce0_(.C(C), .R(R), .E(E), .D(D), .Q(Q[22:19]));
+sdffce1 sdffce1_(.C(C), .R(R), .E(E), .D(D), .Q(Q[26:23]));
+endmodule
+
+EOT
+
+design -save orig
+flatten
+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
+equiv_opt -assert -multiclock dfflegalize -cell $_SDFFE_PP0P_ x
+equiv_opt -assert -multiclock dfflegalize -cell $_SDFFCE_PP0P_ x
+
+# Convert everything to DFFs.
+
+design -load orig
+dfflegalize -cell $_DFF_P_ 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:$_DFF_P_
+select -assert-none t:$_DFF_P_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to DFFEs.
+
+design -load orig
+dfflegalize -cell $_DFFE_PP_ 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:$_DFFE_PP_
+select -assert-none t:$_DFFE_PP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to ADFFs.
+
+design -load orig
+dfflegalize -cell $_DFF_PP0_ 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:$_DFF_PP0_
+select -assert-none t:$_DFF_PP0_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to ADFFEs.
+
+design -load orig
+dfflegalize -cell $_DFFE_PP0P_ 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:$_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
+dfflegalize -cell $_DFFSR_PPP_ 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:$_DFFSR_PPP_
+select -assert-none t:$_DFFSR_PPP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to DFFSREs.
+
+design -load orig
+dfflegalize -cell $_DFFSRE_PPPP_ 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:$_DFFSRE_PPPP_
+select -assert-none t:$_DFFSRE_PPPP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to SDFFs.
+
+design -load orig
+dfflegalize -cell $_SDFF_PP0_ x
+
+select -assert-count 1 dff/t:$_NOT_
+select -assert-count 1 dffe/t:$_NOT_
+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 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 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_ top/* %% %n t:* %i
+
+
+# Convert everything to SDFFEs.
+
+design -load orig
+dfflegalize -cell $_SDFFE_PP0P_ x
+
+select -assert-count 1 dff/t:$_NOT_
+select -assert-count 2 dffe/t:$_NOT_
+select -assert-count 2 sdff0/t:$_NOT_
+select -assert-count 8 sdff1/t:$_NOT_
+select -assert-count 3 sdffe0/t:$_NOT_
+select -assert-count 11 sdffe1/t:$_NOT_
+select -assert-count 3 sdffce0/t:$_NOT_
+select -assert-count 11 sdffce1/t:$_NOT_
+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 27 t:$_SDFFE_PP0P_
+select -assert-none t:$_SDFFE_PP0P_ t:$_NOT_ t:$_AND_ t:$_ORNOT_ t:$_ANDNOT_ top/* %% %n t:* %i
+
+
+# Convert everything to SDFFCEs.
+
+design -load orig
+dfflegalize -cell $_SDFFCE_PP0P_ x
+
+select -assert-count 1 dff/t:$_NOT_
+select -assert-count 2 dffe/t:$_NOT_
+select -assert-count 2 sdff0/t:$_NOT_
+select -assert-count 8 sdff1/t:$_NOT_
+select -assert-count 3 sdffe0/t:$_NOT_
+select -assert-count 11 sdffe1/t:$_NOT_
+select -assert-count 3 sdffce0/t:$_NOT_
+select -assert-count 11 sdffce1/t:$_NOT_
+select -assert-count 0 t:$_OR_ t:$_ORNOT_ t:$_ANDNOT_ %% sdffe0/* sdffe1/* %u %n %i
+select -assert-count 2 sdffe0/t:$_OR_
+select -assert-count 2 sdffe1/t:$_OR_
+select -assert-count 1 sdffe0/t:$_ORNOT_
+select -assert-count 1 sdffe1/t:$_ORNOT_
+select -assert-count 1 sdffe0/t:$_ANDNOT_
+select -assert-count 1 sdffe1/t:$_ANDNOT_
+select -assert-count 27 t:$_SDFFCE_PP0P_
+select -assert-none t:$_SDFFCE_PP0P_ t:$_NOT_ t:$_OR_ t:$_ORNOT_ t:$_ANDNOT_ top/* %% %n t:* %i
diff --git a/tests/techmap/dfflegalize_dff_init.ys b/tests/techmap/dfflegalize_dff_init.ys
new file mode 100644
index 000000000..a170249c7
--- /dev/null
+++ b/tests/techmap/dfflegalize_dff_init.ys
@@ -0,0 +1,868 @@
+read_verilog -icells <<EOT
+
+module dff(input C, D, (* init = 2'b00 *) output [1:0] Q);
+$_DFF_P_ ff0 (.C(C), .D(D), .Q(Q[0]));
+$_DFF_N_ ff1 (.C(C), .D(D), .Q(Q[1]));
+endmodule
+
+module dffe(input C, E, D, (* init = 3'b000 *) output [2:0] Q);
+$_DFFE_PP_ ff0 (.C(C), .E(E), .D(D), .Q(Q[0]));
+$_DFFE_PN_ ff1 (.C(C), .E(E), .D(D), .Q(Q[1]));
+$_DFFE_NP_ ff2 (.C(C), .E(E), .D(D), .Q(Q[2]));
+endmodule
+
+module sdff0(input C, R, D, (* init = 3'b000 *) output [2:0] Q);
+$_SDFF_PP0_ ff0 (.C(C), .R(R), .D(D), .Q(Q[0]));
+$_SDFF_PN0_ ff1 (.C(C), .R(R), .D(D), .Q(Q[1]));
+$_SDFF_NP0_ ff2 (.C(C), .R(R), .D(D), .Q(Q[2]));
+endmodule
+
+module sdff1(input C, R, D, (* init = 3'b000 *) output [2:0] Q);
+$_SDFF_PP1_ ff0 (.C(C), .R(R), .D(D), .Q(Q[0]));
+$_SDFF_PN1_ ff1 (.C(C), .R(R), .D(D), .Q(Q[1]));
+$_SDFF_NP1_ ff2 (.C(C), .R(R), .D(D), .Q(Q[2]));
+endmodule
+
+module sdffe0(input C, E, R, D, (* init = 4'b0000 *) output [3:0] Q);
+$_SDFFE_PP0P_ ff0 (.C(C), .R(R), .E(E), .D(D), .Q(Q[0]));
+$_SDFFE_PP0N_ ff1 (.C(C), .R(R), .E(E), .D(D), .Q(Q[1]));
+$_SDFFE_PN0P_ ff2 (.C(C), .R(R), .E(E), .D(D), .Q(Q[2]));
+$_SDFFE_NP0P_ ff3 (.C(C), .R(R), .E(E), .D(D), .Q(Q[3]));
+endmodule
+
+module sdffe1(input C, E, R, D, (* init = 4'b0000 *) output [3:0] Q);
+$_SDFFE_PP1P_ ff0 (.C(C), .R(R), .E(E), .D(D), .Q(Q[0]));
+$_SDFFE_PP1N_ ff1 (.C(C), .R(R), .E(E), .D(D), .Q(Q[1]));
+$_SDFFE_PN1P_ ff2 (.C(C), .R(R), .E(E), .D(D), .Q(Q[2]));
+$_SDFFE_NP1P_ ff3 (.C(C), .R(R), .E(E), .D(D), .Q(Q[3]));
+endmodule
+
+module sdffce0(input C, E, R, D, (* init = 4'b0000 *) output [3:0] Q);
+$_SDFFCE_PP0P_ ff0 (.C(C), .R(R), .E(E), .D(D), .Q(Q[0]));
+$_SDFFCE_PP0N_ ff1 (.C(C), .R(R), .E(E), .D(D), .Q(Q[1]));
+$_SDFFCE_PN0P_ ff2 (.C(C), .R(R), .E(E), .D(D), .Q(Q[2]));
+$_SDFFCE_NP0P_ ff3 (.C(C), .R(R), .E(E), .D(D), .Q(Q[3]));
+endmodule
+
+module sdffce1(input C, E, R, D, (* init = 4'b0000 *) output [3:0] Q);
+$_SDFFCE_PP1P_ ff0 (.C(C), .R(R), .E(E), .D(D), .Q(Q[0]));
+$_SDFFCE_PP1N_ ff1 (.C(C), .R(R), .E(E), .D(D), .Q(Q[1]));
+$_SDFFCE_PN1P_ ff2 (.C(C), .R(R), .E(E), .D(D), .Q(Q[2]));
+$_SDFFCE_NP1P_ ff3 (.C(C), .R(R), .E(E), .D(D), .Q(Q[3]));
+endmodule
+
+module top(input C, E, R, D, output [26:0] Q);
+dff dff_(.C(C), .D(D), .Q(Q[1:0]));
+dffe dffe_(.C(C), .E(E), .D(D), .Q(Q[4:2]));
+sdff0 sdff0_(.C(C), .R(R), .D(D), .Q(Q[7:5]));
+sdff1 sdff1_(.C(C), .R(R), .D(D), .Q(Q[10:8]));
+sdffe0 sdffe0_(.C(C), .R(R), .E(E), .D(D), .Q(Q[14:11]));
+sdffe1 sdffe1_(.C(C), .R(R), .E(E), .D(D), .Q(Q[18:15]));
+sdffce0 sdffce0_(.C(C), .R(R), .E(E), .D(D), .Q(Q[22:19]));
+sdffce1 sdffce1_(.C(C), .R(R), .E(E), .D(D), .Q(Q[26:23]));
+endmodule
+
+EOT
+
+design -save orig
+flatten
+equiv_opt -assert -multiclock dfflegalize -cell $_DFF_P_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_DFF_P_ 1
+equiv_opt -assert -multiclock dfflegalize -cell $_DFFE_PP_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_DFFE_PP_ 1
+equiv_opt -assert -multiclock dfflegalize -cell $_DFF_PP0_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_DFF_PP0_ 1
+equiv_opt -assert -multiclock dfflegalize -cell $_DFF_PP1_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_DFF_PP1_ 1
+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
+equiv_opt -assert -multiclock dfflegalize -cell $_DFFSRE_PPPP_ 1
+equiv_opt -assert -multiclock dfflegalize -cell $_SDFF_PP0_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_SDFF_PP0_ 1
+equiv_opt -assert -multiclock dfflegalize -cell $_SDFF_PP1_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_SDFF_PP1_ 1
+equiv_opt -assert -multiclock dfflegalize -cell $_SDFFE_PP0P_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_SDFFE_PP0P_ 1
+equiv_opt -assert -multiclock dfflegalize -cell $_SDFFE_PP1P_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_SDFFE_PP1P_ 1
+equiv_opt -assert -multiclock dfflegalize -cell $_SDFFCE_PP0P_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_SDFFCE_PP0P_ 1
+equiv_opt -assert -multiclock dfflegalize -cell $_SDFFCE_PP1P_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_SDFFCE_PP1P_ 1
+
+# Convert everything to DFFs.
+
+design -load orig
+dfflegalize -cell $_DFF_P_ 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:$_DFF_P_
+select -assert-none t:$_DFF_P_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFF_P_ 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:$_DFF_P_
+select -assert-none t:$_DFF_P_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to DFFEs.
+
+design -load orig
+dfflegalize -cell $_DFFE_PP_ 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:$_DFFE_PP_
+select -assert-none t:$_DFFE_PP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFFE_PP_ 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:$_DFFE_PP_
+select -assert-none t:$_DFFE_PP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to ADFFs.
+
+design -load orig
+dfflegalize -cell $_DFF_PP0_ 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:$_DFF_PP0_
+select -assert-none t:$_DFF_PP0_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFF_PP0_ 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:$_DFF_PP0_
+select -assert-none t:$_DFF_PP0_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFF_PP1_ 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:$_DFF_PP1_
+select -assert-none t:$_DFF_PP1_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFF_PP1_ 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:$_DFF_PP1_
+select -assert-none t:$_DFF_PP1_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to ADFFEs.
+
+design -load orig
+dfflegalize -cell $_DFFE_PP0P_ 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:$_DFFE_PP0P_
+select -assert-none t:$_DFFE_PP0P_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFFE_PP0P_ 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:$_DFFE_PP0P_
+select -assert-none t:$_DFFE_PP0P_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFFE_PP1P_ 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:$_DFFE_PP1P_
+select -assert-none t:$_DFFE_PP1P_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFFE_PP1P_ 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:$_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
+dfflegalize -cell $_DFFSR_PPP_ 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:$_DFFSR_PPP_
+select -assert-none t:$_DFFSR_PPP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFFSR_PPP_ 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:$_DFFSR_PPP_
+select -assert-none t:$_DFFSR_PPP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to DFFSREs.
+
+design -load orig
+dfflegalize -cell $_DFFSRE_PPPP_ 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:$_DFFSRE_PPPP_
+select -assert-none t:$_DFFSRE_PPPP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFFSRE_PPPP_ 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:$_DFFSRE_PPPP_
+select -assert-none t:$_DFFSRE_PPPP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to SDFFs.
+
+design -load orig
+dfflegalize -cell $_SDFF_PP0_ 0
+
+select -assert-count 1 dff/t:$_NOT_
+select -assert-count 1 dffe/t:$_NOT_
+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 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 3 sdff1/t:$_MUX_
+select -assert-count 4 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:$_SDFF_PP0_
+select -assert-none t:$_SDFF_PP0_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_SDFF_PP0_ 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 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 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 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 8 sdffce1/t:$_MUX_
+select -assert-count 27 t:$_SDFF_PP0_
+select -assert-none t:$_SDFF_PP0_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_SDFF_PP1_ 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 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 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 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 8 sdffce1/t:$_MUX_
+select -assert-count 27 t:$_SDFF_PP1_
+select -assert-none t:$_SDFF_PP1_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_SDFF_PP1_ 1
+
+select -assert-count 5 dff/t:$_NOT_
+select -assert-count 7 dffe/t:$_NOT_
+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 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 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 8 sdffce0/t:$_MUX_
+select -assert-count 8 sdffce1/t:$_MUX_
+select -assert-count 27 t:$_SDFF_PP1_
+select -assert-none t:$_SDFF_PP1_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to SDFFEs.
+
+design -load orig
+dfflegalize -cell $_SDFFE_PP0P_ 0
+
+select -assert-count 1 dff/t:$_NOT_
+select -assert-count 2 dffe/t:$_NOT_
+select -assert-count 2 sdff0/t:$_NOT_
+select -assert-count 1 sdff1/t:$_NOT_
+select -assert-count 3 sdffe0/t:$_NOT_
+select -assert-count 1 sdffe1/t:$_NOT_
+select -assert-count 3 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 0 sdff0/t:$_MUX_
+select -assert-count 3 sdff1/t:$_MUX_
+select -assert-count 0 sdffe0/t:$_MUX_
+select -assert-count 8 sdffe1/t:$_MUX_
+select -assert-count 0 sdffce0/t:$_MUX_
+select -assert-count 4 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:$_SDFFE_PP0P_
+select -assert-none t:$_SDFFE_PP0P_ t:$_NOT_ t:$_MUX_ t:$_AND_ t:$_ORNOT_ t:$_ANDNOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_SDFFE_PP0P_ 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 8 sdff1/t:$_NOT_
+select -assert-count 9 sdffe0/t:$_NOT_
+select -assert-count 11 sdffe1/t:$_NOT_
+select -assert-count 10 sdffce0/t:$_NOT_
+select -assert-count 11 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 0 sdff1/t:$_MUX_
+select -assert-count 8 sdffe0/t:$_MUX_
+select -assert-count 0 sdffe1/t:$_MUX_
+select -assert-count 4 sdffce0/t:$_MUX_
+select -assert-count 0 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 27 t:$_SDFFE_PP0P_
+select -assert-none t:$_SDFFE_PP0P_ t:$_NOT_ t:$_MUX_ t:$_AND_ t:$_ORNOT_ t:$_ANDNOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_SDFFE_PP1P_ 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 2 sdff1/t:$_NOT_
+select -assert-count 1 sdffe0/t:$_NOT_
+select -assert-count 3 sdffe1/t:$_NOT_
+select -assert-count 2 sdffce0/t:$_NOT_
+select -assert-count 3 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 0 sdff1/t:$_MUX_
+select -assert-count 8 sdffe0/t:$_MUX_
+select -assert-count 0 sdffe1/t:$_MUX_
+select -assert-count 4 sdffce0/t:$_MUX_
+select -assert-count 0 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 27 t:$_SDFFE_PP1P_
+select -assert-none t:$_SDFFE_PP1P_ t:$_NOT_ t:$_MUX_ t:$_AND_ t:$_ORNOT_ t:$_ANDNOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_SDFFE_PP1P_ 1
+
+select -assert-count 5 dff/t:$_NOT_
+select -assert-count 8 dffe/t:$_NOT_
+select -assert-count 8 sdff0/t:$_NOT_
+select -assert-count 7 sdff1/t:$_NOT_
+select -assert-count 11 sdffe0/t:$_NOT_
+select -assert-count 9 sdffe1/t:$_NOT_
+select -assert-count 11 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 0 sdff0/t:$_MUX_
+select -assert-count 3 sdff1/t:$_MUX_
+select -assert-count 0 sdffe0/t:$_MUX_
+select -assert-count 8 sdffe1/t:$_MUX_
+select -assert-count 0 sdffce0/t:$_MUX_
+select -assert-count 4 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:$_SDFFE_PP1P_
+select -assert-none t:$_SDFFE_PP1P_ t:$_NOT_ t:$_MUX_ t:$_AND_ t:$_ORNOT_ t:$_ANDNOT_ top/* %% %n t:* %i
+
+
+# Convert everything to SDFFCEs.
+
+design -load orig
+dfflegalize -cell $_SDFFCE_PP0P_ 0
+
+select -assert-count 1 dff/t:$_NOT_
+select -assert-count 2 dffe/t:$_NOT_
+select -assert-count 2 sdff0/t:$_NOT_
+select -assert-count 1 sdff1/t:$_NOT_
+select -assert-count 3 sdffe0/t:$_NOT_
+select -assert-count 1 sdffe1/t:$_NOT_
+select -assert-count 3 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 0 sdff0/t:$_MUX_
+select -assert-count 3 sdff1/t:$_MUX_
+select -assert-count 0 sdffe0/t:$_MUX_
+select -assert-count 8 sdffe1/t:$_MUX_
+select -assert-count 0 sdffce0/t:$_MUX_
+select -assert-count 4 sdffce1/t:$_MUX_
+select -assert-count 0 t:$_OR_ t:$_ORNOT_ t:$_ANDNOT_ %% sdffe0/* %n %i
+select -assert-count 2 sdffe0/t:$_OR_
+select -assert-count 1 sdffe0/t:$_ORNOT_
+select -assert-count 1 sdffe0/t:$_ANDNOT_
+select -assert-count 27 t:$_SDFFCE_PP0P_
+select -assert-none t:$_SDFFCE_PP0P_ t:$_NOT_ t:$_MUX_ t:$_OR_ t:$_ORNOT_ t:$_ANDNOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_SDFFCE_PP0P_ 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 8 sdff1/t:$_NOT_
+select -assert-count 9 sdffe0/t:$_NOT_
+select -assert-count 11 sdffe1/t:$_NOT_
+select -assert-count 10 sdffce0/t:$_NOT_
+select -assert-count 11 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 0 sdff1/t:$_MUX_
+select -assert-count 8 sdffe0/t:$_MUX_
+select -assert-count 0 sdffe1/t:$_MUX_
+select -assert-count 4 sdffce0/t:$_MUX_
+select -assert-count 0 sdffce1/t:$_MUX_
+select -assert-count 0 t:$_OR_ t:$_ORNOT_ t:$_ANDNOT_ %% sdffe1/* %n %i
+select -assert-count 2 sdffe1/t:$_OR_
+select -assert-count 1 sdffe1/t:$_ORNOT_
+select -assert-count 1 sdffe1/t:$_ANDNOT_
+select -assert-count 27 t:$_SDFFCE_PP0P_
+select -assert-none t:$_SDFFCE_PP0P_ t:$_NOT_ t:$_MUX_ t:$_OR_ t:$_ORNOT_ t:$_ANDNOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_SDFFCE_PP1P_ 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 2 sdff1/t:$_NOT_
+select -assert-count 1 sdffe0/t:$_NOT_
+select -assert-count 3 sdffe1/t:$_NOT_
+select -assert-count 2 sdffce0/t:$_NOT_
+select -assert-count 3 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 0 sdff1/t:$_MUX_
+select -assert-count 8 sdffe0/t:$_MUX_
+select -assert-count 0 sdffe1/t:$_MUX_
+select -assert-count 4 sdffce0/t:$_MUX_
+select -assert-count 0 sdffce1/t:$_MUX_
+select -assert-count 0 t:$_OR_ t:$_ORNOT_ t:$_ANDNOT_ %% sdffe1/* %n %i
+select -assert-count 2 sdffe1/t:$_OR_
+select -assert-count 1 sdffe1/t:$_ORNOT_
+select -assert-count 1 sdffe1/t:$_ANDNOT_
+select -assert-count 27 t:$_SDFFCE_PP1P_
+select -assert-none t:$_SDFFCE_PP1P_ t:$_NOT_ t:$_MUX_ t:$_OR_ t:$_ORNOT_ t:$_ANDNOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_SDFFCE_PP1P_ 1
+
+select -assert-count 5 dff/t:$_NOT_
+select -assert-count 8 dffe/t:$_NOT_
+select -assert-count 8 sdff0/t:$_NOT_
+select -assert-count 7 sdff1/t:$_NOT_
+select -assert-count 11 sdffe0/t:$_NOT_
+select -assert-count 9 sdffe1/t:$_NOT_
+select -assert-count 11 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 0 sdff0/t:$_MUX_
+select -assert-count 3 sdff1/t:$_MUX_
+select -assert-count 0 sdffe0/t:$_MUX_
+select -assert-count 8 sdffe1/t:$_MUX_
+select -assert-count 0 sdffce0/t:$_MUX_
+select -assert-count 4 sdffce1/t:$_MUX_
+select -assert-count 0 t:$_OR_ t:$_ORNOT_ t:$_ANDNOT_ %% sdffe0/* %n %i
+select -assert-count 2 sdffe0/t:$_OR_
+select -assert-count 1 sdffe0/t:$_ORNOT_
+select -assert-count 1 sdffe0/t:$_ANDNOT_
+select -assert-count 27 t:$_SDFFCE_PP1P_
+select -assert-none t:$_SDFFCE_PP1P_ t:$_NOT_ t:$_MUX_ t:$_OR_ t:$_ORNOT_ t:$_ANDNOT_ top/* %% %n t:* %i
diff --git a/tests/techmap/dfflegalize_dffsr.ys b/tests/techmap/dfflegalize_dffsr.ys
new file mode 100644
index 000000000..49a7237a2
--- /dev/null
+++ b/tests/techmap/dfflegalize_dffsr.ys
@@ -0,0 +1,88 @@
+read_verilog -icells <<EOT
+
+module dffsr(input C, R, S, D, output [3:0] Q);
+$_DFFSR_PPP_ ff0 (.C(C), .R(R), .S(S), .D(D), .Q(Q[0]));
+$_DFFSR_PPN_ ff1 (.C(C), .R(R), .S(S), .D(D), .Q(Q[1]));
+$_DFFSR_PNP_ ff2 (.C(C), .R(R), .S(S), .D(D), .Q(Q[2]));
+$_DFFSR_NPP_ ff3 (.C(C), .R(R), .S(S), .D(D), .Q(Q[3]));
+endmodule
+
+module dffsre(input C, R, S, E, D, output [4:0] Q);
+$_DFFSRE_PPPP_ ff0 (.C(C), .R(R), .S(S), .E(E), .D(D), .Q(Q[0]));
+$_DFFSRE_PPPN_ ff1 (.C(C), .R(R), .S(S), .E(E), .D(D), .Q(Q[1]));
+$_DFFSRE_PPNP_ ff2 (.C(C), .R(R), .S(S), .E(E), .D(D), .Q(Q[2]));
+$_DFFSRE_PNPP_ ff3 (.C(C), .R(R), .S(S), .E(E), .D(D), .Q(Q[3]));
+$_DFFSRE_NPPP_ ff4 (.C(C), .R(R), .S(S), .E(E), .D(D), .Q(Q[4]));
+endmodule
+
+module top(input C, E, R, S, D, output [8:0] Q);
+dffsr dffsr_(.C(C), .R(R), .S(S), .D(D), .Q(Q[3:0]));
+dffsre dffsre_(.C(C), .R(R), .S(S), .E(E), .D(D), .Q(Q[8:4]));
+endmodule
+
+EOT
+
+design -save orig
+flatten
+equiv_opt -assert -multiclock dfflegalize -cell $_DFF_PP0_ x -cell $_SR_PP_ x
+equiv_opt -assert -multiclock dfflegalize -cell $_DFFE_PP0P_ x -cell $_SR_PP_ x
+equiv_opt -assert -multiclock dfflegalize -cell $_DFFSR_PPP_ x
+equiv_opt -assert -multiclock dfflegalize -cell $_DFFSRE_PPPP_ x
+
+
+# Convert everything to ADFFs.
+
+design -load orig
+dfflegalize -cell $_DFF_PP0_ x -cell $_SR_PP_ x
+
+select -assert-count 14 dffsr/t:$_NOT_
+select -assert-count 16 dffsre/t:$_NOT_
+select -assert-count 4 dffsr/t:$_MUX_
+select -assert-count 10 dffsre/t:$_MUX_
+select -assert-count 8 dffsr/t:$_DFF_PP0_
+select -assert-count 10 dffsre/t:$_DFF_PP0_
+select -assert-count 4 dffsr/t:$_SR_PP_
+select -assert-count 5 dffsre/t:$_SR_PP_
+select -assert-none t:$_DFF_PP0_ t:$_SR_PP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to ADFFEs.
+
+design -load orig
+dfflegalize -cell $_DFFE_PP0P_ x -cell $_SR_PP_ x
+
+select -assert-count 14 dffsr/t:$_NOT_
+select -assert-count 18 dffsre/t:$_NOT_
+select -assert-count 4 dffsr/t:$_MUX_
+select -assert-count 5 dffsre/t:$_MUX_
+select -assert-count 8 dffsr/t:$_DFFE_PP0P_
+select -assert-count 10 dffsre/t:$_DFFE_PP0P_
+select -assert-count 4 dffsr/t:$_SR_PP_
+select -assert-count 5 dffsre/t:$_SR_PP_
+select -assert-none t:$_DFFE_PP0P_ t:$_SR_PP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to DFFSRs.
+
+design -load orig
+dfflegalize -cell $_DFFSR_PPP_ x
+
+select -assert-count 3 dffsr/t:$_NOT_
+select -assert-count 3 dffsre/t:$_NOT_
+select -assert-count 0 dffsr/t:$_MUX_
+select -assert-count 5 dffsre/t:$_MUX_
+select -assert-count 4 dffsr/t:$_DFFSR_PPP_
+select -assert-count 5 dffsre/t:$_DFFSR_PPP_
+select -assert-none t:$_DFFSR_PPP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to DFFSREs.
+
+design -load orig
+dfflegalize -cell $_DFFSRE_PPPP_ x
+
+select -assert-count 3 dffsr/t:$_NOT_
+select -assert-count 4 dffsre/t:$_NOT_
+select -assert-count 4 dffsr/t:$_DFFSRE_PPPP_
+select -assert-count 5 dffsre/t:$_DFFSRE_PPPP_
+select -assert-none t:$_DFFSRE_PPPP_ t:$_NOT_ top/* %% %n t:* %i
diff --git a/tests/techmap/dfflegalize_dffsr_init.ys b/tests/techmap/dfflegalize_dffsr_init.ys
new file mode 100644
index 000000000..ce5a32f76
--- /dev/null
+++ b/tests/techmap/dfflegalize_dffsr_init.ys
@@ -0,0 +1,379 @@
+read_verilog -icells <<EOT
+
+module dffsr0(input C, R, S, D, (* init = 4'h0 *) output [3:0] Q);
+$_DFFSR_PPP_ ff0 (.C(C), .R(R), .S(S), .D(D), .Q(Q[0]));
+$_DFFSR_PPN_ ff1 (.C(C), .R(R), .S(S), .D(D), .Q(Q[1]));
+$_DFFSR_PNP_ ff2 (.C(C), .R(R), .S(S), .D(D), .Q(Q[2]));
+$_DFFSR_NPP_ ff3 (.C(C), .R(R), .S(S), .D(D), .Q(Q[3]));
+endmodule
+
+module dffsr1(input C, R, S, D, (* init = 4'hf *) output [3:0] Q);
+$_DFFSR_PPP_ ff0 (.C(C), .R(R), .S(S), .D(D), .Q(Q[0]));
+$_DFFSR_PPN_ ff1 (.C(C), .R(R), .S(S), .D(D), .Q(Q[1]));
+$_DFFSR_PNP_ ff2 (.C(C), .R(R), .S(S), .D(D), .Q(Q[2]));
+$_DFFSR_NPP_ ff3 (.C(C), .R(R), .S(S), .D(D), .Q(Q[3]));
+endmodule
+
+module dffsre0(input C, R, S, E, D, (* init = 5'h0 *) output [4:0] Q);
+$_DFFSRE_PPPP_ ff0 (.C(C), .R(R), .S(S), .E(E), .D(D), .Q(Q[0]));
+$_DFFSRE_PPPN_ ff1 (.C(C), .R(R), .S(S), .E(E), .D(D), .Q(Q[1]));
+$_DFFSRE_PPNP_ ff2 (.C(C), .R(R), .S(S), .E(E), .D(D), .Q(Q[2]));
+$_DFFSRE_PNPP_ ff3 (.C(C), .R(R), .S(S), .E(E), .D(D), .Q(Q[3]));
+$_DFFSRE_NPPP_ ff4 (.C(C), .R(R), .S(S), .E(E), .D(D), .Q(Q[4]));
+endmodule
+
+module dffsre1(input C, R, S, E, D, (* init = 5'h1f *) output [4:0] Q);
+$_DFFSRE_PPPP_ ff0 (.C(C), .R(R), .S(S), .E(E), .D(D), .Q(Q[0]));
+$_DFFSRE_PPPN_ ff1 (.C(C), .R(R), .S(S), .E(E), .D(D), .Q(Q[1]));
+$_DFFSRE_PPNP_ ff2 (.C(C), .R(R), .S(S), .E(E), .D(D), .Q(Q[2]));
+$_DFFSRE_PNPP_ ff3 (.C(C), .R(R), .S(S), .E(E), .D(D), .Q(Q[3]));
+$_DFFSRE_NPPP_ ff4 (.C(C), .R(R), .S(S), .E(E), .D(D), .Q(Q[4]));
+endmodule
+
+module top(input C, E, R, S, D, output [17:0] Q);
+dffsr0 dffsr0_(.C(C), .R(R), .S(S), .D(D), .Q(Q[3:0]));
+dffsr1 dffsr1_(.C(C), .R(R), .S(S), .D(D), .Q(Q[7:4]));
+dffsre0 dffsre0_(.C(C), .R(R), .S(S), .E(E), .D(D), .Q(Q[12:8]));
+dffsre1 dffsre1_(.C(C), .R(R), .S(S), .E(E), .D(D), .Q(Q[17:13]));
+endmodule
+
+EOT
+
+design -save orig
+flatten
+#equiv_opt -assert -multiclock dfflegalize -cell $_DFF_PP0_ 0 -cell $_SR_PP_ 0
+#equiv_opt -assert -multiclock dfflegalize -cell $_DFF_PP0_ 1 -cell $_SR_PP_ 0
+#equiv_opt -assert -multiclock dfflegalize -cell $_DFF_PP1_ 0 -cell $_SR_PP_ 0
+#equiv_opt -assert -multiclock dfflegalize -cell $_DFF_PP1_ 1 -cell $_SR_PP_ 0
+#equiv_opt -assert -multiclock dfflegalize -cell $_DFFE_PP0P_ 0 -cell $_SR_PP_ 0
+#equiv_opt -assert -multiclock dfflegalize -cell $_DFFE_PP0P_ 1 -cell $_SR_PP_ 0
+#equiv_opt -assert -multiclock dfflegalize -cell $_DFFE_PP1P_ 0 -cell $_SR_PP_ 0
+#equiv_opt -assert -multiclock dfflegalize -cell $_DFFE_PP1P_ 1 -cell $_SR_PP_ 0
+#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 ADFFs.
+
+design -load orig
+dfflegalize -cell $_DFF_PP0_ 0 -cell $_SR_PP_ 0
+
+select -assert-count 14 dffsr0/t:$_NOT_
+select -assert-count 18 dffsr1/t:$_NOT_
+select -assert-count 16 dffsre0/t:$_NOT_
+select -assert-count 21 dffsre1/t:$_NOT_
+select -assert-count 4 dffsr0/t:$_MUX_
+select -assert-count 4 dffsr1/t:$_MUX_
+select -assert-count 10 dffsre0/t:$_MUX_
+select -assert-count 10 dffsre1/t:$_MUX_
+select -assert-count 8 dffsr0/t:$_DFF_PP0_
+select -assert-count 8 dffsr1/t:$_DFF_PP0_
+select -assert-count 10 dffsre0/t:$_DFF_PP0_
+select -assert-count 10 dffsre1/t:$_DFF_PP0_
+select -assert-count 4 dffsr0/t:$_SR_PP_
+select -assert-count 4 dffsr1/t:$_SR_PP_
+select -assert-count 5 dffsre0/t:$_SR_PP_
+select -assert-count 5 dffsre1/t:$_SR_PP_
+select -assert-count 1 dffsr1/t:$_AND_
+select -assert-count 2 dffsr1/t:$_ANDNOT_
+select -assert-count 1 dffsr1/t:$_OR_
+select -assert-count 1 dffsre1/t:$_AND_
+select -assert-count 3 dffsre1/t:$_ANDNOT_
+select -assert-count 1 dffsre1/t:$_OR_
+select -assert-count 0 t:$_AND_ t:$_OR_ t:$_ANDNOT_ %% dffsr1/* dffsre1/* %u %n %i
+select -assert-none t:$_DFF_PP0_ t:$_SR_PP_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_OR_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFF_PP0_ 1 -cell $_SR_PP_ 0
+
+select -assert-count 18 dffsr0/t:$_NOT_
+select -assert-count 14 dffsr1/t:$_NOT_
+select -assert-count 21 dffsre0/t:$_NOT_
+select -assert-count 16 dffsre1/t:$_NOT_
+select -assert-count 4 dffsr0/t:$_MUX_
+select -assert-count 4 dffsr1/t:$_MUX_
+select -assert-count 10 dffsre0/t:$_MUX_
+select -assert-count 10 dffsre1/t:$_MUX_
+select -assert-count 8 dffsr0/t:$_DFF_PP0_
+select -assert-count 8 dffsr1/t:$_DFF_PP0_
+select -assert-count 10 dffsre0/t:$_DFF_PP0_
+select -assert-count 10 dffsre1/t:$_DFF_PP0_
+select -assert-count 4 dffsr0/t:$_SR_PP_
+select -assert-count 4 dffsr1/t:$_SR_PP_
+select -assert-count 5 dffsre0/t:$_SR_PP_
+select -assert-count 5 dffsre1/t:$_SR_PP_
+select -assert-count 1 dffsr0/t:$_AND_
+select -assert-count 2 dffsr0/t:$_ANDNOT_
+select -assert-count 1 dffsr0/t:$_OR_
+select -assert-count 1 dffsre0/t:$_AND_
+select -assert-count 3 dffsre0/t:$_ANDNOT_
+select -assert-count 1 dffsre0/t:$_OR_
+select -assert-count 0 t:$_AND_ t:$_OR_ t:$_ANDNOT_ %% dffsr0/* dffsre0/* %u %n %i
+select -assert-none t:$_DFF_PP0_ t:$_SR_PP_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_OR_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFF_PP1_ 0 -cell $_SR_PP_ 0
+
+select -assert-count 18 dffsr0/t:$_NOT_
+select -assert-count 14 dffsr1/t:$_NOT_
+select -assert-count 21 dffsre0/t:$_NOT_
+select -assert-count 16 dffsre1/t:$_NOT_
+select -assert-count 4 dffsr0/t:$_MUX_
+select -assert-count 4 dffsr1/t:$_MUX_
+select -assert-count 10 dffsre0/t:$_MUX_
+select -assert-count 10 dffsre1/t:$_MUX_
+select -assert-count 8 dffsr0/t:$_DFF_PP1_
+select -assert-count 8 dffsr1/t:$_DFF_PP1_
+select -assert-count 10 dffsre0/t:$_DFF_PP1_
+select -assert-count 10 dffsre1/t:$_DFF_PP1_
+select -assert-count 4 dffsr0/t:$_SR_PP_
+select -assert-count 4 dffsr1/t:$_SR_PP_
+select -assert-count 5 dffsre0/t:$_SR_PP_
+select -assert-count 5 dffsre1/t:$_SR_PP_
+select -assert-count 1 dffsr0/t:$_AND_
+select -assert-count 2 dffsr0/t:$_ANDNOT_
+select -assert-count 1 dffsr0/t:$_OR_
+select -assert-count 1 dffsre0/t:$_AND_
+select -assert-count 3 dffsre0/t:$_ANDNOT_
+select -assert-count 1 dffsre0/t:$_OR_
+select -assert-count 0 t:$_AND_ t:$_OR_ t:$_ANDNOT_ %% dffsr0/* dffsre0/* %u %n %i
+select -assert-none t:$_DFF_PP1_ t:$_SR_PP_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_OR_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFF_PP1_ 1 -cell $_SR_PP_ 0
+
+select -assert-count 14 dffsr0/t:$_NOT_
+select -assert-count 18 dffsr1/t:$_NOT_
+select -assert-count 16 dffsre0/t:$_NOT_
+select -assert-count 21 dffsre1/t:$_NOT_
+select -assert-count 4 dffsr0/t:$_MUX_
+select -assert-count 4 dffsr1/t:$_MUX_
+select -assert-count 10 dffsre0/t:$_MUX_
+select -assert-count 10 dffsre1/t:$_MUX_
+select -assert-count 8 dffsr0/t:$_DFF_PP1_
+select -assert-count 8 dffsr1/t:$_DFF_PP1_
+select -assert-count 10 dffsre0/t:$_DFF_PP1_
+select -assert-count 10 dffsre1/t:$_DFF_PP1_
+select -assert-count 4 dffsr0/t:$_SR_PP_
+select -assert-count 4 dffsr1/t:$_SR_PP_
+select -assert-count 5 dffsre0/t:$_SR_PP_
+select -assert-count 5 dffsre1/t:$_SR_PP_
+select -assert-count 1 dffsr1/t:$_AND_
+select -assert-count 2 dffsr1/t:$_ANDNOT_
+select -assert-count 1 dffsr1/t:$_OR_
+select -assert-count 1 dffsre1/t:$_AND_
+select -assert-count 3 dffsre1/t:$_ANDNOT_
+select -assert-count 1 dffsre1/t:$_OR_
+select -assert-count 0 t:$_AND_ t:$_OR_ t:$_ANDNOT_ %% dffsr1/* dffsre1/* %u %n %i
+select -assert-none t:$_DFF_PP1_ t:$_SR_PP_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_OR_ top/* %% %n t:* %i
+
+
+# Convert everything to ADFFEs.
+
+design -load orig
+dfflegalize -cell $_DFFE_PP0P_ 0 -cell $_SR_PP_ 1
+
+select -assert-count 18 dffsr0/t:$_NOT_
+select -assert-count 14 dffsr1/t:$_NOT_
+select -assert-count 23 dffsre0/t:$_NOT_
+select -assert-count 18 dffsre1/t:$_NOT_
+select -assert-count 4 dffsr0/t:$_MUX_
+select -assert-count 4 dffsr1/t:$_MUX_
+select -assert-count 5 dffsre0/t:$_MUX_
+select -assert-count 5 dffsre1/t:$_MUX_
+select -assert-count 8 dffsr0/t:$_DFFE_PP0P_
+select -assert-count 8 dffsr1/t:$_DFFE_PP0P_
+select -assert-count 10 dffsre0/t:$_DFFE_PP0P_
+select -assert-count 10 dffsre1/t:$_DFFE_PP0P_
+select -assert-count 4 dffsr0/t:$_SR_PP_
+select -assert-count 4 dffsr1/t:$_SR_PP_
+select -assert-count 5 dffsre0/t:$_SR_PP_
+select -assert-count 5 dffsre1/t:$_SR_PP_
+select -assert-count 1 dffsr0/t:$_AND_
+select -assert-count 2 dffsr0/t:$_ANDNOT_
+select -assert-count 1 dffsr0/t:$_OR_
+select -assert-count 1 dffsre0/t:$_AND_
+select -assert-count 3 dffsre0/t:$_ANDNOT_
+select -assert-count 1 dffsre0/t:$_OR_
+select -assert-count 0 t:$_AND_ t:$_OR_ t:$_ANDNOT_ %% dffsr0/* dffsre0/* %u %n %i
+select -assert-none t:$_DFFE_PP0P_ t:$_SR_PP_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_OR_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFFE_PP0P_ 1 -cell $_SR_PP_ 1
+
+select -assert-count 14 dffsr0/t:$_NOT_
+select -assert-count 18 dffsr1/t:$_NOT_
+select -assert-count 18 dffsre0/t:$_NOT_
+select -assert-count 23 dffsre1/t:$_NOT_
+select -assert-count 4 dffsr0/t:$_MUX_
+select -assert-count 4 dffsr1/t:$_MUX_
+select -assert-count 5 dffsre0/t:$_MUX_
+select -assert-count 5 dffsre1/t:$_MUX_
+select -assert-count 8 dffsr0/t:$_DFFE_PP0P_
+select -assert-count 8 dffsr1/t:$_DFFE_PP0P_
+select -assert-count 10 dffsre0/t:$_DFFE_PP0P_
+select -assert-count 10 dffsre1/t:$_DFFE_PP0P_
+select -assert-count 4 dffsr0/t:$_SR_PP_
+select -assert-count 4 dffsr1/t:$_SR_PP_
+select -assert-count 5 dffsre0/t:$_SR_PP_
+select -assert-count 5 dffsre1/t:$_SR_PP_
+select -assert-count 1 dffsr1/t:$_AND_
+select -assert-count 2 dffsr1/t:$_ANDNOT_
+select -assert-count 1 dffsr1/t:$_OR_
+select -assert-count 1 dffsre1/t:$_AND_
+select -assert-count 3 dffsre1/t:$_ANDNOT_
+select -assert-count 1 dffsre1/t:$_OR_
+select -assert-count 0 t:$_AND_ t:$_OR_ t:$_ANDNOT_ %% dffsr1/* dffsre1/* %u %n %i
+select -assert-none t:$_DFFE_PP0P_ t:$_SR_PP_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_OR_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFFE_PP1P_ 0 -cell $_SR_PP_ 1
+
+select -assert-count 14 dffsr0/t:$_NOT_
+select -assert-count 18 dffsr1/t:$_NOT_
+select -assert-count 18 dffsre0/t:$_NOT_
+select -assert-count 23 dffsre1/t:$_NOT_
+select -assert-count 4 dffsr0/t:$_MUX_
+select -assert-count 4 dffsr1/t:$_MUX_
+select -assert-count 5 dffsre0/t:$_MUX_
+select -assert-count 5 dffsre1/t:$_MUX_
+select -assert-count 8 dffsr0/t:$_DFFE_PP1P_
+select -assert-count 8 dffsr1/t:$_DFFE_PP1P_
+select -assert-count 10 dffsre0/t:$_DFFE_PP1P_
+select -assert-count 10 dffsre1/t:$_DFFE_PP1P_
+select -assert-count 4 dffsr0/t:$_SR_PP_
+select -assert-count 4 dffsr1/t:$_SR_PP_
+select -assert-count 5 dffsre0/t:$_SR_PP_
+select -assert-count 5 dffsre1/t:$_SR_PP_
+select -assert-count 1 dffsr1/t:$_AND_
+select -assert-count 2 dffsr1/t:$_ANDNOT_
+select -assert-count 1 dffsr1/t:$_OR_
+select -assert-count 1 dffsre1/t:$_AND_
+select -assert-count 3 dffsre1/t:$_ANDNOT_
+select -assert-count 1 dffsre1/t:$_OR_
+select -assert-count 0 t:$_AND_ t:$_OR_ t:$_ANDNOT_ %% dffsr1/* dffsre1/* %u %n %i
+select -assert-none t:$_DFFE_PP1P_ t:$_SR_PP_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_OR_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFFE_PP1P_ 1 -cell $_SR_PP_ 1
+
+select -assert-count 18 dffsr0/t:$_NOT_
+select -assert-count 14 dffsr1/t:$_NOT_
+select -assert-count 23 dffsre0/t:$_NOT_
+select -assert-count 18 dffsre1/t:$_NOT_
+select -assert-count 4 dffsr0/t:$_MUX_
+select -assert-count 4 dffsr1/t:$_MUX_
+select -assert-count 5 dffsre0/t:$_MUX_
+select -assert-count 5 dffsre1/t:$_MUX_
+select -assert-count 8 dffsr0/t:$_DFFE_PP1P_
+select -assert-count 8 dffsr1/t:$_DFFE_PP1P_
+select -assert-count 10 dffsre0/t:$_DFFE_PP1P_
+select -assert-count 10 dffsre1/t:$_DFFE_PP1P_
+select -assert-count 4 dffsr0/t:$_SR_PP_
+select -assert-count 4 dffsr1/t:$_SR_PP_
+select -assert-count 5 dffsre0/t:$_SR_PP_
+select -assert-count 5 dffsre1/t:$_SR_PP_
+select -assert-count 1 dffsr0/t:$_AND_
+select -assert-count 2 dffsr0/t:$_ANDNOT_
+select -assert-count 1 dffsr0/t:$_OR_
+select -assert-count 1 dffsre0/t:$_AND_
+select -assert-count 3 dffsre0/t:$_ANDNOT_
+select -assert-count 1 dffsre0/t:$_OR_
+select -assert-count 0 t:$_AND_ t:$_OR_ t:$_ANDNOT_ %% dffsr0/* dffsre0/* %u %n %i
+select -assert-none t:$_DFFE_PP1P_ t:$_SR_PP_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_OR_ top/* %% %n t:* %i
+
+
+# Convert everything to DFFSRs.
+
+design -load orig
+dfflegalize -cell $_DFFSR_PPP_ 0
+
+select -assert-count 3 dffsr0/t:$_NOT_
+select -assert-count 11 dffsr1/t:$_NOT_
+select -assert-count 3 dffsre0/t:$_NOT_
+select -assert-count 13 dffsre1/t:$_NOT_
+select -assert-count 0 dffsr0/t:$_MUX_
+select -assert-count 0 dffsr1/t:$_MUX_
+select -assert-count 5 dffsre0/t:$_MUX_
+select -assert-count 5 dffsre1/t:$_MUX_
+select -assert-count 4 dffsr0/t:$_DFFSR_PPP_
+select -assert-count 4 dffsr1/t:$_DFFSR_PPP_
+select -assert-count 5 dffsre0/t:$_DFFSR_PPP_
+select -assert-count 5 dffsre1/t:$_DFFSR_PPP_
+select -assert-count 1 dffsr1/t:$_AND_
+select -assert-count 2 dffsr1/t:$_ANDNOT_
+select -assert-count 1 dffsr1/t:$_OR_
+select -assert-count 1 dffsre1/t:$_AND_
+select -assert-count 3 dffsre1/t:$_ANDNOT_
+select -assert-count 1 dffsre1/t:$_OR_
+select -assert-count 0 t:$_AND_ t:$_OR_ t:$_ANDNOT_ %% dffsr1/* dffsre1/* %u %n %i
+select -assert-none t:$_DFFSR_PPP_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_OR_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFFSR_PPP_ 1
+
+select -assert-count 11 dffsr0/t:$_NOT_
+select -assert-count 3 dffsr1/t:$_NOT_
+select -assert-count 13 dffsre0/t:$_NOT_
+select -assert-count 3 dffsre1/t:$_NOT_
+select -assert-count 0 dffsr0/t:$_MUX_
+select -assert-count 0 dffsr1j/t:$_MUX_
+select -assert-count 5 dffsre0/t:$_MUX_
+select -assert-count 5 dffsre1/t:$_MUX_
+select -assert-count 4 dffsr0/t:$_DFFSR_PPP_
+select -assert-count 4 dffsr1/t:$_DFFSR_PPP_
+select -assert-count 5 dffsre0/t:$_DFFSR_PPP_
+select -assert-count 5 dffsre1/t:$_DFFSR_PPP_
+select -assert-count 1 dffsr0/t:$_AND_
+select -assert-count 2 dffsr0/t:$_ANDNOT_
+select -assert-count 1 dffsr0/t:$_OR_
+select -assert-count 1 dffsre0/t:$_AND_
+select -assert-count 3 dffsre0/t:$_ANDNOT_
+select -assert-count 1 dffsre0/t:$_OR_
+select -assert-count 0 t:$_AND_ t:$_OR_ t:$_ANDNOT_ %% dffsr0/* dffsre0/* %u %n %i
+select -assert-none t:$_DFFSR_PPP_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_OR_ top/* %% %n t:* %i
+
+
+# Convert everything to DFFSREs.
+
+design -load orig
+dfflegalize -cell $_DFFSRE_PPPP_ 0
+
+select -assert-count 3 dffsr0/t:$_NOT_
+select -assert-count 11 dffsr1/t:$_NOT_
+select -assert-count 4 dffsre0/t:$_NOT_
+select -assert-count 14 dffsre1/t:$_NOT_
+select -assert-count 4 dffsr0/t:$_DFFSRE_PPPP_
+select -assert-count 4 dffsr1/t:$_DFFSRE_PPPP_
+select -assert-count 5 dffsre0/t:$_DFFSRE_PPPP_
+select -assert-count 5 dffsre1/t:$_DFFSRE_PPPP_
+select -assert-count 1 dffsr1/t:$_AND_
+select -assert-count 2 dffsr1/t:$_ANDNOT_
+select -assert-count 1 dffsr1/t:$_OR_
+select -assert-count 1 dffsre1/t:$_AND_
+select -assert-count 3 dffsre1/t:$_ANDNOT_
+select -assert-count 1 dffsre1/t:$_OR_
+select -assert-count 0 t:$_AND_ t:$_OR_ t:$_ANDNOT_ %% dffsr1/* dffsre1/* %u %n %i
+select -assert-none t:$_DFFSRE_PPPP_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_OR_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFFSRE_PPPP_ 1
+
+select -assert-count 11 dffsr0/t:$_NOT_
+select -assert-count 3 dffsr1/t:$_NOT_
+select -assert-count 14 dffsre0/t:$_NOT_
+select -assert-count 4 dffsre1/t:$_NOT_
+select -assert-count 4 dffsr0/t:$_DFFSRE_PPPP_
+select -assert-count 4 dffsr1/t:$_DFFSRE_PPPP_
+select -assert-count 5 dffsre0/t:$_DFFSRE_PPPP_
+select -assert-count 5 dffsre1/t:$_DFFSRE_PPPP_
+select -assert-count 1 dffsr0/t:$_AND_
+select -assert-count 2 dffsr0/t:$_ANDNOT_
+select -assert-count 1 dffsr0/t:$_OR_
+select -assert-count 1 dffsre0/t:$_AND_
+select -assert-count 3 dffsre0/t:$_ANDNOT_
+select -assert-count 1 dffsre0/t:$_OR_
+select -assert-count 0 t:$_AND_ t:$_OR_ t:$_ANDNOT_ %% dffsr0/* dffsre0/* %u %n %i
+select -assert-none t:$_DFFSRE_PPPP_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_OR_ top/* %% %n t:* %i
diff --git a/tests/techmap/dfflegalize_dlatch.ys b/tests/techmap/dfflegalize_dlatch.ys
new file mode 100644
index 000000000..11683bc1a
--- /dev/null
+++ b/tests/techmap/dfflegalize_dlatch.ys
@@ -0,0 +1,64 @@
+read_verilog -icells <<EOT
+
+module dlatch(input E, D, output [1:0] Q);
+$_DLATCH_P_ ff0 (.E(E), .D(D), .Q(Q[0]));
+$_DLATCH_N_ ff1 (.E(E), .D(D), .Q(Q[1]));
+endmodule
+
+EOT
+
+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.
+
+design -load orig
+dfflegalize -cell $_DLATCH_P_ x
+
+select -assert-count 1 t:$_NOT_
+select -assert-count 2 t:$_DLATCH_P_
+select -assert-none t:$_DLATCH_P_ t:$_NOT_ %% %n t:* %i
+
+
+# Convert everything to ADLATCHs.
+
+design -load orig
+dfflegalize -cell $_DLATCH_PP0_ x
+
+select -assert-count 1 t:$_NOT_
+select -assert-count 2 t:$_DLATCH_PP0_
+select -assert-none t:$_DLATCH_PP0_ t:$_NOT_ %% %n t:* %i
+
+
+# Convert everything to DLATCHSRs.
+
+design -load orig
+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
new file mode 100644
index 000000000..159692249
--- /dev/null
+++ b/tests/techmap/dfflegalize_dlatch_const.ys
@@ -0,0 +1,53 @@
+read_verilog -icells <<EOT
+
+module dlatch(input E, D, (* init = 8'hf0 *) output [7:0] Q);
+$_DLATCH_P_ ff0 (.E(E), .D(1'b0), .Q(Q[0]));
+$_DLATCH_N_ ff1 (.E(E), .D(1'b0), .Q(Q[1]));
+$_DLATCH_P_ ff2 (.E(E), .D(1'b1), .Q(Q[2]));
+$_DLATCH_N_ ff3 (.E(E), .D(1'b1), .Q(Q[3]));
+$_DLATCH_P_ ff4 (.E(E), .D(1'b0), .Q(Q[4]));
+$_DLATCH_N_ ff5 (.E(E), .D(1'b0), .Q(Q[5]));
+$_DLATCH_P_ ff6 (.E(E), .D(1'b1), .Q(Q[6]));
+$_DLATCH_N_ ff7 (.E(E), .D(1'b1), .Q(Q[7]));
+endmodule
+
+EOT
+
+design -save orig
+equiv_opt -assert -multiclock dfflegalize -cell $_DFF_PP0_ 01
+equiv_opt -assert -multiclock dfflegalize -cell $_DFF_PP?_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_DFFSRE_PPPP_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_DFFSRE_PPPP_ 1
+
+# Convert everything to ADFFs.
+
+design -load orig
+dfflegalize -cell $_DFF_PP0_ 01
+
+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 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
+
+# Convert everything to DFFSREs.
+
+design -load orig
+dfflegalize -cell $_DFFSRE_PPPP_ 0
+
+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 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
new file mode 100644
index 000000000..9324c6691
--- /dev/null
+++ b/tests/techmap/dfflegalize_dlatch_init.ys
@@ -0,0 +1,120 @@
+read_verilog -icells <<EOT
+
+module dlatch(input E, D, (* init = 2'h0 *) output [1:0] Q);
+$_DLATCH_P_ ff0 (.E(E), .D(D), .Q(Q[0]));
+$_DLATCH_N_ ff1 (.E(E), .D(D), .Q(Q[1]));
+endmodule
+
+EOT
+
+design -save orig
+equiv_opt -assert -multiclock dfflegalize -cell $_DLATCH_P_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_DLATCH_P_ 1
+equiv_opt -assert -multiclock dfflegalize -cell $_DLATCH_PP0_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_DLATCH_PP0_ 1
+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.
+
+design -load orig
+dfflegalize -cell $_DLATCH_P_ 0
+
+select -assert-count 1 t:$_NOT_
+select -assert-count 2 t:$_DLATCH_P_
+select -assert-none t:$_DLATCH_P_ t:$_NOT_ %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DLATCH_P_ 1
+
+select -assert-count 5 t:$_NOT_
+select -assert-count 2 t:$_DLATCH_P_
+select -assert-none t:$_DLATCH_P_ t:$_NOT_ %% %n t:* %i
+
+
+# Convert everything to ADLATCHs.
+
+design -load orig
+dfflegalize -cell $_DLATCH_PP0_ 0
+
+select -assert-count 1 t:$_NOT_
+select -assert-count 2 t:$_DLATCH_PP0_
+select -assert-none t:$_DLATCH_PP0_ t:$_NOT_ %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DLATCH_PP0_ 1
+
+select -assert-count 5 t:$_NOT_
+select -assert-count 2 t:$_DLATCH_PP0_
+select -assert-none t:$_DLATCH_PP0_ t:$_NOT_ %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DLATCH_PP1_ 0
+
+select -assert-count 1 t:$_NOT_
+select -assert-count 2 t:$_DLATCH_PP1_
+select -assert-none t:$_DLATCH_PP1_ t:$_NOT_ %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DLATCH_PP1_ 1
+
+select -assert-count 5 t:$_NOT_
+select -assert-count 2 t:$_DLATCH_PP1_
+select -assert-none t:$_DLATCH_PP1_ t:$_NOT_ %% %n t:* %i
+
+
+# Convert everything to DLATCHSRs.
+
+design -load orig
+dfflegalize -cell $_DLATCHSR_PPP_ 0
+
+select -assert-count 1 t:$_NOT_
+select -assert-count 2 t:$_DLATCHSR_PPP_
+select -assert-none t:$_DLATCHSR_PPP_ t:$_NOT_ %% %n t:* %i
+
+design -load orig
+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.ys b/tests/techmap/dfflegalize_dlatchsr.ys
new file mode 100644
index 000000000..53d910723
--- /dev/null
+++ b/tests/techmap/dfflegalize_dlatchsr.ys
@@ -0,0 +1,37 @@
+read_verilog -icells <<EOT
+
+module dlatchsr(input E, R, S, D, output [3:0] Q);
+$_DLATCHSR_PPP_ ff0 (.E(E), .R(R), .S(S), .D(D), .Q(Q[0]));
+$_DLATCHSR_PPN_ ff1 (.E(E), .R(R), .S(S), .D(D), .Q(Q[1]));
+$_DLATCHSR_PNP_ ff2 (.E(E), .R(R), .S(S), .D(D), .Q(Q[2]));
+$_DLATCHSR_NPP_ ff3 (.E(E), .R(R), .S(S), .D(D), .Q(Q[3]));
+endmodule
+
+EOT
+
+design -save orig
+equiv_opt -assert -multiclock dfflegalize -cell $_DLATCH_PP0_ x -cell $_SR_PP_ x
+equiv_opt -assert -multiclock dfflegalize -cell $_DLATCHSR_PPP_ x
+
+
+# Convert everything to ADLATCHs.
+
+design -load orig
+dfflegalize -cell $_DLATCH_PP0_ x -cell $_SR_PP_ x
+
+select -assert-count 14 t:$_NOT_
+select -assert-count 4 t:$_MUX_
+select -assert-count 8 t:$_DLATCH_PP0_
+select -assert-count 4 t:$_SR_PP_
+select -assert-none t:$_DLATCH_PP0_ t:$_SR_PP_ t:$_MUX_ t:$_NOT_ %% %n t:* %i
+
+
+# Convert everything to DLATCHSRs.
+
+design -load orig
+dfflegalize -cell $_DLATCHSR_PPP_ x
+
+select -assert-count 3 t:$_NOT_
+select -assert-count 0 t:$_MUX_
+select -assert-count 4 t:$_DLATCHSR_PPP_
+select -assert-none t:$_DLATCHSR_PPP_ t:$_MUX_ t:$_NOT_ %% %n t:* %i
diff --git a/tests/techmap/dfflegalize_dlatchsr_init.ys b/tests/techmap/dfflegalize_dlatchsr_init.ys
new file mode 100644
index 000000000..b38a9eb3b
--- /dev/null
+++ b/tests/techmap/dfflegalize_dlatchsr_init.ys
@@ -0,0 +1,127 @@
+read_verilog -icells <<EOT
+
+module dlatchsr0(input E, R, S, D, (* init = 4'h0 *) output [3:0] Q);
+$_DLATCHSR_PPP_ ff0 (.E(E), .R(R), .S(S), .D(D), .Q(Q[0]));
+$_DLATCHSR_PPN_ ff1 (.E(E), .R(R), .S(S), .D(D), .Q(Q[1]));
+$_DLATCHSR_PNP_ ff2 (.E(E), .R(R), .S(S), .D(D), .Q(Q[2]));
+$_DLATCHSR_NPP_ ff3 (.E(E), .R(R), .S(S), .D(D), .Q(Q[3]));
+endmodule
+
+module dlatchsr1(input E, R, S, D, (* init = 4'hf *) output [3:0] Q);
+$_DLATCHSR_PPP_ ff0 (.E(E), .R(R), .S(S), .D(D), .Q(Q[0]));
+$_DLATCHSR_PPN_ ff1 (.E(E), .R(R), .S(S), .D(D), .Q(Q[1]));
+$_DLATCHSR_PNP_ ff2 (.E(E), .R(R), .S(S), .D(D), .Q(Q[2]));
+$_DLATCHSR_NPP_ ff3 (.E(E), .R(R), .S(S), .D(D), .Q(Q[3]));
+endmodule
+
+module top(input C, E, R, S, D, output [17:0] Q);
+dlatchsr0 dlatchsr0_(.E(E), .R(R), .S(S), .D(D), .Q(Q[3:0]));
+dlatchsr1 dlatchsr1_(.E(E), .R(R), .S(S), .D(D), .Q(Q[7:4]));
+endmodule
+
+EOT
+
+design -save orig
+flatten
+#equiv_opt -assert -multiclock dfflegalize -cell $_DLATCH_PP0_ 0
+#equiv_opt -assert -multiclock dfflegalize -cell $_DLATCH_PP0_ 1
+#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
+
+
+# Convert everything to ADLATCHs.
+
+design -load orig
+dfflegalize -cell $_DLATCH_PP0_ 0
+
+select -assert-count 14 dlatchsr0/t:$_NOT_
+select -assert-count 18 dlatchsr1/t:$_NOT_
+select -assert-count 4 dlatchsr0/t:$_MUX_
+select -assert-count 4 dlatchsr1/t:$_MUX_
+select -assert-count 12 dlatchsr0/t:$_DLATCH_PP0_
+select -assert-count 12 dlatchsr1/t:$_DLATCH_PP0_
+select -assert-count 1 dlatchsr1/t:$_AND_
+select -assert-count 2 dlatchsr1/t:$_ANDNOT_
+select -assert-count 1 dlatchsr1/t:$_OR_
+select -assert-count 0 t:$_AND_ t:$_OR_ t:$_ANDNOT_ %% dlatchsr1/* %n %i
+select -assert-none t:$_DLATCH_PP0_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_OR_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DLATCH_PP0_ 1
+
+select -assert-count 14 dlatchsr0/t:$_NOT_
+select -assert-count 18 dlatchsr1/t:$_NOT_
+select -assert-count 4 dlatchsr0/t:$_MUX_
+select -assert-count 4 dlatchsr1/t:$_MUX_
+select -assert-count 12 dlatchsr0/t:$_DLATCH_PP0_
+select -assert-count 12 dlatchsr1/t:$_DLATCH_PP0_
+select -assert-count 1 dlatchsr1/t:$_AND_
+select -assert-count 2 dlatchsr1/t:$_ANDNOT_
+select -assert-count 1 dlatchsr1/t:$_OR_
+select -assert-count 0 t:$_AND_ t:$_OR_ t:$_ANDNOT_ %% dlatchsr1/* %n %i
+select -assert-none t:$_DLATCH_PP0_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_OR_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DLATCH_PP1_ 0
+
+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_
+select -assert-count 12 dlatchsr1/t:$_DLATCH_PP1_
+select -assert-count 1 dlatchsr1/t:$_AND_
+select -assert-count 2 dlatchsr1/t:$_ANDNOT_
+select -assert-count 1 dlatchsr1/t:$_OR_
+select -assert-count 0 t:$_AND_ t:$_OR_ t:$_ANDNOT_ %% dlatchsr1/* %n %i
+select -assert-none t:$_DLATCH_PP1_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_OR_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DLATCH_PP1_ 1
+
+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_
+select -assert-count 12 dlatchsr1/t:$_DLATCH_PP1_
+select -assert-count 1 dlatchsr1/t:$_AND_
+select -assert-count 2 dlatchsr1/t:$_ANDNOT_
+select -assert-count 1 dlatchsr1/t:$_OR_
+select -assert-count 0 t:$_AND_ t:$_OR_ t:$_ANDNOT_ %% dlatchsr1/* %n %i
+select -assert-none t:$_DLATCH_PP1_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_OR_ top/* %% %n t:* %i
+
+
+# Convert everything to DLATCHSRs.
+
+design -load orig
+dfflegalize -cell $_DLATCHSR_PPP_ 0
+
+select -assert-count 3 dlatchsr0/t:$_NOT_
+select -assert-count 11 dlatchsr1/t:$_NOT_
+select -assert-count 0 dlatchsr0/t:$_MUX_
+select -assert-count 0 dlatchsr1/t:$_MUX_
+select -assert-count 4 dlatchsr0/t:$_DLATCHSR_PPP_
+select -assert-count 4 dlatchsr1/t:$_DLATCHSR_PPP_
+select -assert-count 1 dlatchsr1/t:$_AND_
+select -assert-count 2 dlatchsr1/t:$_ANDNOT_
+select -assert-count 1 dlatchsr1/t:$_OR_
+select -assert-count 0 t:$_AND_ t:$_OR_ t:$_ANDNOT_ %% dlatchsr1/* %n %i
+select -assert-none t:$_DLATCHSR_PPP_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_OR_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DLATCHSR_PPP_ 1
+
+select -assert-count 11 dlatchsr0/t:$_NOT_
+select -assert-count 3 dlatchsr1/t:$_NOT_
+select -assert-count 0 dlatchsr0/t:$_MUX_
+select -assert-count 0 dlatchsr1j/t:$_MUX_
+select -assert-count 4 dlatchsr0/t:$_DLATCHSR_PPP_
+select -assert-count 4 dlatchsr1/t:$_DLATCHSR_PPP_
+select -assert-count 1 dlatchsr0/t:$_AND_
+select -assert-count 2 dlatchsr0/t:$_ANDNOT_
+select -assert-count 1 dlatchsr0/t:$_OR_
+select -assert-count 0 t:$_AND_ t:$_OR_ t:$_ANDNOT_ %% dlatchsr0/* %n %i
+select -assert-none t:$_DLATCHSR_PPP_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_OR_ top/* %% %n t:* %i
diff --git a/tests/techmap/dfflegalize_inv.ys b/tests/techmap/dfflegalize_inv.ys
new file mode 100644
index 000000000..a74d74161
--- /dev/null
+++ b/tests/techmap/dfflegalize_inv.ys
@@ -0,0 +1,191 @@
+# Base test: make sure inverters are applied correctly.
+
+read_verilog -icells <<EOT
+
+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]));
+
+$_DFFE_PP_ ff2 (.C(C), .E(E), .D(D), .Q(Q[2]));
+$_DFFE_PN_ ff3 (.C(C), .E(E), .D(D), .Q(Q[3]));
+$_DFFE_NP_ ff4 (.C(C), .E(E), .D(D), .Q(Q[4]));
+
+$_DFF_PP0_ ff5 (.C(C), .R(R), .D(D), .Q(Q[5]));
+$_DFF_PN0_ ff6 (.C(C), .R(R), .D(D), .Q(Q[6]));
+$_DFF_NP0_ ff7 (.C(C), .R(R), .D(D), .Q(Q[7]));
+
+$_DFF_PP1_ ff8 (.C(C), .R(R), .D(D), .Q(Q[8]));
+$_DFF_PN1_ ff9 (.C(C), .R(R), .D(D), .Q(Q[9]));
+$_DFF_NP1_ ff10 (.C(C), .R(R), .D(D), .Q(Q[10]));
+
+$_DFFE_PP0P_ ff11 (.C(C), .R(R), .E(E), .D(D), .Q(Q[11]));
+$_DFFE_PP0N_ ff12 (.C(C), .R(R), .E(E), .D(D), .Q(Q[12]));
+$_DFFE_PN0P_ ff13 (.C(C), .R(R), .E(E), .D(D), .Q(Q[13]));
+$_DFFE_NP0P_ ff14 (.C(C), .R(R), .E(E), .D(D), .Q(Q[14]));
+
+$_DFFE_PP1P_ ff15 (.C(C), .R(R), .E(E), .D(D), .Q(Q[15]));
+$_DFFE_PP1N_ ff16 (.C(C), .R(R), .E(E), .D(D), .Q(Q[16]));
+$_DFFE_PN1P_ ff17 (.C(C), .R(R), .E(E), .D(D), .Q(Q[17]));
+$_DFFE_NP1P_ ff18 (.C(C), .R(R), .E(E), .D(D), .Q(Q[18]));
+
+$_DFFSR_PPP_ ff19 (.C(C), .R(R), .S(S), .D(D), .Q(Q[19]));
+$_DFFSR_PPN_ ff20 (.C(C), .R(R), .S(S), .D(D), .Q(Q[20]));
+$_DFFSR_PNP_ ff21 (.C(C), .R(R), .S(S), .D(D), .Q(Q[21]));
+$_DFFSR_NPP_ ff22 (.C(C), .R(R), .S(S), .D(D), .Q(Q[22]));
+
+$_DFFSRE_PPPP_ ff23 (.C(C), .R(R), .S(S), .E(E), .D(D), .Q(Q[23]));
+$_DFFSRE_PPPN_ ff24 (.C(C), .R(R), .S(S), .E(E), .D(D), .Q(Q[24]));
+$_DFFSRE_PPNP_ ff25 (.C(C), .R(R), .S(S), .E(E), .D(D), .Q(Q[25]));
+$_DFFSRE_PNPP_ ff26 (.C(C), .R(R), .S(S), .E(E), .D(D), .Q(Q[26]));
+$_DFFSRE_NPPP_ ff27 (.C(C), .R(R), .S(S), .E(E), .D(D), .Q(Q[27]));
+
+$_SDFF_PP0_ ff28 (.C(C), .R(R), .D(D), .Q(Q[28]));
+$_SDFF_PN0_ ff29 (.C(C), .R(R), .D(D), .Q(Q[29]));
+$_SDFF_NP0_ ff30 (.C(C), .R(R), .D(D), .Q(Q[30]));
+
+$_SDFF_PP1_ ff31 (.C(C), .R(R), .D(D), .Q(Q[31]));
+$_SDFF_PN1_ ff32 (.C(C), .R(R), .D(D), .Q(Q[32]));
+$_SDFF_NP1_ ff33 (.C(C), .R(R), .D(D), .Q(Q[33]));
+
+$_SDFFE_PP0P_ ff34 (.C(C), .R(R), .E(E), .D(D), .Q(Q[34]));
+$_SDFFE_PP0N_ ff35 (.C(C), .R(R), .E(E), .D(D), .Q(Q[35]));
+$_SDFFE_PN0P_ ff36 (.C(C), .R(R), .E(E), .D(D), .Q(Q[36]));
+$_SDFFE_NP0P_ ff37 (.C(C), .R(R), .E(E), .D(D), .Q(Q[37]));
+
+$_SDFFE_PP1P_ ff38 (.C(C), .R(R), .E(E), .D(D), .Q(Q[38]));
+$_SDFFE_PP1N_ ff39 (.C(C), .R(R), .E(E), .D(D), .Q(Q[39]));
+$_SDFFE_PN1P_ ff40 (.C(C), .R(R), .E(E), .D(D), .Q(Q[40]));
+$_SDFFE_NP1P_ ff41 (.C(C), .R(R), .E(E), .D(D), .Q(Q[41]));
+
+$_SDFFCE_PP0P_ ff42 (.C(C), .R(R), .E(E), .D(D), .Q(Q[42]));
+$_SDFFCE_PP0N_ ff43 (.C(C), .R(R), .E(E), .D(D), .Q(Q[43]));
+$_SDFFCE_PN0P_ ff44 (.C(C), .R(R), .E(E), .D(D), .Q(Q[44]));
+$_SDFFCE_NP0P_ ff45 (.C(C), .R(R), .E(E), .D(D), .Q(Q[45]));
+
+$_SDFFCE_PP1P_ ff46 (.C(C), .R(R), .E(E), .D(D), .Q(Q[46]));
+$_SDFFCE_PP1N_ ff47 (.C(C), .R(R), .E(E), .D(D), .Q(Q[47]));
+$_SDFFCE_PN1P_ ff48 (.C(C), .R(R), .E(E), .D(D), .Q(Q[48]));
+$_SDFFCE_NP1P_ ff49 (.C(C), .R(R), .E(E), .D(D), .Q(Q[49]));
+
+$_DLATCH_P_ ff50 (.E(E), .D(D), .Q(Q[50]));
+$_DLATCH_N_ ff51 (.E(E), .D(D), .Q(Q[51]));
+
+$_DLATCH_PP0_ ff52 (.E(E), .R(R), .D(D), .Q(Q[52]));
+$_DLATCH_PN0_ ff53 (.E(E), .R(R), .D(D), .Q(Q[53]));
+$_DLATCH_NP0_ ff54 (.E(E), .R(R), .D(D), .Q(Q[54]));
+
+$_DLATCH_PP1_ ff55 (.E(E), .R(R), .D(D), .Q(Q[55]));
+$_DLATCH_PN1_ ff56 (.E(E), .R(R), .D(D), .Q(Q[56]));
+$_DLATCH_NP1_ ff57 (.E(E), .R(R), .D(D), .Q(Q[57]));
+
+$_DLATCHSR_PPP_ ff58 (.E(E), .R(R), .S(S), .D(D), .Q(Q[58]));
+$_DLATCHSR_PPN_ ff59 (.E(E), .R(R), .S(S), .D(D), .Q(Q[59]));
+$_DLATCHSR_PNP_ ff60 (.E(E), .R(R), .S(S), .D(D), .Q(Q[60]));
+$_DLATCHSR_NPP_ ff61 (.E(E), .R(R), .S(S), .D(D), .Q(Q[61]));
+
+$_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 -cell $_ALDFF_PP_ x -cell $_ALDFFE_PPP_ x
+design -load postopt
+
+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_
+select -assert-count 3 t:$_DFF_PP1_
+select -assert-count 4 t:$_DFFE_PP0P_
+select -assert-count 4 t:$_DFFE_PP1P_
+select -assert-count 4 t:$_DFFSR_PPP_
+select -assert-count 5 t:$_DFFSRE_PPPP_
+select -assert-count 3 t:$_SDFF_PP0_
+select -assert-count 3 t:$_SDFF_PP1_
+select -assert-count 4 t:$_SDFFE_PP0P_
+select -assert-count 4 t:$_SDFFE_PP1P_
+select -assert-count 4 t:$_SDFFCE_PP0P_
+select -assert-count 4 t:$_SDFFCE_PP1P_
+select -assert-count 2 t:$_DLATCH_P_
+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-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 -cell $_ALDFF_NN_ x -cell $_ALDFFE_NNN_ x
+design -load postopt
+
+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_
+select -assert-count 3 t:$_DFF_NN1_
+select -assert-count 4 t:$_DFFE_NN0N_
+select -assert-count 4 t:$_DFFE_NN1N_
+select -assert-count 4 t:$_DFFSR_NNN_
+select -assert-count 5 t:$_DFFSRE_NNNN_
+select -assert-count 3 t:$_SDFF_NN0_
+select -assert-count 3 t:$_SDFF_NN1_
+select -assert-count 4 t:$_SDFFE_NN0N_
+select -assert-count 4 t:$_SDFFE_NN1N_
+select -assert-count 4 t:$_SDFFCE_NN0N_
+select -assert-count 4 t:$_SDFFCE_NN1N_
+select -assert-count 2 t:$_DLATCH_N_
+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-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.
+
+design -reset
+
+read_verilog -icells <<EOT
+
+module top(input C, E, R, S, D, output [3:0] Q);
+
+$_DFFSRE_PPPP_ ff0 (.C(C), .E(E), .R(R), .S(S), .D(D), .Q(Q[0]));
+$_DFFSRE_NPPP_ ff1 (.C(C), .E(E), .R(R), .S(S), .D(D), .Q(Q[1]));
+$_DFFSRE_PNNN_ ff2 (.C(C), .E(E), .R(R), .S(S), .D(D), .Q(Q[2]));
+$_DFFSRE_NNNN_ ff3 (.C(C), .E(E), .R(R), .S(S), .D(D), .Q(Q[3]));
+
+endmodule
+
+EOT
+
+equiv_opt -assert -multiclock dfflegalize -cell $_DFFSRE_NNNN_ x -cell $_DFFSRE_PPPP_ x
+design -load postopt
+
+select -assert-count 6 t:$_NOT_
+select -assert-count 2 t:$_DFFSRE_PPPP_
+select -assert-count 2 t:$_DFFSRE_NNNN_
+select -assert-count 1 t:$_DFFSRE_PPPP_ n:ff0 %i
+select -assert-count 1 t:$_DFFSRE_NNNN_ n:ff1 %i
+select -assert-count 1 t:$_DFFSRE_PPPP_ n:ff2 %i
+select -assert-count 1 t:$_DFFSRE_NNNN_ n:ff3 %i
diff --git a/tests/techmap/dfflegalize_mince.ys b/tests/techmap/dfflegalize_mince.ys
new file mode 100644
index 000000000..31c8d04fc
--- /dev/null
+++ b/tests/techmap/dfflegalize_mince.ys
@@ -0,0 +1,53 @@
+read_verilog -icells <<EOT
+
+module top(input D, C, R, S, input [4:0] E, output [15:0] Q);
+$_DFFE_PP_ ff0(.D(D), .C(C), .E(E[0]), .Q(Q[0]));
+$_DFFE_PP0P_ ff1(.D(D), .C(C), .E(E[0]), .R(R), .Q(Q[1]));
+$_DFFE_PP1P_ ff2(.D(D), .C(C), .E(E[0]), .R(R), .Q(Q[2]));
+$_SDFFE_PP0P_ ff3(.D(D), .C(C), .E(E[0]), .R(R), .Q(Q[3]));
+$_SDFFE_PP1P_ ff4(.D(D), .C(C), .E(E[0]), .R(R), .Q(Q[4]));
+$_SDFFCE_PP0P_ ff5(.D(D), .C(C), .E(E[0]), .R(R), .Q(Q[5]));
+$_SDFFCE_PP1P_ ff6(.D(D), .C(C), .E(E[0]), .R(R), .Q(Q[6]));
+$_DFFSRE_PPPP_ ff7(.D(D), .C(C), .E(E[0]), .R(R), .S(S), .Q(Q[7]));
+$_DFFE_PP_ ff8(.D(D), .C(C), .E(E[1]), .Q(Q[8]));
+$_DFFE_PP0P_ ff9(.D(D), .C(C), .E(E[1]), .R(R), .Q(Q[9]));
+$_DFFE_PP1P_ ff10(.D(D), .C(C), .E(E[2]), .R(R), .Q(Q[10]));
+$_SDFFE_PP0P_ ff11(.D(D), .C(C), .E(E[2]), .R(R), .Q(Q[11]));
+$_SDFFE_PP1P_ ff12(.D(D), .C(C), .E(E[3]), .R(R), .Q(Q[12]));
+$_SDFFCE_PP0P_ ff13(.D(D), .C(C), .E(E[3]), .R(R), .Q(Q[13]));
+$_SDFFCE_PP1P_ ff14(.D(D), .C(C), .E(E[4]), .R(R), .Q(Q[14]));
+$_DFFSRE_PPPP_ ff15(.D(D), .C(C), .E(E[4]), .R(R), .S(S), .Q(Q[15]));
+endmodule
+
+EOT
+
+design -save orig
+equiv_opt -assert -multiclock dfflegalize -cell $_DFFE_PP_ x -cell $_DFFE_PP?P_ x -cell $_DFFSRE_PPPP_ x -cell $_SDFFE_PP?P_ x -cell $_SDFFCE_PP?P_ x -mince 3
+design -load postopt
+
+select -assert-count 4 t:$_DFFE_PP_
+select -assert-count 2 t:$_DFFE_PP0P_
+select -assert-count 2 t:$_DFFE_PP1P_
+select -assert-count 2 t:$_SDFFE_PP0P_
+select -assert-count 2 t:$_SDFFE_PP1P_
+select -assert-count 1 t:$_SDFFCE_PP0P_
+select -assert-count 1 t:$_SDFFCE_PP1P_
+select -assert-count 2 t:$_DFFSRE_PPPP_
+select -assert-count 10 t:$_MUX_
+select -assert-count 0 n:ff0 %ci %ci t:$_MUX_ %i
+select -assert-count 0 n:ff1 %ci %ci t:$_MUX_ %i
+select -assert-count 0 n:ff2 %ci %ci t:$_MUX_ %i
+select -assert-count 0 n:ff3 %ci %ci t:$_MUX_ %i
+select -assert-count 0 n:ff4 %ci %ci t:$_MUX_ %i
+select -assert-count 0 n:ff5 %ci %ci t:$_MUX_ %i
+select -assert-count 0 n:ff6 %ci %ci t:$_MUX_ %i
+select -assert-count 0 n:ff7 %ci %ci t:$_MUX_ %i
+select -assert-count 1 n:ff8 %ci %ci t:$_MUX_ %i
+select -assert-count 1 n:ff9 %ci %ci t:$_MUX_ %i
+select -assert-count 1 n:ff10 %ci %ci t:$_MUX_ %i
+select -assert-count 1 n:ff11 %ci %ci t:$_MUX_ %i
+select -assert-count 1 n:ff12 %ci %ci t:$_MUX_ %i
+select -assert-count 1 n:ff13 %ci %ci t:$_MUX_ %i
+select -assert-count 1 n:ff14 %ci %ci t:$_MUX_ %i
+select -assert-count 1 n:ff15 %ci %ci t:$_MUX_ %i
+select -assert-none n:ff* t:$_MUX_ %% %n t:* %i
diff --git a/tests/techmap/dfflegalize_minsrst.ys b/tests/techmap/dfflegalize_minsrst.ys
new file mode 100644
index 000000000..689066147
--- /dev/null
+++ b/tests/techmap/dfflegalize_minsrst.ys
@@ -0,0 +1,43 @@
+read_verilog -icells <<EOT
+
+module top(input D, C, E, input [3:0] R, output [11:0] Q);
+$_SDFF_PP0_ ff0(.D(D), .C(C), .R(R[0]), .Q(Q[0]));
+$_SDFF_PP1_ ff1(.D(D), .C(C), .R(R[0]), .Q(Q[1]));
+$_SDFFE_PP0P_ ff2(.D(D), .C(C), .R(R[0]), .E(E), .Q(Q[2]));
+$_SDFFE_PP1P_ ff3(.D(D), .C(C), .R(R[0]), .E(E), .Q(Q[3]));
+$_SDFFCE_PP0P_ ff4(.D(D), .C(C), .R(R[0]), .E(E), .Q(Q[4]));
+$_SDFFCE_PP1P_ ff5(.D(D), .C(C), .R(R[0]), .E(E), .Q(Q[5]));
+$_SDFF_PP0_ ff6(.D(D), .C(C), .R(R[1]), .Q(Q[6]));
+$_SDFF_PP1_ ff7(.D(D), .C(C), .R(R[1]), .Q(Q[7]));
+$_SDFFE_PP0P_ ff8(.D(D), .C(C), .R(R[2]), .E(E), .Q(Q[8]));
+$_SDFFE_PP1P_ ff9(.D(D), .C(C), .R(R[2]), .E(E), .Q(Q[9]));
+$_SDFFCE_PP0P_ ff10(.D(D), .C(C), .R(R[3]), .E(E), .Q(Q[10]));
+$_SDFFCE_PP1P_ ff11(.D(D), .C(C), .R(R[3]), .E(E), .Q(Q[11]));
+endmodule
+
+EOT
+
+design -save orig
+equiv_opt -assert -multiclock dfflegalize -cell $_SDFF_PP?_ x -cell $_SDFFE_PP?P_ x -cell $_SDFFCE_PP?P_ x -minsrst 3
+design -load postopt
+
+select -assert-count 5 t:$_SDFF_PP0_
+select -assert-count 1 t:$_SDFF_PP1_
+select -assert-count 1 t:$_SDFFE_PP0P_
+select -assert-count 1 t:$_SDFFE_PP1P_
+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
+select -assert-count 0 n:ff1 %ci %ci t:$_MUX_ %i
+select -assert-count 0 n:ff2 %ci %ci t:$_MUX_ %i
+select -assert-count 0 n:ff3 %ci %ci t:$_MUX_ %i
+select -assert-count 0 n:ff4 %ci %ci t:$_MUX_ %i
+select -assert-count 0 n:ff5 %ci %ci t:$_MUX_ %i
+select -assert-count 1 n:ff6 %ci %ci t:$_MUX_ %i
+select -assert-count 1 n:ff7 %ci %ci t:$_MUX_ %i
+select -assert-count 1 n:ff8 %ci %ci t:$_MUX_ %i
+select -assert-count 1 n:ff9 %ci %ci t:$_MUX_ %i
+select -assert-count 1 n:ff10 %ci %ci t:$_MUX_ %i
+select -assert-count 1 n:ff11 %ci %ci t:$_MUX_ %i
+select -assert-none n:ff* t:$_MUX_ %% %n t:* %i
diff --git a/tests/techmap/dfflegalize_sr.ys b/tests/techmap/dfflegalize_sr.ys
new file mode 100644
index 000000000..ee59a6e3c
--- /dev/null
+++ b/tests/techmap/dfflegalize_sr.ys
@@ -0,0 +1,74 @@
+read_verilog -icells <<EOT
+
+module sr(input R, S, output [2:0] Q);
+$_SR_PP_ ff0 (.R(R), .S(S), .Q(Q[0]));
+$_SR_PN_ ff1 (.R(R), .S(S), .Q(Q[1]));
+$_SR_NP_ ff2 (.R(R), .S(S), .Q(Q[2]));
+endmodule
+
+EOT
+
+design -save orig
+equiv_opt -assert -multiclock dfflegalize -cell $_SR_PP_ x
+equiv_opt -assert -multiclock dfflegalize -cell $_DLATCH_PP0_ x
+equiv_opt -assert -multiclock dfflegalize -cell $_DLATCH_PP1_ x
+equiv_opt -assert -multiclock dfflegalize -cell $_DLATCHSR_PPP_ x
+equiv_opt -assert -multiclock dfflegalize -cell $_DFFSR_PPP_ x
+equiv_opt -assert -multiclock dfflegalize -cell $_DFFSRE_PPPP_ x
+
+
+# Convert everything to SRs.
+
+design -load orig
+dfflegalize -cell $_SR_PP_ x
+
+select -assert-count 2 t:$_NOT_
+select -assert-count 3 t:$_SR_PP_
+select -assert-none t:$_SR_PP_ t:$_NOT_ %% %n t:* %i
+
+
+# Convert everything to ADLATCHs.
+
+design -load orig
+dfflegalize -cell $_DLATCH_PP0_ x
+
+select -assert-count 2 t:$_NOT_
+select -assert-count 3 t:$_DLATCH_PP0_
+select -assert-none t:$_DLATCH_PP0_ t:$_NOT_ %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DLATCH_PP1_ x
+
+select -assert-count 5 t:$_NOT_
+select -assert-count 3 t:$_DLATCH_PP1_
+select -assert-none t:$_DLATCH_PP1_ t:$_NOT_ %% %n t:* %i
+
+
+# Convert everything to DLATCHSRs.
+
+design -load orig
+dfflegalize -cell $_DLATCHSR_PPP_ x
+
+select -assert-count 2 t:$_NOT_
+select -assert-count 3 t:$_DLATCHSR_PPP_
+select -assert-none t:$_DLATCHSR_PPP_ t:$_NOT_ %% %n t:* %i
+
+
+# Convert everything to DFFSRs.
+
+design -load orig
+dfflegalize -cell $_DFFSR_PPP_ x
+
+select -assert-count 2 t:$_NOT_
+select -assert-count 3 t:$_DFFSR_PPP_
+select -assert-none t:$_DFFSR_PPP_ t:$_NOT_ %% %n t:* %i
+
+
+# Convert everything to DFFSREs.
+
+design -load orig
+dfflegalize -cell $_DFFSRE_PPPP_ x
+
+select -assert-count 2 t:$_NOT_
+select -assert-count 3 t:$_DFFSRE_PPPP_
+select -assert-none t:$_DFFSRE_PPPP_ t:$_NOT_ %% %n t:* %i
diff --git a/tests/techmap/dfflegalize_sr_init.ys b/tests/techmap/dfflegalize_sr_init.ys
new file mode 100644
index 000000000..9d724de29
--- /dev/null
+++ b/tests/techmap/dfflegalize_sr_init.ys
@@ -0,0 +1,230 @@
+read_verilog -icells <<EOT
+
+module sr0(input R, S, (* init = 3'h0 *) output [2:0] Q);
+$_SR_PP_ ff0 (.R(R), .S(S), .Q(Q[0]));
+$_SR_PN_ ff1 (.R(R), .S(S), .Q(Q[1]));
+$_SR_NP_ ff2 (.R(R), .S(S), .Q(Q[2]));
+endmodule
+
+module sr1(input R, S, (* init = 3'h7 *) output [2:0] Q);
+$_SR_PP_ ff0 (.R(R), .S(S), .Q(Q[0]));
+$_SR_PN_ ff1 (.R(R), .S(S), .Q(Q[1]));
+$_SR_NP_ ff2 (.R(R), .S(S), .Q(Q[2]));
+endmodule
+
+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
+
+EOT
+
+design -save orig
+flatten
+#equiv_opt -assert -multiclock dfflegalize -cell $_SR_PP_ 0
+#equiv_opt -assert -multiclock dfflegalize -cell $_SR_PP_ 1
+#equiv_opt -assert -multiclock dfflegalize -cell $_DLATCH_PP0_ 0
+#equiv_opt -assert -multiclock dfflegalize -cell $_DLATCH_PP0_ 1
+#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 $_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 SRs.
+
+design -load orig
+dfflegalize -cell $_SR_PP_ 0
+
+select -assert-count 2 sr0/t:$_NOT_
+select -assert-count 5 sr1/t:$_NOT_
+select -assert-count 3 sr0/t:$_SR_PP_
+select -assert-count 3 sr1/t:$_SR_PP_
+select -assert-count 0 sr0/t:$_ANDNOT_
+select -assert-count 1 sr1/t:$_ANDNOT_
+select -assert-count 0 sr0/t:$_AND_
+select -assert-count 1 sr1/t:$_AND_
+select -assert-count 0 sr0/t:$_OR_
+select -assert-count 1 sr1/t:$_OR_
+select -assert-none t:$_SR_PP_ t:$_NOT_ t:$_ANDNOT_ t:$_OR_ t:$_AND_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_SR_PP_ 1
+
+select -assert-count 5 sr0/t:$_NOT_
+select -assert-count 2 sr1/t:$_NOT_
+select -assert-count 3 sr0/t:$_SR_PP_
+select -assert-count 3 sr1/t:$_SR_PP_
+select -assert-count 1 sr0/t:$_ANDNOT_
+select -assert-count 0 sr1/t:$_ANDNOT_
+select -assert-count 1 sr0/t:$_AND_
+select -assert-count 0 sr1/t:$_AND_
+select -assert-count 1 sr0/t:$_OR_
+select -assert-count 0 sr1/t:$_OR_
+select -assert-none t:$_SR_PP_ t:$_NOT_ t:$_ANDNOT_ t:$_OR_ t:$_AND_ top/* %% %n t:* %i
+
+
+# Convert everything to ADLATCHs.
+
+design -load orig
+dfflegalize -cell $_DLATCH_PP0_ 0
+
+select -assert-count 2 sr0/t:$_NOT_
+select -assert-count 5 sr1/t:$_NOT_
+select -assert-count 3 sr0/t:$_DLATCH_PP0_
+select -assert-count 3 sr1/t:$_DLATCH_PP0_
+select -assert-count 0 sr0/t:$_ANDNOT_
+select -assert-count 1 sr1/t:$_ANDNOT_
+select -assert-count 0 sr0/t:$_AND_
+select -assert-count 1 sr1/t:$_AND_
+select -assert-count 0 sr0/t:$_OR_
+select -assert-count 1 sr1/t:$_OR_
+select -assert-none t:$_DLATCH_PP0_ t:$_NOT_ t:$_ANDNOT_ t:$_OR_ t:$_AND_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DLATCH_PP0_ 1
+
+select -assert-count 5 sr0/t:$_NOT_
+select -assert-count 2 sr1/t:$_NOT_
+select -assert-count 3 sr0/t:$_DLATCH_PP0_
+select -assert-count 3 sr1/t:$_DLATCH_PP0_
+select -assert-count 1 sr0/t:$_ANDNOT_
+select -assert-count 0 sr1/t:$_ANDNOT_
+select -assert-count 1 sr0/t:$_AND_
+select -assert-count 0 sr1/t:$_AND_
+select -assert-count 1 sr0/t:$_OR_
+select -assert-count 0 sr1/t:$_OR_
+select -assert-none t:$_DLATCH_PP0_ t:$_NOT_ t:$_ANDNOT_ t:$_OR_ t:$_AND_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DLATCH_PP1_ 0
+
+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_
+select -assert-count 0 sr1/t:$_ANDNOT_
+select -assert-count 1 sr0/t:$_AND_
+select -assert-count 0 sr1/t:$_AND_
+select -assert-count 1 sr0/t:$_OR_
+select -assert-count 0 sr1/t:$_OR_
+select -assert-none t:$_DLATCH_PP1_ t:$_NOT_ t:$_ANDNOT_ t:$_OR_ t:$_AND_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DLATCH_PP1_ 1
+
+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_
+select -assert-count 1 sr1/t:$_ANDNOT_
+select -assert-count 0 sr0/t:$_AND_
+select -assert-count 1 sr1/t:$_AND_
+select -assert-count 0 sr0/t:$_OR_
+select -assert-count 1 sr1/t:$_OR_
+select -assert-none t:$_DLATCH_PP1_ t:$_NOT_ t:$_ANDNOT_ t:$_OR_ t:$_AND_ top/* %% %n t:* %i
+
+
+# Convert everything to DLATCHSRs.
+
+design -load orig
+dfflegalize -cell $_DLATCHSR_PPP_ 0
+
+select -assert-count 2 sr0/t:$_NOT_
+select -assert-count 5 sr1/t:$_NOT_
+select -assert-count 3 sr0/t:$_DLATCHSR_PPP_
+select -assert-count 3 sr1/t:$_DLATCHSR_PPP_
+select -assert-count 0 sr0/t:$_ANDNOT_
+select -assert-count 1 sr1/t:$_ANDNOT_
+select -assert-count 0 sr0/t:$_AND_
+select -assert-count 1 sr1/t:$_AND_
+select -assert-count 0 sr0/t:$_OR_
+select -assert-count 1 sr1/t:$_OR_
+select -assert-none t:$_DLATCHSR_PPP_ t:$_NOT_ t:$_ANDNOT_ t:$_OR_ t:$_AND_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DLATCHSR_PPP_ 1
+
+select -assert-count 5 sr0/t:$_NOT_
+select -assert-count 2 sr1/t:$_NOT_
+select -assert-count 3 sr0/t:$_DLATCHSR_PPP_
+select -assert-count 3 sr1/t:$_DLATCHSR_PPP_
+select -assert-count 1 sr0/t:$_ANDNOT_
+select -assert-count 0 sr1/t:$_ANDNOT_
+select -assert-count 1 sr0/t:$_AND_
+select -assert-count 0 sr1/t:$_AND_
+select -assert-count 1 sr0/t:$_OR_
+select -assert-count 0 sr1/t:$_OR_
+select -assert-none t:$_DLATCHSR_PPP_ t:$_NOT_ t:$_ANDNOT_ t:$_OR_ t:$_AND_ top/* %% %n t:* %i
+
+
+# Convert everything to DFFSRs.
+
+design -load orig
+dfflegalize -cell $_DFFSR_PPP_ 0
+
+select -assert-count 2 sr0/t:$_NOT_
+select -assert-count 5 sr1/t:$_NOT_
+select -assert-count 3 sr0/t:$_DFFSR_PPP_
+select -assert-count 3 sr1/t:$_DFFSR_PPP_
+select -assert-count 0 sr0/t:$_ANDNOT_
+select -assert-count 1 sr1/t:$_ANDNOT_
+select -assert-count 0 sr0/t:$_AND_
+select -assert-count 1 sr1/t:$_AND_
+select -assert-count 0 sr0/t:$_OR_
+select -assert-count 1 sr1/t:$_OR_
+select -assert-none t:$_DFFSR_PPP_ t:$_NOT_ t:$_ANDNOT_ t:$_OR_ t:$_AND_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFFSR_PPP_ 1
+
+select -assert-count 5 sr0/t:$_NOT_
+select -assert-count 2 sr1/t:$_NOT_
+select -assert-count 3 sr0/t:$_DFFSR_PPP_
+select -assert-count 3 sr1/t:$_DFFSR_PPP_
+select -assert-count 1 sr0/t:$_ANDNOT_
+select -assert-count 0 sr1/t:$_ANDNOT_
+select -assert-count 1 sr0/t:$_AND_
+select -assert-count 0 sr1/t:$_AND_
+select -assert-count 1 sr0/t:$_OR_
+select -assert-count 0 sr1/t:$_OR_
+select -assert-none t:$_DFFSR_PPP_ t:$_NOT_ t:$_ANDNOT_ t:$_OR_ t:$_AND_ top/* %% %n t:* %i
+
+
+# Convert everything to DFFSREs.
+
+design -load orig
+dfflegalize -cell $_DFFSRE_PPPP_ 0
+
+select -assert-count 2 sr0/t:$_NOT_
+select -assert-count 5 sr1/t:$_NOT_
+select -assert-count 3 sr0/t:$_DFFSRE_PPPP_
+select -assert-count 3 sr1/t:$_DFFSRE_PPPP_
+select -assert-count 0 sr0/t:$_ANDNOT_
+select -assert-count 1 sr1/t:$_ANDNOT_
+select -assert-count 0 sr0/t:$_AND_
+select -assert-count 1 sr1/t:$_AND_
+select -assert-count 0 sr0/t:$_OR_
+select -assert-count 1 sr1/t:$_OR_
+select -assert-none t:$_DFFSRE_PPPP_ t:$_NOT_ t:$_ANDNOT_ t:$_OR_ t:$_AND_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFFSRE_PPPP_ 1
+
+select -assert-count 5 sr0/t:$_NOT_
+select -assert-count 2 sr1/t:$_NOT_
+select -assert-count 3 sr0/t:$_DFFSRE_PPPP_
+select -assert-count 3 sr1/t:$_DFFSRE_PPPP_
+select -assert-count 1 sr0/t:$_ANDNOT_
+select -assert-count 0 sr1/t:$_ANDNOT_
+select -assert-count 1 sr0/t:$_AND_
+select -assert-count 0 sr1/t:$_AND_
+select -assert-count 1 sr0/t:$_OR_
+select -assert-count 0 sr1/t:$_OR_
+select -assert-none t:$_DFFSRE_PPPP_ t:$_NOT_ t:$_ANDNOT_ t:$_OR_ t:$_AND_ top/* %% %n t:* %i
diff --git a/tests/techmap/dfflibmap-sim.v b/tests/techmap/dfflibmap-sim.v
new file mode 100644
index 000000000..1788a683b
--- /dev/null
+++ b/tests/techmap/dfflibmap-sim.v
@@ -0,0 +1,22 @@
+module dffn(input CLK, D, output reg Q, output QN);
+
+always @(negedge CLK)
+ Q <= D;
+
+assign QN = ~Q;
+
+endmodule
+
+module dffsr(input CLK, D, CLEAR, PRESET, output reg Q, output QN);
+
+always @(posedge CLK, posedge CLEAR, posedge PRESET)
+ if (CLEAR)
+ Q <= 0;
+ else if (PRESET)
+ Q <= 1;
+ else
+ Q <= D;
+
+assign QN = ~Q;
+
+endmodule
diff --git a/tests/techmap/dfflibmap.lib b/tests/techmap/dfflibmap.lib
new file mode 100644
index 000000000..ce460877e
--- /dev/null
+++ b/tests/techmap/dfflibmap.lib
@@ -0,0 +1,55 @@
+library(test) {
+ /* D-type flip-flop with asynchronous reset and preset */
+ cell (dffn) {
+ area : 6;
+ ff("IQ", "IQN") {
+ next_state : "D";
+ clocked_on : "!CLK";
+ }
+ pin(D) {
+ direction : input;
+ }
+ pin(CLK) {
+ direction : input;
+ }
+ pin(Q) {
+ direction: output;
+ function : "IQ";
+ }
+ pin(QN) {
+ direction: output;
+ function : "IQN";
+ }
+ }
+ cell (dffsr) {
+ area : 6;
+ ff("IQ", "IQN") {
+ next_state : "D";
+ clocked_on : "CLK";
+ clear : "CLEAR";
+ preset : "PRESET";
+ clear_preset_var1 : L;
+ clear_preset_var2 : L;
+ }
+ pin(D) {
+ direction : input;
+ }
+ pin(CLK) {
+ direction : input;
+ }
+ pin(CLEAR) {
+ direction : input;
+ }
+ pin(PRESET) {
+ direction : input;
+ }
+ pin(Q) {
+ direction: output;
+ function : "IQ";
+ }
+ pin(QN) {
+ direction: output;
+ function : "IQN";
+ }
+ }
+}
diff --git a/tests/techmap/dfflibmap.ys b/tests/techmap/dfflibmap.ys
new file mode 100644
index 000000000..04477eb14
--- /dev/null
+++ b/tests/techmap/dfflibmap.ys
@@ -0,0 +1,58 @@
+read_verilog -icells <<EOT
+
+module top(input C, D, S, R, output [9:0] Q);
+
+$_DFF_P_ ff0 (.C(C), .D(D), .Q(Q[0]));
+$_DFF_PP0_ ff1 (.C(C), .D(D), .R(R), .Q(Q[1]));
+$_DFF_PP1_ ff2 (.C(C), .D(D), .R(R), .Q(Q[2]));
+$_DFFSR_PPP_ ff3 (.C(C), .D(D), .R(R), .S(S), .Q(Q[3]));
+$_DFFSR_NNN_ ff4 (.C(C), .D(D), .R(R), .S(S), .Q(Q[4]));
+
+assign Q[9:5] = ~Q[4:0];
+
+endmodule
+
+EOT
+
+simplemap
+
+design -save orig
+
+#equiv_opt -map dfflibmap-sim.v -assert -multiclock dfflibmap -liberty dfflibmap.lib
+#equiv_opt -map dfflibmap-sim.v -assert -multiclock dfflibmap -prepare -liberty dfflibmap.lib
+dfflibmap -prepare -liberty dfflibmap.lib
+equiv_opt -map dfflibmap-sim.v -assert -multiclock dfflibmap -map-only -liberty dfflibmap.lib
+
+design -load orig
+dfflibmap -liberty dfflibmap.lib
+clean
+
+select -assert-count 4 t:$_NOT_
+select -assert-count 1 t:dffn
+select -assert-count 4 t:dffsr
+select -assert-none t:dffn t:dffsr t:$_NOT_ %% %n t:* %i
+
+design -load orig
+dfflibmap -prepare -liberty dfflibmap.lib
+
+select -assert-count 9 t:$_NOT_
+select -assert-count 1 t:$_DFF_N_
+select -assert-count 4 t:$_DFFSR_PPP_
+select -assert-none t:$_DFF_N_ t:$_DFFSR_PPP_ t:$_NOT_ %% %n t:* %i
+
+design -load orig
+dfflibmap -map-only -liberty dfflibmap.lib
+
+select -assert-count 5 t:$_NOT_
+select -assert-count 0 t:dffn
+select -assert-count 1 t:dffsr
+
+design -load orig
+dfflibmap -prepare -liberty dfflibmap.lib
+dfflibmap -map-only -liberty dfflibmap.lib
+clean
+
+select -assert-count 4 t:$_NOT_
+select -assert-count 1 t:dffn
+select -assert-count 4 t:dffsr
+select -assert-none t:dffn t:dffsr t:$_NOT_ %% %n t:* %i
diff --git a/tests/techmap/dffunmap.ys b/tests/techmap/dffunmap.ys
new file mode 100644
index 000000000..b813078ee
--- /dev/null
+++ b/tests/techmap/dffunmap.ys
@@ -0,0 +1,100 @@
+read_verilog -icells << EOT
+
+module top(...);
+
+input C, R, E, S;
+input [1:0] D;
+output [20:0] Q;
+
+$dff #(.CLK_POLARITY(1'b0), .WIDTH(2)) ff0 (.CLK(C), .D(D), .Q(Q[1:0]));
+$dffe #(.CLK_POLARITY(1'b0), .EN_POLARITY(1'b0), .WIDTH(2)) ff1 (.CLK(C), .EN(E), .D(D), .Q(Q[3:2]));
+$sdff #(.CLK_POLARITY(1'b0), .WIDTH(2), .SRST_POLARITY(1'b0), .SRST_VALUE(2'h2)) ff2 (.CLK(C), .SRST(R), .D(D), .Q(Q[5:4]));
+$sdffe #(.CLK_POLARITY(1'b0), .EN_POLARITY(1'b1), .WIDTH(2), .SRST_POLARITY(1'b1), .SRST_VALUE(2'h2)) ff3 (.CLK(C), .EN(E), .SRST(R), .D(D), .Q(Q[7:6]));
+$sdffce #(.CLK_POLARITY(1'b0), .EN_POLARITY(1'b1), .WIDTH(2), .SRST_POLARITY(1'b1), .SRST_VALUE(2'h2)) ff4 (.CLK(C), .EN(E), .SRST(R), .D(D), .Q(Q[9:8]));
+$adff #(.CLK_POLARITY(1'b0), .WIDTH(2), .ARST_POLARITY(1'b0), .ARST_VALUE(2'h2)) ff5 (.CLK(C), .ARST(R), .D(D), .Q(Q[11:10]));
+$adffe #(.CLK_POLARITY(1'b0), .EN_POLARITY(1'b1), .WIDTH(2), .ARST_POLARITY(1'b1), .ARST_VALUE(2'h2)) ff6 (.CLK(C), .EN(E), .ARST(R), .D(D), .Q(Q[13:12]));
+$dffsr #(.CLK_POLARITY(1'b0), .WIDTH(2), .CLR_POLARITY(1'b0), .SET_POLARITY(1'b1)) ff7 (.CLK(C), .CLR({R, S}), .SET({S, R}), .D(D), .Q(Q[15:14]));
+$dffsre #(.CLK_POLARITY(1'b0), .EN_POLARITY(1'b1), .WIDTH(2), .CLR_POLARITY(1'b1), .SET_POLARITY(1'b0)) ff8 (.CLK(C), .EN(E), .CLR({R, R}), .SET({S, S}), .D(D), .Q(Q[17:16]));
+
+endmodule
+
+EOT
+
+design -save orig
+
+equiv_opt -assert -async2sync dffunmap
+design -load postopt
+select -assert-none t:$sdff t:$dffe t:$adffe t:$sdffe t:$sdffce t:$dffsre
+select -assert-count 5 t:$dff
+select -assert-count 2 t:$adff
+select -assert-count 2 t:$dffsr
+
+design -load orig
+
+equiv_opt -assert -async2sync dffunmap -ce-only
+design -load postopt
+select -assert-none t:$dffe t:$adffe t:$sdffe t:$sdffce t:$dffsre
+select -assert-count 3 t:$dff
+select -assert-count 2 t:$sdff
+select -assert-count 2 t:$adff
+select -assert-count 2 t:$dffsr
+
+design -load orig
+
+equiv_opt -assert -async2sync dffunmap -srst-only
+design -load postopt
+select -assert-none t:$sdff t:$sdffe t:$sdffce
+select -assert-count 3 t:$dff
+select -assert-count 2 t:$dffe
+select -assert-count 1 t:$adff
+select -assert-count 1 t:$adffe
+select -assert-count 1 t:$dffsr
+select -assert-count 1 t:$dffsre
+
+design -load orig
+simplemap
+
+equiv_opt -assert -async2sync dffunmap
+design -load postopt
+select -assert-none t:$_SDFF* t:$_DFFE_* t:$_DFFSRE_*
+select -assert-count 10 t:$_DFF_N_
+select -assert-count 1 t:$_DFF_NP0_
+select -assert-count 1 t:$_DFF_NN0_
+select -assert-count 1 t:$_DFF_NP1_
+select -assert-count 1 t:$_DFF_NN1_
+select -assert-count 2 t:$_DFFSR_NPN_
+select -assert-count 2 t:$_DFFSR_NNP_
+
+design -load orig
+simplemap
+
+equiv_opt -assert -async2sync dffunmap -ce-only
+design -load postopt
+select -assert-none t:$_SDFFE_* t:$_SDFFCE_* t:$_DFFE_* t:$_DFFSRE_*
+select -assert-count 6 t:$_DFF_N_
+select -assert-count 1 t:$_SDFF_NP0_
+select -assert-count 1 t:$_SDFF_NN0_
+select -assert-count 1 t:$_SDFF_NP1_
+select -assert-count 1 t:$_SDFF_NN1_
+select -assert-count 1 t:$_DFF_NP0_
+select -assert-count 1 t:$_DFF_NN0_
+select -assert-count 1 t:$_DFF_NP1_
+select -assert-count 1 t:$_DFF_NN1_
+select -assert-count 2 t:$_DFFSR_NPN_
+select -assert-count 2 t:$_DFFSR_NNP_
+
+design -load orig
+simplemap
+
+equiv_opt -assert -async2sync dffunmap -srst-only
+design -load postopt
+select -assert-none t:$sdff t:$sdffe t:$sdffce
+select -assert-count 6 t:$_DFF_N_
+select -assert-count 2 t:$_DFFE_NP_
+select -assert-count 2 t:$_DFFE_NN_
+select -assert-count 1 t:$_DFF_NN0_
+select -assert-count 1 t:$_DFF_NN1_
+select -assert-count 1 t:$_DFFE_NP0P_
+select -assert-count 1 t:$_DFFE_NP1P_
+select -assert-count 2 t:$_DFFSR_NPN_
+select -assert-count 2 t:$_DFFSRE_NNPP_
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 e2c6303da..b486de5c7 100644
--- a/tests/techmap/mem_simple_4x1_runtest.sh
+++ b/tests/techmap/mem_simple_4x1_runtest.sh
@@ -1,8 +1,8 @@
#!/bin/bash
-set -ev
+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/pmux2mux.ys b/tests/techmap/pmux2mux.ys
new file mode 100644
index 000000000..1714a6b87
--- /dev/null
+++ b/tests/techmap/pmux2mux.ys
@@ -0,0 +1,15 @@
+read_verilog -icells << EOT
+module top(...);
+
+input [3:0] A;
+input [3:0] B0;
+input [3:0] B1;
+input [1:0] S;
+output [3:0] O;
+
+\$pmux #(.WIDTH(4), .S_WIDTH(2)) pm (.A(A), .B({B1, B0}), .S(S), .Y(O));
+
+endmodule
+EOT
+
+equiv_opt techmap -map +/pmux2mux.v
diff --git a/tests/techmap/recursive_runtest.sh b/tests/techmap/recursive_runtest.sh
index 30c79bf03..564d678fa 100644
--- a/tests/techmap/recursive_runtest.sh
+++ b/tests/techmap/recursive_runtest.sh
@@ -1,3 +1,3 @@
-set -ev
+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/run-test.sh b/tests/techmap/run-test.sh
index c16f204d9..581847ab0 100755
--- a/tests/techmap/run-test.sh
+++ b/tests/techmap/run-test.sh
@@ -1,20 +1,4 @@
#!/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 -e 'select out of bounds' $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 > ${s%.sh}.log 2>&1"
- fi
-done
-} > run-test.mk
-exec ${MAKE:-make} -f run-test.mk
+set -eu
+source ../gen-tests-makefile.sh
+run_tests --yosys-scripts --bash --yosys-args "-e 'select out of bounds'"
diff --git a/tests/techmap/shiftx2mux.ys b/tests/techmap/shiftx2mux.ys
index eb29680f6..f749e79b2 100644
--- a/tests/techmap/shiftx2mux.ys
+++ b/tests/techmap/shiftx2mux.ys
@@ -74,12 +74,6 @@ design -save gold
design -load gold
-techmap -D NO_LSB_FIRST_SHIFT_SHIFTX
-abc -lut 6
-select -assert-min 17 t:$lut
-
-
-design -load gold
techmap
abc -lut 6
select -assert-count 16 t:$lut
@@ -92,12 +86,6 @@ sat -verify -prove-asserts -show-ports miter
design -load gold
-techmap -D NO_LSB_FIRST_SHIFT_SHIFTX
-abc9 -lut 6
-select -assert-min 17 t:$lut
-
-
-design -load gold
techmap
abc9 -lut 6
select -assert-count 16 t:$lut
diff --git a/tests/techmap/zinit.ys b/tests/techmap/zinit.ys
index 3527840b9..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
@@ -95,7 +96,7 @@ EOT
zinit
select -assert-count 48 t:$_NOT_
-select -assert-count 1 w:Q a:init=24'bx %i
+select -assert-count 0 w:Q a:init %i
select -assert-count 4 c:dff0 c:dff2 c:dff4 c:dff6 %% t:$_DFFE_??1P_ %i
select -assert-count 4 c:dff1 c:dff3 c:dff5 c:dff7 %% t:$_DFFE_??0P_ %i
select -assert-count 4 c:dff8 c:dff10 c:dff12 c:dff14 %% t:$_SDFF_??1_ %i
@@ -142,7 +143,7 @@ EOT
zinit
select -assert-count 0 t:$_NOT_
-select -assert-count 1 w:Q a:init=24'bx %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 4d3478628..e4aef9917 100755
--- a/tests/tools/autotest.sh
+++ b/tests/tools/autotest.sh
@@ -193,13 +193,13 @@ do
elif [ "$frontend" = "verific_gates" ]; then
test_passes -p "verific -vlog2k ${bn}_ref.${refext}; verific -import -gates -all; opt; memory;;"
else
- test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.${refext}
+ test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt -nodffe -nosdff; fsm; opt; memory; opt -full -fine" ${bn}_ref.${refext}
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; memory; opt; fsm; 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; memory; opt; fsm; opt -full -fine" ${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
fi
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/.gitignore b/tests/various/.gitignore
index 12d4e5048..2bb6c7179 100644
--- a/tests/various/.gitignore
+++ b/tests/various/.gitignore
@@ -4,3 +4,4 @@
/write_gzip.v.gz
/run-test.mk
/plugin.so
+/plugin.so.dSYM
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/const_arg_loop.sv b/tests/various/const_arg_loop.sv
new file mode 100644
index 000000000..f28d06e68
--- /dev/null
+++ b/tests/various/const_arg_loop.sv
@@ -0,0 +1,92 @@
+module top;
+ function automatic [31:0] operation1;
+ input [4:0] rounds;
+ input integer num;
+ integer i;
+ begin
+ begin : shadow
+ integer rounds;
+ rounds = 0;
+ end
+ for (i = 0; i < rounds; i = i + 1)
+ num = num * 2;
+ operation1 = num;
+ end
+ endfunction
+
+ function automatic [31:0] pass_through;
+ input [31:0] inp;
+ pass_through = inp;
+ endfunction
+
+ function automatic [31:0] operation2;
+ input [4:0] inp;
+ input integer num;
+ begin
+ inp[0] = inp[0] ^ 1;
+ operation2 = num * inp;
+ end
+ endfunction
+
+ function automatic [31:0] operation3;
+ input [4:0] rounds;
+ input integer num;
+ reg [4:0] rounds;
+ integer i;
+ begin
+ begin : shadow
+ integer rounds;
+ rounds = 0;
+ end
+ for (i = 0; i < rounds; i = i + 1)
+ num = num * 2;
+ operation3 = num;
+ end
+ endfunction
+
+ function automatic [16:0] operation4;
+ input [15:0] a;
+ input b;
+ operation4 = {a, b};
+ endfunction
+
+ function automatic integer operation5;
+ input x;
+ integer x;
+ operation5 = x;
+ endfunction
+
+ wire [31:0] a;
+ assign a = 2;
+
+ parameter A = 3;
+
+ wire [31:0] x1;
+ assign x1 = operation1(A, a);
+
+ wire [31:0] x1b;
+ assign x1b = operation1(pass_through(A), a);
+
+ wire [31:0] x2;
+ assign x2 = operation2(A, a);
+
+ wire [31:0] x3;
+ assign x3 = operation3(A, a);
+
+ wire [16:0] x4;
+ assign x4 = operation4(a[15:0], 0);
+
+ wire [31:0] x5;
+ assign x5 = operation5(64);
+
+ always_comb begin
+ assert(a == 2);
+ assert(A == 3);
+ assert(x1 == 16);
+ assert(x1b == 16);
+ assert(x2 == 4);
+ assert(x3 == 16);
+ assert(x4 == a << 1);
+ assert(x5 == 64);
+ end
+endmodule
diff --git a/tests/various/const_arg_loop.ys b/tests/various/const_arg_loop.ys
new file mode 100644
index 000000000..392532213
--- /dev/null
+++ b/tests/various/const_arg_loop.ys
@@ -0,0 +1,6 @@
+read_verilog -sv const_arg_loop.sv
+hierarchy
+proc
+opt -full
+select -module top
+sat -verify -seq 1 -tempinduct -prove-asserts -show-all
diff --git a/tests/various/const_func.v b/tests/various/const_func.sv
index 76cdc385d..af65f5c73 100644
--- a/tests/various/const_func.v
+++ b/tests/various/const_func.sv
@@ -53,23 +53,34 @@ module top(out);
c1, c2, c3, c4,
d1, d2, d3, d4};
-// `define VERIFY
-`ifdef VERIFY
- assert property (a1 == 0);
- assert property (a2 == 0);
- assert property (a3 == "BAR");
- assert property (a4 == 0);
- assert property (b1 == "FOO");
- assert property (b2 == "FOO");
- assert property (b3 == 0);
- assert property (b4 == "HI");
- assert property (c1 == 1);
- assert property (c2 == 1);
- assert property (c3 == 0);
- assert property (c4 == 0);
- assert property (d1 == 0);
- assert property (d2 == 0);
- assert property (d3 == 1);
- assert property (d4 == 1);
-`endif
+ function signed [31:0] negate;
+ input integer inp;
+ negate = ~inp;
+ endfunction
+ parameter W = 10;
+ parameter X = 3;
+ localparam signed Y = $floor(W / X);
+ localparam signed Z = negate($floor(W / X));
+
+ always_comb begin
+ assert(a1 == 0);
+ assert(a2 == 0);
+ assert(a3 == "BAR");
+ assert(a4 == 0);
+ assert(b1 == "FOO");
+ assert(b2 == "FOO");
+ assert(b3 == 0);
+ assert(b4 == "HI");
+ assert(c1 == 1);
+ assert(c2 == 1);
+ assert(c3 == 0);
+ assert(c4 == 0);
+ assert(d1 == 0);
+ assert(d2 == 0);
+ assert(d3 == 1);
+ assert(d4 == 1);
+
+ assert(Y == 3);
+ assert(Z == ~3);
+ end
endmodule
diff --git a/tests/various/const_func.ys b/tests/various/const_func.ys
index 5e3c04105..2f60acfe6 100644
--- a/tests/various/const_func.ys
+++ b/tests/various/const_func.ys
@@ -1 +1,7 @@
-read_verilog const_func.v
+read_verilog -sv const_func.sv
+hierarchy
+proc
+flatten
+opt -full
+select -module top
+sat -verify -seq 1 -tempinduct -prove-asserts -show-all
diff --git a/tests/various/const_func_block_var.v b/tests/various/const_func_block_var.v
new file mode 100644
index 000000000..cb60844ab
--- /dev/null
+++ b/tests/various/const_func_block_var.v
@@ -0,0 +1,26 @@
+module top(out);
+ function integer operation;
+ input integer num;
+ localparam incr = 1;
+ localparam mult = 1;
+ begin
+ operation = 0;
+ begin : op_i
+ integer i;
+ for (i = 0; i * mult < 2; i = i + incr)
+ begin : op_j
+ integer j;
+ localparam other_mult = 2;
+ for (j = i; j < i * other_mult; j = j + incr)
+ num = num + incr;
+ end
+ num = num * 2;
+ end
+ operation = num;
+ end
+ endfunction
+
+ localparam res = operation(4);
+ output wire [31:0] out;
+ assign out = res;
+endmodule
diff --git a/tests/various/const_func_block_var.ys b/tests/various/const_func_block_var.ys
new file mode 100644
index 000000000..7c2e85c64
--- /dev/null
+++ b/tests/various/const_func_block_var.ys
@@ -0,0 +1 @@
+read_verilog const_func_block_var.v
diff --git a/tests/various/countbits.sv b/tests/various/countbits.sv
new file mode 100644
index 000000000..5762217bb
--- /dev/null
+++ b/tests/various/countbits.sv
@@ -0,0 +1,69 @@
+module top;
+
+ assert property ($countbits(15'b011xxxxzzzzzzzz, '0 ) == 1);
+ assert property ($countbits(15'b011xxxxzzzzzzzz, '1 ) == 2);
+ assert property ($countbits(15'b011xxxxzzzzzzzz, 'x ) == 4);
+ assert property ($countbits(15'b011xxxxzzzzzzzz, 'z ) == 8);
+ assert property ($countbits(15'b011xxxxzzzzzzzz, '0, '1 ) == 3);
+ assert property ($countbits(15'b011xxxxzzzzzzzz, '1, '1, '0 ) == 3);
+ assert property ($countbits(15'b011xxxxzzzzzzzz, '0, 'x ) == 5);
+ assert property ($countbits(15'b011xxxxzzzzzzzz, '0, 'z ) == 9);
+ assert property ($countbits(15'bz1x10xzxzzxzzzz, '0, 'z ) == 9);
+ assert property ($countbits(15'b011xxxxzzzzzzzz, 'x, 'z ) == 12);
+ assert property ($countbits(15'b011xxxxzzzzzzzz, '1, 'z ) == 10);
+ assert property ($countbits(15'b011xxxxzzzzzzzz, '1, 'x, 'z ) == 14);
+ assert property ($countbits(15'b011xxxxzzzzzzzz, '1, 'x, 'z, '0) == 15);
+
+ assert property ($countbits(0, '0) == 32); // test integers
+ assert property ($countbits(0, '1) == 0);
+ assert property ($countbits(80'b0, '0) == 80); // test something bigger than integer
+ assert property ($countbits(80'bx0, 'x) == 79);
+
+ always_comb begin
+ logic one;
+ logic [1:0] two;
+ logic [3:0] four;
+
+ // Make sure that the width of the whole expression doesn't affect the width of the shift
+ // operations inside the function.
+ one = $countbits(3'b100, '1) & 1'b1;
+ two = $countbits(3'b111, '1) & 2'b11;
+ four = $countbits(3'b111, '1) & 4'b1111;
+
+ assert (one == 1);
+ assert (two == 3);
+ assert (four == 3);
+ end
+
+ assert property ($countones(8'h00) == 0);
+ assert property ($countones(8'hff) == 8);
+ assert property ($countones(8'ha5) == 4);
+ assert property ($countones(8'h13) == 3);
+
+ logic test1 = 1'b1;
+ logic [4:0] test5 = 5'b10101;
+
+ assert property ($countones(test1) == 1);
+ assert property ($countones(test5) == 3);
+
+ assert property ($isunknown(8'h00) == 0);
+ assert property ($isunknown(8'hff) == 0);
+ assert property ($isunknown(8'hx0) == 1);
+ assert property ($isunknown(8'h1z) == 1);
+ assert property ($isunknown(8'hxz) == 1);
+
+ assert property ($onehot(8'h00) == 0);
+ assert property ($onehot(8'hff) == 0);
+ assert property ($onehot(8'h01) == 1);
+ assert property ($onehot(8'h80) == 1);
+ assert property ($onehot(8'h81) == 0);
+ assert property ($onehot(8'h20) == 1);
+
+ assert property ($onehot0(8'h00) == 1);
+ assert property ($onehot0(8'hff) == 0);
+ assert property ($onehot0(8'h01) == 1);
+ assert property ($onehot0(8'h80) == 1);
+ assert property ($onehot0(8'h81) == 0);
+ assert property ($onehot0(8'h20) == 1);
+
+endmodule
diff --git a/tests/various/countbits.ys b/tests/various/countbits.ys
new file mode 100644
index 000000000..a556f7c5d
--- /dev/null
+++ b/tests/various/countbits.ys
@@ -0,0 +1,7 @@
+read_verilog -sv countbits.sv
+hierarchy
+proc
+flatten
+opt -full
+select -module top
+sat -verify -seq 1 -tempinduct -prove-asserts -show-all
diff --git a/tests/various/dynamic_part_select.ys b/tests/various/dynamic_part_select.ys
index abc1daad6..2dc061e89 100644
--- a/tests/various/dynamic_part_select.ys
+++ b/tests/various/dynamic_part_select.ys
@@ -21,18 +21,18 @@ read_verilog ./dynamic_part_select/multiple_blocking.v
proc
rename -top gold
design -stash gold
-
+
read_verilog ./dynamic_part_select/multiple_blocking_gate.v
proc
rename -top gate
design -stash gate
-
+
design -copy-from gold -as gold gold
design -copy-from gate -as gate gate
miter -equiv -make_assert -make_outcmp -flatten gold gate equiv
sat -prove-asserts -seq 10 -show-public -verify -set-init-zero equiv
-
+
### Non-blocking to the same output register ###
design -reset
read_verilog ./dynamic_part_select/nonblocking.v
@@ -44,13 +44,13 @@ read_verilog ./dynamic_part_select/nonblocking_gate.v
proc
rename -top gate
design -stash gate
-
+
design -copy-from gold -as gold gold
design -copy-from gate -as gate gate
miter -equiv -make_assert -make_outcmp -flatten gold gate equiv
sat -prove-asserts -seq 10 -show-public -verify -set-init-zero equiv
-
+
### For-loop select, one dynamic input
design -reset
read_verilog ./dynamic_part_select/forloop_select.v
@@ -62,13 +62,13 @@ read_verilog ./dynamic_part_select/forloop_select_gate.v
proc
rename -top gate
design -stash gate
-
+
design -copy-from gold -as gold gold
design -copy-from gate -as gate gate
miter -equiv -make_assert -make_outcmp -flatten gold gate equiv
sat -prove-asserts -seq 10 -show-public -verify -set-init-zero equiv
-
+
#### Double loop (part-select, reset) ###
design -reset
read_verilog ./dynamic_part_select/reset_test.v
@@ -83,10 +83,10 @@ design -stash gate
design -copy-from gold -as gold gold
design -copy-from gate -as gate gate
-
+
miter -equiv -make_assert -make_outcmp -flatten gold gate equiv
sat -prove-asserts -seq 10 -show-public -verify -set-init-zero equiv
-
+
### Reversed part-select case ###
design -reset
read_verilog ./dynamic_part_select/reversed.v
@@ -101,6 +101,62 @@ design -stash gate
design -copy-from gold -as gold gold
design -copy-from gate -as gate gate
-
+
+miter -equiv -make_assert -make_outcmp -flatten gold gate equiv
+sat -prove-asserts -seq 10 -show-public -verify -set-init-zero equiv
+
+### Latches
+## Issue 1990
+design -reset
+read_verilog ./dynamic_part_select/latch_1990.v
+hierarchy -top latch_1990; prep; async2sync
+rename -top gold
+design -stash gold
+
+read_verilog ./dynamic_part_select/latch_1990_gate.v
+hierarchy -top latch_1990_gate; prep
+rename -top gate
+design -stash gate
+
+design -copy-from gold -as gold gold
+design -copy-from gate -as gate gate
+
+miter -equiv -make_assert -make_outcmp -flatten gold gate equiv
+sat -prove-asserts -show-public -verify -set-init-zero equiv
+
+###
+## Part select with obvious latch, expected to fail due comparison with old shift&mask AST transformation
+design -reset
+read_verilog ./dynamic_part_select/latch_002.v
+hierarchy -top latch_002; prep; async2sync
+rename -top gold
+design -stash gold
+
+read_verilog ./dynamic_part_select/latch_002_gate.v
+hierarchy -top latch_002_gate; prep; async2sync
+rename -top gate
+design -stash gate
+
+design -copy-from gold -as gold gold
+design -copy-from gate -as gate gate
+
+miter -equiv -make_assert -make_outcmp -flatten gold gate equiv
+sat -prove-asserts -seq 10 -show-public -falsify -set-init-zero equiv
+
+## Part select + latch, with no shift&mask
+design -reset
+read_verilog ./dynamic_part_select/latch_002.v
+hierarchy -top latch_002; prep; async2sync
+rename -top gold
+design -stash gold
+
+read_verilog ./dynamic_part_select/latch_002_gate_good.v
+hierarchy -top latch_002_gate; prep; async2sync
+rename -top gate
+design -stash gate
+
+design -copy-from gold -as gold gold
+design -copy-from gate -as gate gate
+
miter -equiv -make_assert -make_outcmp -flatten gold gate equiv
sat -prove-asserts -seq 10 -show-public -verify -set-init-zero equiv
diff --git a/tests/various/dynamic_part_select/forloop_select.v b/tests/various/dynamic_part_select/forloop_select.v
index 8260f3186..926fb3133 100644
--- a/tests/various/dynamic_part_select/forloop_select.v
+++ b/tests/various/dynamic_part_select/forloop_select.v
@@ -1,13 +1,14 @@
+`default_nettype none
module forloop_select #(parameter WIDTH=16, SELW=4, CTRLW=$clog2(WIDTH), DINW=2**SELW)
- (input clk,
- input [CTRLW-1:0] ctrl,
- input [DINW-1:0] din,
- input en,
+ (input wire clk,
+ input wire [CTRLW-1:0] ctrl,
+ input wire [DINW-1:0] din,
+ input wire en,
output reg [WIDTH-1:0] dout);
-
- reg [SELW:0] sel;
+
+ reg [SELW:0] sel;
localparam SLICE = WIDTH/(SELW**2);
-
+
always @(posedge clk)
begin
if (en) begin
@@ -16,4 +17,3 @@ module forloop_select #(parameter WIDTH=16, SELW=4, CTRLW=$clog2(WIDTH), DINW=2*
end
end
endmodule
-
diff --git a/tests/various/dynamic_part_select/forloop_select_gate.v b/tests/various/dynamic_part_select/forloop_select_gate.v
index 71ae88537..1a5fffdc7 100644
--- a/tests/various/dynamic_part_select/forloop_select_gate.v
+++ b/tests/various/dynamic_part_select/forloop_select_gate.v
@@ -1,8 +1,9 @@
+`default_nettype none
module forloop_select_gate (clk, ctrl, din, en, dout);
- input clk;
- input [3:0] ctrl;
- input [15:0] din;
- input en;
+ input wire clk;
+ input wire [3:0] ctrl;
+ input wire [15:0] din;
+ input wire en;
output reg [15:0] dout;
reg [4:0] sel;
always @(posedge clk)
diff --git a/tests/various/dynamic_part_select/latch_002.v b/tests/various/dynamic_part_select/latch_002.v
new file mode 100644
index 000000000..7617d6a72
--- /dev/null
+++ b/tests/various/dynamic_part_select/latch_002.v
@@ -0,0 +1,13 @@
+`default_nettype none
+module latch_002
+ (dword, sel, st, vect);
+ output reg [63:0] dword;
+ input wire [7:0] vect;
+ input wire [7:0] sel;
+ input wire st;
+
+ always @(*) begin
+ if (st)
+ dword[8*sel +:8] <= vect[7:0];
+ end
+endmodule // latch_002
diff --git a/tests/various/dynamic_part_select/latch_002_gate.v b/tests/various/dynamic_part_select/latch_002_gate.v
new file mode 100644
index 000000000..4acf129c6
--- /dev/null
+++ b/tests/various/dynamic_part_select/latch_002_gate.v
@@ -0,0 +1,18 @@
+`default_nettype none
+module latch_002_gate(dword, vect, sel, st);
+ output reg [63:0] dword;
+ input wire [7:0] vect;
+ input wire [7:0] sel;
+ input wire st;
+ reg [63:0] mask;
+ reg [63:0] data;
+ always @*
+ case (|(st))
+ 1'b 1:
+ begin
+ mask = (8'b 11111111)<<((((8)*(sel)))+(0));
+ data = ((8'b 11111111)&(vect[7:0]))<<((((8)*(sel)))+(0));
+ dword <= ((dword)&(~(mask)))|(data);
+ end
+ endcase
+endmodule
diff --git a/tests/various/dynamic_part_select/latch_002_gate_good.v b/tests/various/dynamic_part_select/latch_002_gate_good.v
new file mode 100644
index 000000000..809c74fc9
--- /dev/null
+++ b/tests/various/dynamic_part_select/latch_002_gate_good.v
@@ -0,0 +1,141 @@
+`default_nettype none
+module latch_002_gate (dword, vect, sel, st);
+ output reg [63:0] dword;
+ input wire [7:0] vect;
+ input wire [7:0] sel;
+ input st;
+ always @*
+ case (|(st))
+ 1'b 1:
+ case ((((8)*(sel)))+(0))
+ 0:
+ dword[7:0] <= vect[7:0];
+ 1:
+ dword[8:1] <= vect[7:0];
+ 2:
+ dword[9:2] <= vect[7:0];
+ 3:
+ dword[10:3] <= vect[7:0];
+ 4:
+ dword[11:4] <= vect[7:0];
+ 5:
+ dword[12:5] <= vect[7:0];
+ 6:
+ dword[13:6] <= vect[7:0];
+ 7:
+ dword[14:7] <= vect[7:0];
+ 8:
+ dword[15:8] <= vect[7:0];
+ 9:
+ dword[16:9] <= vect[7:0];
+ 10:
+ dword[17:10] <= vect[7:0];
+ 11:
+ dword[18:11] <= vect[7:0];
+ 12:
+ dword[19:12] <= vect[7:0];
+ 13:
+ dword[20:13] <= vect[7:0];
+ 14:
+ dword[21:14] <= vect[7:0];
+ 15:
+ dword[22:15] <= vect[7:0];
+ 16:
+ dword[23:16] <= vect[7:0];
+ 17:
+ dword[24:17] <= vect[7:0];
+ 18:
+ dword[25:18] <= vect[7:0];
+ 19:
+ dword[26:19] <= vect[7:0];
+ 20:
+ dword[27:20] <= vect[7:0];
+ 21:
+ dword[28:21] <= vect[7:0];
+ 22:
+ dword[29:22] <= vect[7:0];
+ 23:
+ dword[30:23] <= vect[7:0];
+ 24:
+ dword[31:24] <= vect[7:0];
+ 25:
+ dword[32:25] <= vect[7:0];
+ 26:
+ dword[33:26] <= vect[7:0];
+ 27:
+ dword[34:27] <= vect[7:0];
+ 28:
+ dword[35:28] <= vect[7:0];
+ 29:
+ dword[36:29] <= vect[7:0];
+ 30:
+ dword[37:30] <= vect[7:0];
+ 31:
+ dword[38:31] <= vect[7:0];
+ 32:
+ dword[39:32] <= vect[7:0];
+ 33:
+ dword[40:33] <= vect[7:0];
+ 34:
+ dword[41:34] <= vect[7:0];
+ 35:
+ dword[42:35] <= vect[7:0];
+ 36:
+ dword[43:36] <= vect[7:0];
+ 37:
+ dword[44:37] <= vect[7:0];
+ 38:
+ dword[45:38] <= vect[7:0];
+ 39:
+ dword[46:39] <= vect[7:0];
+ 40:
+ dword[47:40] <= vect[7:0];
+ 41:
+ dword[48:41] <= vect[7:0];
+ 42:
+ dword[49:42] <= vect[7:0];
+ 43:
+ dword[50:43] <= vect[7:0];
+ 44:
+ dword[51:44] <= vect[7:0];
+ 45:
+ dword[52:45] <= vect[7:0];
+ 46:
+ dword[53:46] <= vect[7:0];
+ 47:
+ dword[54:47] <= vect[7:0];
+ 48:
+ dword[55:48] <= vect[7:0];
+ 49:
+ dword[56:49] <= vect[7:0];
+ 50:
+ dword[57:50] <= vect[7:0];
+ 51:
+ dword[58:51] <= vect[7:0];
+ 52:
+ dword[59:52] <= vect[7:0];
+ 53:
+ dword[60:53] <= vect[7:0];
+ 54:
+ dword[61:54] <= vect[7:0];
+ 55:
+ dword[62:55] <= vect[7:0];
+ 56:
+ dword[63:56] <= vect[7:0];
+ 57:
+ dword[63:57] <= vect[7:0];
+ 58:
+ dword[63:58] <= vect[7:0];
+ 59:
+ dword[63:59] <= vect[7:0];
+ 60:
+ dword[63:60] <= vect[7:0];
+ 61:
+ dword[63:61] <= vect[7:0];
+ 62:
+ dword[63:62] <= vect[7:0];
+ 63:
+ dword[63:63] <= vect[7:0];
+ endcase
+ endcase
+endmodule
diff --git a/tests/various/dynamic_part_select/latch_1990.v b/tests/various/dynamic_part_select/latch_1990.v
new file mode 100644
index 000000000..864c05244
--- /dev/null
+++ b/tests/various/dynamic_part_select/latch_1990.v
@@ -0,0 +1,12 @@
+module latch_1990 #(
+ parameter BUG = 1
+) (
+ (* nowrshmsk = !BUG *)
+ output reg [1:0] x
+);
+ wire z = 0;
+ integer i;
+ always @*
+ for (i = 0; i < 2; i=i+1)
+ x[z^i] = z^i;
+endmodule
diff --git a/tests/various/dynamic_part_select/latch_1990_gate.v b/tests/various/dynamic_part_select/latch_1990_gate.v
new file mode 100644
index 000000000..a46183f23
--- /dev/null
+++ b/tests/various/dynamic_part_select/latch_1990_gate.v
@@ -0,0 +1,6 @@
+`default_nettype none
+module latch_1990_gate
+ (output wire [1:0] x);
+ assign x = 2'b10;
+endmodule // latch_1990_gate
+
diff --git a/tests/various/dynamic_part_select/multiple_blocking.v b/tests/various/dynamic_part_select/multiple_blocking.v
index 2858f7741..3bb249a76 100644
--- a/tests/various/dynamic_part_select/multiple_blocking.v
+++ b/tests/various/dynamic_part_select/multiple_blocking.v
@@ -1,8 +1,9 @@
+`default_nettype none
module multiple_blocking #(parameter WIDTH=32, SELW=1, CTRLW=$clog2(WIDTH), DINW=2**SELW)
- (input clk,
- input [CTRLW-1:0] ctrl,
- input [DINW-1:0] din,
- input [SELW-1:0] sel,
+ (input wire clk,
+ input wire [CTRLW-1:0] ctrl,
+ input wire [DINW-1:0] din,
+ input wire [SELW-1:0] sel,
output reg [WIDTH-1:0] dout);
localparam SLICE = WIDTH/(SELW**2);
diff --git a/tests/various/dynamic_part_select/multiple_blocking_gate.v b/tests/various/dynamic_part_select/multiple_blocking_gate.v
index 073b559dc..840918876 100644
--- a/tests/various/dynamic_part_select/multiple_blocking_gate.v
+++ b/tests/various/dynamic_part_select/multiple_blocking_gate.v
@@ -1,8 +1,9 @@
+`default_nettype none
module multiple_blocking_gate (clk, ctrl, din, sel, dout);
- input clk;
- input [4:0] ctrl;
- input [1:0] din;
- input [0:0] sel;
+ input wire clk;
+ input wire [4:0] ctrl;
+ input wire [1:0] din;
+ input wire [0:0] sel;
output reg [31:0] dout;
reg [5:0] a;
reg [0:0] b;
diff --git a/tests/various/dynamic_part_select/nonblocking.v b/tests/various/dynamic_part_select/nonblocking.v
index 0949b31a9..20f857cf9 100644
--- a/tests/various/dynamic_part_select/nonblocking.v
+++ b/tests/various/dynamic_part_select/nonblocking.v
@@ -1,8 +1,9 @@
+`default_nettype none
module nonblocking #(parameter WIDTH=32, SELW=1, CTRLW=$clog2(WIDTH), DINW=2**SELW)
- (input clk,
- input [CTRLW-1:0] ctrl,
- input [DINW-1:0] din,
- input [SELW-1:0] sel,
+ (input wire clk,
+ input wire [CTRLW-1:0] ctrl,
+ input wire [DINW-1:0] din,
+ input wire [SELW-1:0] sel,
output reg [WIDTH-1:0] dout);
localparam SLICE = WIDTH/(SELW**2);
diff --git a/tests/various/dynamic_part_select/nonblocking_gate.v b/tests/various/dynamic_part_select/nonblocking_gate.v
index ed1ee2776..212d44609 100644
--- a/tests/various/dynamic_part_select/nonblocking_gate.v
+++ b/tests/various/dynamic_part_select/nonblocking_gate.v
@@ -1,8 +1,9 @@
+`default_nettype none
module nonblocking_gate (clk, ctrl, din, sel, dout);
- input clk;
- input [4:0] ctrl;
- input [1:0] din;
- input [0:0] sel;
+ input wire clk;
+ input wire [4:0] ctrl;
+ input wire [1:0] din;
+ input wire [0:0] sel;
output reg [31:0] dout;
always @(posedge clk)
begin
diff --git a/tests/various/dynamic_part_select/original.v b/tests/various/dynamic_part_select/original.v
index f7dfed1a1..41310a215 100644
--- a/tests/various/dynamic_part_select/original.v
+++ b/tests/various/dynamic_part_select/original.v
@@ -1,8 +1,9 @@
+`default_nettype none
module original #(parameter WIDTH=32, SELW=1, CTRLW=$clog2(WIDTH), DINW=2**SELW)
- (input clk,
- input [CTRLW-1:0] ctrl,
- input [DINW-1:0] din,
- input [SELW-1:0] sel,
+ (input wire clk,
+ input wire [CTRLW-1:0] ctrl,
+ input wire [DINW-1:0] din,
+ input wire [SELW-1:0] sel,
output reg [WIDTH-1:0] dout);
localparam SLICE = WIDTH/(SELW**2);
always @(posedge clk)
diff --git a/tests/various/dynamic_part_select/original_gate.v b/tests/various/dynamic_part_select/original_gate.v
index 22093bf63..963b4228c 100644
--- a/tests/various/dynamic_part_select/original_gate.v
+++ b/tests/various/dynamic_part_select/original_gate.v
@@ -1,8 +1,9 @@
+`default_nettype none
module original_gate (clk, ctrl, din, sel, dout);
- input clk;
- input [4:0] ctrl;
- input [1:0] din;
- input [0:0] sel;
+ input wire clk;
+ input wire [4:0] ctrl;
+ input wire [1:0] din;
+ input wire [0:0] sel;
output reg [31:0] dout;
always @(posedge clk)
case (({(ctrl)*(sel)})+(0))
diff --git a/tests/various/dynamic_part_select/reset_test.v b/tests/various/dynamic_part_select/reset_test.v
index 29355aafb..1bb9379f2 100644
--- a/tests/various/dynamic_part_select/reset_test.v
+++ b/tests/various/dynamic_part_select/reset_test.v
@@ -1,8 +1,10 @@
+`default_nettype none
module reset_test #(parameter WIDTH=32, SELW=1, CTRLW=$clog2(WIDTH), DINW=2**SELW)
- (input clk,
- input [CTRLW-1:0] ctrl,
- input [DINW-1:0] din,
- input [SELW-1:0] sel,
+ (input wire clk,
+ input wire reset,
+ input wire [CTRLW-1:0] ctrl,
+ input wire [DINW-1:0] din,
+ input wire [SELW-1:0] sel,
output reg [WIDTH-1:0] dout);
reg [SELW:0] i;
@@ -16,8 +18,6 @@ module reset_test #(parameter WIDTH=32, SELW=1, CTRLW=$clog2(WIDTH), DINW=2**SE
dout[i*rval+:SLICE] <= 32'hDEAD;
end
end
- //else begin
dout[ctrl*sel+:SLICE] <= din;
- //end
end
endmodule
diff --git a/tests/various/dynamic_part_select/reset_test_gate.v b/tests/various/dynamic_part_select/reset_test_gate.v
index 96dff4135..4ae76c4f7 100644
--- a/tests/various/dynamic_part_select/reset_test_gate.v
+++ b/tests/various/dynamic_part_select/reset_test_gate.v
@@ -1,8 +1,10 @@
-module reset_test_gate (clk, ctrl, din, sel, dout);
- input clk;
- input [4:0] ctrl;
- input [1:0] din;
- input [0:0] sel;
+`default_nettype none
+module reset_test_gate (clk, reset, ctrl, din, sel, dout);
+ input wire clk;
+ input wire reset;
+ input wire [4:0] ctrl;
+ input wire [1:0] din;
+ input wire [0:0] sel;
output reg [31:0] dout;
reg [1:0] i;
wire [0:0] rval;
diff --git a/tests/various/dynamic_part_select/reversed.v b/tests/various/dynamic_part_select/reversed.v
index 8b114ac77..0268fa6bb 100644
--- a/tests/various/dynamic_part_select/reversed.v
+++ b/tests/various/dynamic_part_select/reversed.v
@@ -1,8 +1,9 @@
+`default_nettype none
module reversed #(parameter WIDTH=32, SELW=4, CTRLW=$clog2(WIDTH), DINW=2**SELW)
- (input clk,
- input [CTRLW-1:0] ctrl,
- input [DINW-1:0] din,
- input [SELW-1:0] sel,
+ (input wire clk,
+ input wire [CTRLW-1:0] ctrl,
+ input wire [DINW-1:0] din,
+ input wire [SELW-1:0] sel,
output reg [WIDTH-1:0] dout);
localparam SLICE = WIDTH/(SELW**2);
diff --git a/tests/various/dynamic_part_select/reversed_gate.v b/tests/various/dynamic_part_select/reversed_gate.v
index 9349d45ee..5ffdcb4d7 100644
--- a/tests/various/dynamic_part_select/reversed_gate.v
+++ b/tests/various/dynamic_part_select/reversed_gate.v
@@ -1,8 +1,9 @@
+`default_nettype none
module reversed_gate (clk, ctrl, din, sel, dout);
- input clk;
- input [4:0] ctrl;
- input [15:0] din;
- input [3:0] sel;
+ input wire clk;
+ input wire [4:0] ctrl;
+ input wire [15:0] din;
+ input wire [3:0] sel;
output reg [31:0] dout;
always @(posedge clk)
case ((({(32)-((ctrl)*(sel))})+(1))-(2))
diff --git a/tests/various/equiv_opt_undef.ys b/tests/various/equiv_opt_undef.ys
new file mode 100644
index 000000000..5d2c60d0a
--- /dev/null
+++ b/tests/various/equiv_opt_undef.ys
@@ -0,0 +1,35 @@
+read_ilang << EOT
+
+module \top
+ wire $a
+ wire $b
+ wire input 1 \D
+ wire input 2 \EN
+ wire output 3 \Q
+ cell $mux $x
+ parameter \WIDTH 1
+ connect \A \Q
+ connect \B \D
+ connect \S \EN
+ connect \Y $a
+ end
+ cell $ff $y
+ parameter \WIDTH 1
+ connect \D $a
+ connect \Q $b
+ end
+ cell $and $z
+ parameter \A_SIGNED 0
+ parameter \A_WIDTH 1
+ parameter \B_SIGNED 0
+ parameter \B_WIDTH 1
+ parameter \Y_WIDTH 1
+ connect \A $b
+ connect \B 1'x
+ connect \Y \Q
+ end
+end
+
+EOT
+
+equiv_opt -assert -undef ls
diff --git a/tests/various/fib.v b/tests/various/fib.v
new file mode 100644
index 000000000..986749626
--- /dev/null
+++ b/tests/various/fib.v
@@ -0,0 +1,65 @@
+module gate(
+ off, fib0, fib1, fib2, fib3, fib4, fib5, fib6, fib7, fib8, fib9
+);
+ input wire signed [31:0] off;
+
+ function automatic integer fib(
+ input integer k
+ );
+ if (k == 0)
+ fib = 0;
+ else if (k == 1)
+ fib = 1;
+ else
+ fib = fib(k - 1) + fib(k - 2);
+ endfunction
+
+ function automatic integer fib_wrap(
+ input integer k,
+ output integer o
+ );
+ o = off + fib(k);
+ endfunction
+
+ output integer fib0;
+ output integer fib1;
+ output integer fib2;
+ output integer fib3;
+ output integer fib4;
+ output integer fib5;
+ output integer fib6;
+ output integer fib7;
+ output integer fib8;
+ output integer fib9;
+
+ initial begin : blk
+ integer unused;
+ unused = fib_wrap(0, fib0);
+ unused = fib_wrap(1, fib1);
+ unused = fib_wrap(2, fib2);
+ unused = fib_wrap(3, fib3);
+ unused = fib_wrap(4, fib4);
+ unused = fib_wrap(5, fib5);
+ unused = fib_wrap(6, fib6);
+ unused = fib_wrap(7, fib7);
+ unused = fib_wrap(8, fib8);
+ unused = fib_wrap(9, fib9);
+ end
+endmodule
+
+module gold(
+ off, fib0, fib1, fib2, fib3, fib4, fib5, fib6, fib7, fib8, fib9
+);
+ input wire signed [31:0] off;
+
+ output integer fib0 = off + 0;
+ output integer fib1 = off + 1;
+ output integer fib2 = off + 1;
+ output integer fib3 = off + 2;
+ output integer fib4 = off + 3;
+ output integer fib5 = off + 5;
+ output integer fib6 = off + 8;
+ output integer fib7 = off + 13;
+ output integer fib8 = off + 21;
+ output integer fib9 = off + 34;
+endmodule
diff --git a/tests/various/fib.ys b/tests/various/fib.ys
new file mode 100644
index 000000000..946e0738a
--- /dev/null
+++ b/tests/various/fib.ys
@@ -0,0 +1,6 @@
+read_verilog fib.v
+hierarchy
+proc
+equiv_make gold gate equiv
+equiv_simple
+equiv_status -assert
diff --git a/tests/various/fib_tern.v b/tests/various/fib_tern.v
new file mode 100644
index 000000000..fefde74ce
--- /dev/null
+++ b/tests/various/fib_tern.v
@@ -0,0 +1,70 @@
+module gate(
+ off, fib0, fib1, fib2, fib3, fib4, fib5, fib6, fib7, fib8, fib9
+);
+ input wire signed [31:0] off;
+
+ function automatic blah(
+ input x
+ );
+ blah = x;
+ endfunction
+
+ function automatic integer fib(
+ input integer k
+ );
+ fib = k == 0
+ ? 0
+ : k == 1
+ ? 1
+ : fib(k - 1) + fib(k - 2);
+ endfunction
+
+ function automatic integer fib_wrap(
+ input integer k,
+ output integer o
+ );
+ o = off + fib(k);
+ endfunction
+
+ output integer fib0;
+ output integer fib1;
+ output integer fib2;
+ output integer fib3;
+ output integer fib4;
+ output integer fib5;
+ output integer fib6;
+ output integer fib7;
+ output integer fib8;
+ output integer fib9;
+
+ initial begin : blk
+ integer unused;
+ unused = fib_wrap(0, fib0);
+ unused = fib_wrap(1, fib1);
+ unused = fib_wrap(2, fib2);
+ unused = fib_wrap(3, fib3);
+ unused = fib_wrap(4, fib4);
+ unused = fib_wrap(5, fib5);
+ unused = fib_wrap(6, fib6);
+ unused = fib_wrap(7, fib7);
+ unused = fib_wrap(8, fib8);
+ unused = fib_wrap(9, fib9);
+ end
+endmodule
+
+module gold(
+ off, fib0, fib1, fib2, fib3, fib4, fib5, fib6, fib7, fib8, fib9
+);
+ input wire signed [31:0] off;
+
+ output integer fib0 = off + 0;
+ output integer fib1 = off + 1;
+ output integer fib2 = off + 1;
+ output integer fib3 = off + 2;
+ output integer fib4 = off + 3;
+ output integer fib5 = off + 5;
+ output integer fib6 = off + 8;
+ output integer fib7 = off + 13;
+ output integer fib8 = off + 21;
+ output integer fib9 = off + 34;
+endmodule
diff --git a/tests/various/fib_tern.ys b/tests/various/fib_tern.ys
new file mode 100644
index 000000000..e5bf186e1
--- /dev/null
+++ b/tests/various/fib_tern.ys
@@ -0,0 +1,6 @@
+read_verilog fib_tern.v
+hierarchy
+proc
+equiv_make gold gate equiv
+equiv_simple
+equiv_status -assert
diff --git a/tests/various/func_port_implied_dir.sv b/tests/various/func_port_implied_dir.sv
new file mode 100644
index 000000000..0424f1b46
--- /dev/null
+++ b/tests/various/func_port_implied_dir.sv
@@ -0,0 +1,23 @@
+module gate(w, x, y, z);
+ function automatic integer bar(
+ integer a
+ );
+ bar = 2 ** a;
+ endfunction
+ output integer w = bar(4);
+
+ function automatic integer foo(
+ input integer a, /* implicitly input */ integer b,
+ output integer c, /* implicitly output */ integer d
+ );
+ c = 42;
+ d = 51;
+ foo = a + b + 1;
+ endfunction
+ output integer x, y, z;
+ initial x = foo(1, 2, y, z);
+endmodule
+
+module gold(w, x, y, z);
+ output integer w = 16, x = 4, y = 42, z = 51;
+endmodule
diff --git a/tests/various/func_port_implied_dir.ys b/tests/various/func_port_implied_dir.ys
new file mode 100644
index 000000000..b5c22a05b
--- /dev/null
+++ b/tests/various/func_port_implied_dir.ys
@@ -0,0 +1,6 @@
+read_verilog -sv func_port_implied_dir.sv
+hierarchy
+proc
+equiv_make gold gate equiv
+equiv_simple
+equiv_status -assert
diff --git a/tests/various/gen_if_null.v b/tests/various/gen_if_null.v
index a12ac6288..992bc68b3 100644
--- a/tests/various/gen_if_null.v
+++ b/tests/various/gen_if_null.v
@@ -1,13 +1,17 @@
-module test(x, y, z);
+`default_nettype none
+module test;
localparam OFF = 0;
generate
if (OFF) ;
- else input x;
- if (!OFF) input y;
+ else wire x;
+ if (!OFF) wire y;
else ;
if (OFF) ;
else ;
if (OFF) ;
- input z;
+ wire z;
endgenerate
+ assign genblk1.x = 0;
+ assign genblk2.y = 0;
+ assign z = 0;
endmodule
diff --git a/tests/various/gen_if_null.ys b/tests/various/gen_if_null.ys
index 31dfc444b..0733e3a94 100644
--- a/tests/various/gen_if_null.ys
+++ b/tests/various/gen_if_null.ys
@@ -1,4 +1,4 @@
read_verilog gen_if_null.v
-select -assert-count 1 test/x
-select -assert-count 1 test/y
+select -assert-count 1 test/genblk1.x
+select -assert-count 1 test/genblk2.y
select -assert-count 1 test/z
diff --git a/tests/various/integer_range_bad_syntax.ys b/tests/various/integer_range_bad_syntax.ys
new file mode 100644
index 000000000..4f427211f
--- /dev/null
+++ b/tests/various/integer_range_bad_syntax.ys
@@ -0,0 +1,6 @@
+logger -expect error "syntax error, unexpected" 1
+read_verilog -sv <<EOT
+module test_integer_range();
+parameter integer [31:0] a = 0;
+endmodule
+EOT
diff --git a/tests/various/integer_real_bad_syntax.ys b/tests/various/integer_real_bad_syntax.ys
new file mode 100644
index 000000000..942d8de77
--- /dev/null
+++ b/tests/various/integer_real_bad_syntax.ys
@@ -0,0 +1,6 @@
+logger -expect error "syntax error, unexpected TOK_REAL" 1
+read_verilog -sv <<EOT
+module test_integer_real();
+parameter integer real a = 0;
+endmodule
+EOT
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/logic_param_simple.ys b/tests/various/logic_param_simple.ys
new file mode 100644
index 000000000..968564080
--- /dev/null
+++ b/tests/various/logic_param_simple.ys
@@ -0,0 +1,9 @@
+read_verilog -sv <<EOT
+module test_logic_param();
+parameter logic a = 0;
+parameter logic [31:0] e = 0;
+parameter logic signed b = 0;
+parameter logic unsigned c = 0;
+parameter logic unsigned [31:0] d = 0;
+endmodule
+EOT
diff --git a/tests/various/memory_word_as_index.data b/tests/various/memory_word_as_index.data
new file mode 100644
index 000000000..d525c18ee
--- /dev/null
+++ b/tests/various/memory_word_as_index.data
@@ -0,0 +1,4 @@
+00 04 08 0c
+10 14 18 1c
+20 24 28 2c
+30 34 38 3c
diff --git a/tests/various/memory_word_as_index.v b/tests/various/memory_word_as_index.v
new file mode 100644
index 000000000..a99ea9566
--- /dev/null
+++ b/tests/various/memory_word_as_index.v
@@ -0,0 +1,21 @@
+`define DATA 64'h492e5c4d7747e032
+
+`define GATE(n, expr) \
+module gate``n(sel, out); \
+ input wire [3:0] sel; \
+ output wire out; \
+ reg [63:0] bits; \
+ reg [5:0] ptrs[15:0]; \
+ initial bits = `DATA; \
+ initial $readmemh("memory_word_as_index.data", ptrs); \
+ assign out = expr; \
+endmodule
+
+`GATE(1, bits[ptrs[sel]])
+`GATE(2, bits[ptrs[sel][5:0]])
+`GATE(3, bits[ptrs[sel]+:1])
+
+module gold(sel, out);
+ input wire [3:0] sel;
+ output wire out = `DATA >> (sel * 4);
+endmodule
diff --git a/tests/various/memory_word_as_index.ys b/tests/various/memory_word_as_index.ys
new file mode 100644
index 000000000..9a2dea40e
--- /dev/null
+++ b/tests/various/memory_word_as_index.ys
@@ -0,0 +1,23 @@
+read_verilog memory_word_as_index.v
+
+hierarchy
+proc
+memory
+flatten
+opt -full
+
+equiv_make gold gate1 equiv
+equiv_simple
+equiv_status -assert
+
+delete equiv
+
+equiv_make gold gate2 equiv
+equiv_simple
+equiv_status -assert
+
+delete equiv
+
+equiv_make gold gate3 equiv
+equiv_simple
+equiv_status -assert
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/peepopt.ys b/tests/various/peepopt.ys
index ee5ad8a1a..45e936a21 100644
--- a/tests/various/peepopt.ys
+++ b/tests/various/peepopt.ys
@@ -68,146 +68,3 @@ equiv_opt -assert peepopt
design -load postopt
clean
select -assert-count 0 t:*
-
-####################
-
-design -reset
-read_verilog <<EOT
-module peepopt_dffmuxext_unsigned(input clk, ce, input [1:0] i, output reg [3:0] o);
- always @(posedge clk) if (ce) o <= i;
-endmodule
-EOT
-
-proc
-equiv_opt -assert peepopt
-design -load postopt
-clean
-select -assert-count 1 t:$dff r:WIDTH=2 %i
-select -assert-count 1 t:$mux r:WIDTH=2 %i
-select -assert-count 0 t:$dff t:$mux %% t:* %D
-
-####################
-
-design -reset
-read_verilog <<EOT
-module peepopt_dffmuxext_signed(input clk, ce, input signed [1:0] i, output reg signed [3:0] o);
- always @(posedge clk) if (ce) o <= i;
-endmodule
-EOT
-
-proc
-equiv_opt -assert peepopt
-design -load postopt
-clean
-select -assert-count 1 t:$dff r:WIDTH=2 %i
-select -assert-count 1 t:$mux r:WIDTH=2 %i
-select -assert-count 0 t:$dff t:$mux %% t:* %D
-
-###################
-
-design -reset
-read_verilog <<EOT
-module peepopt_dffmuxext_const(input clk, ce, input [1:0] i, output reg [5:0] o);
- always @(posedge clk) if (ce) o <= {1'b0, i[1], 2'b1x, i[0], 1'bz};
-endmodule
-EOT
-
-proc
-equiv_opt -assert peepopt
-design -load postopt
-select -assert-count 1 t:$dff r:WIDTH=2 %i
-select -assert-count 1 t:$mux r:WIDTH=2 %i
-select -assert-count 0 t:$dff t:$mux %% t:* %D
-
-###################
-
-design -reset
-read_verilog <<EOT
-module peepopt_dffmuxext_const_init(input clk, ce, input [1:0] i, (* init=6'b0x00x1 *) output reg [5:0] o);
- always @(posedge clk) if (ce) o <= {1'b0, i[1], 2'b1x, i[0], 1'bz};
-endmodule
-EOT
-
-proc
-equiv_opt -assert peepopt
-design -load postopt
-select -assert-count 1 t:$dff r:WIDTH=4 %i
-select -assert-count 1 t:$mux r:WIDTH=4 %i
-select -assert-count 0 t:$dff t:$mux %% t:* %D
-
-####################
-
-design -reset
-read_verilog <<EOT
-module peepopt_dffmuxext_unsigned_rst(input clk, ce, rst, input [1:0] i, output reg [3:0] o);
- always @(posedge clk) if (rst) o <= 0; else if (ce) o <= i;
-endmodule
-EOT
-
-proc
-equiv_opt -assert peepopt
-design -load postopt
-wreduce
-select -assert-count 1 t:$dff r:WIDTH=2 %i
-select -assert-count 2 t:$mux
-select -assert-count 2 t:$mux r:WIDTH=2 %i
-select -assert-count 0 t:$dff t:$mux %% t:* %D
-
-####################
-
-design -reset
-read_verilog <<EOT
-module peepopt_dffmuxext_signed_rst(input clk, ce, rstn, input signed [1:0] i, output reg signed [3:0] o);
- always @(posedge clk) begin
- if (ce) o <= i;
- if (!rstn) o <= 4'b1111;
- end
-endmodule
-EOT
-
-proc
-equiv_opt -assert peepopt
-design -load postopt
-wreduce
-select -assert-count 1 t:$dff r:WIDTH=2 %i
-select -assert-count 2 t:$mux
-select -assert-count 2 t:$mux r:WIDTH=2 %i
-select -assert-count 0 t:$logic_not t:$dff t:$mux %% t:* %D
-
-####################
-
-design -reset
-read_verilog <<EOT
-module peepopt_dffmuxext_signed_rst_init(input clk, ce, rstn, input signed [1:0] i, output reg signed [3:0] o);
- initial o <= 4'b0010;
- always @(posedge clk) begin
- if (ce) o <= i;
- if (!rstn) o <= 4'b1111;
- end
-endmodule
-EOT
-
-proc
-# NB: equiv_opt uses equiv_induct which covers
-# only the induction half of temporal induction
-# --- missing the base-case half
-# This makes it akin to `sat -tempinduct-inductonly`
-# instead of `sat -tempinduct-baseonly` or
-# `sat -tempinduct` which is necessary for this
-# testcase
-#equiv_opt -assert peepopt
-
-design -save gold
-peepopt
-wreduce
-design -stash gate
-design -import gold -as gold
-design -import gate -as gate
-miter -equiv -flatten -make_assert -make_outputs gold gate miter
-sat -tempinduct -verify -prove-asserts -show-ports miter
-
-design -load gate
-select -assert-count 1 t:$dff r:WIDTH=4 %i
-select -assert-count 2 t:$mux
-select -assert-count 2 t:$mux r:WIDTH=4 %i
-select -assert-count 0 t:$logic_not t:$dff t:$mux %% t:* %D
diff --git a/tests/various/port_sign_extend.v b/tests/various/port_sign_extend.v
new file mode 100644
index 000000000..813ceb503
--- /dev/null
+++ b/tests/various/port_sign_extend.v
@@ -0,0 +1,95 @@
+module GeneratorSigned1(out);
+ output wire signed out;
+ assign out = 1;
+endmodule
+
+module GeneratorUnsigned1(out);
+ output wire out;
+ assign out = 1;
+endmodule
+
+module GeneratorSigned2(out);
+ output wire signed [1:0] out;
+ assign out = 2;
+endmodule
+
+module GeneratorUnsigned2(out);
+ output wire [1:0] out;
+ assign out = 2;
+endmodule
+
+module PassThrough(a, b);
+ input wire [3:0] a;
+ output wire [3:0] b;
+ assign b = a;
+endmodule
+
+module act(o1, o2, o3, o4, o5, o6, o7, o8, o9, yay1, nay1, yay2, nay2);
+ output wire [3:0] o1, o2, o3, o4, o5, o6, o7, o8, o9;
+
+ // unsigned constant
+ PassThrough pt1(1'b1, o1);
+
+ // unsigned wire
+ wire tmp2;
+ assign tmp2 = 1'sb1;
+ PassThrough pt2(tmp2, o2);
+
+ // signed constant
+ PassThrough pt3(1'sb1, o3);
+
+ // signed wire
+ wire signed tmp4;
+ assign tmp4 = 1'sb1;
+ PassThrough pt4(tmp4, o4);
+
+ // signed expressions
+ wire signed [1:0] tmp5a = 2'b11;
+ wire signed [1:0] tmp5b = 2'b01;
+ PassThrough pt5(tmp5a ^ tmp5b, o5);
+
+ wire signed [2:0] tmp6a = 3'b100;
+ wire signed [2:0] tmp6b = 3'b001;
+ PassThrough pt6(tmp6a ? tmp6a : tmp6b, o6);
+
+ wire signed [2:0] tmp7 = 3'b011;
+ PassThrough pt7(~tmp7, o7);
+
+ reg signed [2:0] tmp8 [0:0];
+ initial tmp8[0] = 3'b101;
+ PassThrough pt8(tmp8[0], o8);
+
+ wire signed [2:0] tmp9a = 3'b100;
+ wire signed [1:0] tmp9b = 2'b11;
+ PassThrough pt9(0 ? tmp9a : tmp9b, o9);
+
+ output wire [2:0] yay1, nay1;
+ GeneratorSigned1 os1(yay1);
+ GeneratorUnsigned1 ou1(nay1);
+
+ output wire [2:0] yay2, nay2;
+ GeneratorSigned2 os2(yay2);
+ GeneratorUnsigned2 ou2(nay2);
+endmodule
+
+module ref(o1, o2, o3, o4, o5, o6, o7, o8, o9, yay1, nay1, yay2, nay2);
+ output wire [3:0] o1, o2, o3, o4, o5, o6, o7, o8, o9;
+
+ assign o1 = 4'b0001;
+ assign o2 = 4'b0001;
+ assign o3 = 4'b1111;
+ assign o4 = 4'b1111;
+ assign o5 = 4'b1110;
+ assign o6 = 4'b1100;
+ assign o7 = 4'b1100;
+ assign o8 = 4'b1101;
+ assign o9 = 4'b1111;
+
+ output wire [2:0] yay1, nay1;
+ assign yay1 = 3'b111;
+ assign nay1 = 3'b001;
+
+ output wire [2:0] yay2, nay2;
+ assign yay2 = 3'b110;
+ assign nay2 = 3'b010;
+endmodule
diff --git a/tests/various/port_sign_extend.ys b/tests/various/port_sign_extend.ys
new file mode 100644
index 000000000..6d1adf7f3
--- /dev/null
+++ b/tests/various/port_sign_extend.ys
@@ -0,0 +1,29 @@
+read_verilog -nomem2reg port_sign_extend.v
+hierarchy
+flatten
+proc
+memory
+equiv_make ref act equiv
+equiv_simple
+equiv_status -assert
+
+delete
+
+read_verilog -nomem2reg port_sign_extend.v
+flatten
+proc
+memory
+equiv_make ref act equiv
+equiv_simple
+equiv_status -assert
+
+delete
+
+read_verilog -nomem2reg port_sign_extend.v
+hierarchy
+proc
+memory
+equiv_make ref act equiv
+prep -flatten -top equiv
+equiv_induct
+equiv_status -assert
diff --git a/tests/various/rand_const.sv b/tests/various/rand_const.sv
new file mode 100644
index 000000000..be00812c0
--- /dev/null
+++ b/tests/various/rand_const.sv
@@ -0,0 +1,8 @@
+module top;
+ rand const reg rx;
+ const reg ry;
+ rand reg rz;
+ rand const integer ix;
+ const integer iy;
+ rand integer iz;
+endmodule
diff --git a/tests/various/rand_const.ys b/tests/various/rand_const.ys
new file mode 100644
index 000000000..74e43c7cc
--- /dev/null
+++ b/tests/various/rand_const.ys
@@ -0,0 +1 @@
+read_verilog -sv rand_const.sv
diff --git a/tests/various/run-test.sh b/tests/various/run-test.sh
index ea56b70f0..2f91cf0fd 100755
--- a/tests/various/run-test.sh
+++ b/tests/various/run-test.sh
@@ -1,20 +1,4 @@
#!/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
+set -eu
+source ../gen-tests-makefile.sh
+run_tests --yosys-scripts --bash
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 b48f808a1..96ebe20ba 100644
--- a/tests/verilog/.gitignore
+++ b/tests/verilog/.gitignore
@@ -1,3 +1,6 @@
/*.log
/*.out
/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/atom_type_signedness.ys b/tests/verilog/atom_type_signedness.ys
new file mode 100644
index 000000000..22bbe6efc
--- /dev/null
+++ b/tests/verilog/atom_type_signedness.ys
@@ -0,0 +1,19 @@
+read_verilog -dump_ast1 -dump_ast2 -sv <<EOT
+module dut();
+
+enum integer { uInteger = -10 } a;
+enum int { uInt = -11 } b;
+enum shortint { uShortInt = -12 } c;
+enum byte { uByte = -13 } d;
+
+always_comb begin
+ assert(-10 == uInteger);
+ assert(-11 == uInt);
+ assert(-12 == uShortInt);
+ assert(-13 == uByte);
+end
+endmodule
+EOT
+hierarchy; proc; opt
+select -module dut
+sat -verify -seq 1 -tempinduct -prove-asserts -show-all
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/block_labels.ys b/tests/verilog/block_labels.ys
new file mode 100644
index 000000000..e76bcf771
--- /dev/null
+++ b/tests/verilog/block_labels.ys
@@ -0,0 +1,26 @@
+read_verilog <<EOT
+module foo;
+
+ genvar a = 0;
+ for (a = 0; a < 10; a++) begin : a
+ end : a
+endmodule
+EOT
+read_verilog <<EOT
+module foo2;
+
+ genvar a = 0;
+ for (a = 0; a < 10; a++) begin : a
+ end
+endmodule
+EOT
+
+logger -expect error "Begin label \(a\) and end label \(b\) don't match\." 1
+read_verilog <<EOT
+module foo3;
+
+ genvar a = 0;
+ for (a = 0; a < 10; a++) begin : a
+ end : b
+endmodule
+EOT
diff --git a/tests/verilog/bug2493.ys b/tests/verilog/bug2493.ys
new file mode 100644
index 000000000..380d2a823
--- /dev/null
+++ b/tests/verilog/bug2493.ys
@@ -0,0 +1,12 @@
+logger -expect error "Failed to detect width for identifier \\genblk1\.y!" 1
+read_verilog <<EOT
+module top1;
+ wire x;
+ generate
+ if (1) begin
+ mod y();
+ assign x = y;
+ end
+ endgenerate
+endmodule
+EOT
diff --git a/tests/verilog/bug656.v b/tests/verilog/bug656.v
new file mode 100644
index 000000000..068d045fd
--- /dev/null
+++ b/tests/verilog/bug656.v
@@ -0,0 +1,21 @@
+module top #(
+ parameter WIDTH = 6
+) (
+ input [WIDTH-1:0] a_i,
+ input [WIDTH-1:0] b_i,
+ output [WIDTH-1:0] z_o
+);
+ genvar g;
+ generate
+ for (g = 0; g < WIDTH; g = g + 1) begin
+ if (g > 2) begin
+ wire tmp;
+ assign tmp = a_i[g] || b_i[g];
+ assign z_o[g] = tmp;
+ end
+ else begin
+ assign z_o[g] = a_i[g] && b_i[g];
+ end
+ end
+ endgenerate
+endmodule
diff --git a/tests/verilog/bug656.ys b/tests/verilog/bug656.ys
new file mode 100644
index 000000000..7f367341a
--- /dev/null
+++ b/tests/verilog/bug656.ys
@@ -0,0 +1,13 @@
+read_verilog bug656.v
+
+select -assert-count 1 top/a_i
+select -assert-count 1 top/b_i
+select -assert-count 1 top/z_o
+
+select -assert-none top/genblk1[0].genblk1.tmp
+select -assert-none top/genblk1[1].genblk1.tmp
+select -assert-none top/genblk1[2].genblk1.tmp
+
+select -assert-count 1 top/genblk1[3].genblk1.tmp
+select -assert-count 1 top/genblk1[4].genblk1.tmp
+select -assert-count 1 top/genblk1[5].genblk1.tmp
diff --git a/tests/verilog/conflict_assert.ys b/tests/verilog/conflict_assert.ys
new file mode 100644
index 000000000..121a0cf51
--- /dev/null
+++ b/tests/verilog/conflict_assert.ys
@@ -0,0 +1,8 @@
+logger -expect error "Cannot add procedural assertion `\\x' because a signal with the same name was already created" 1
+read_verilog -sv <<EOT
+module top;
+ wire x, y;
+ always @*
+ x: assert(y == 1);
+endmodule
+EOT
diff --git a/tests/verilog/conflict_cell_memory.ys b/tests/verilog/conflict_cell_memory.ys
new file mode 100644
index 000000000..ddc67596f
--- /dev/null
+++ b/tests/verilog/conflict_cell_memory.ys
@@ -0,0 +1,9 @@
+logger -expect error "Cannot add cell `\\x' because a memory with the same name was already created" 1
+read_verilog <<EOT
+module mod;
+endmodule
+module top;
+ reg [2:0] x [0:0];
+ mod x();
+endmodule
+EOT
diff --git a/tests/verilog/conflict_interface_port.ys b/tests/verilog/conflict_interface_port.ys
new file mode 100644
index 000000000..b97ec029e
--- /dev/null
+++ b/tests/verilog/conflict_interface_port.ys
@@ -0,0 +1,17 @@
+logger -expect error "Cannot add interface port `\\i' because a signal with the same name was already created" 1
+read_verilog -sv <<EOT
+interface intf;
+ logic x;
+ assign x = 1;
+ modport m(input x);
+endinterface
+module mod(intf.m i);
+ wire x;
+ assign x = i.x;
+ wire i;
+endmodule
+module top;
+ intf i();
+ mod m(i);
+endmodule
+EOT
diff --git a/tests/verilog/conflict_memory_wire.ys b/tests/verilog/conflict_memory_wire.ys
new file mode 100644
index 000000000..5c296074f
--- /dev/null
+++ b/tests/verilog/conflict_memory_wire.ys
@@ -0,0 +1,7 @@
+logger -expect error "Cannot add memory `\\x' because a signal with the same name was already created" 1
+read_verilog <<EOT
+module top;
+ reg [2:0] x;
+ reg [2:0] x [0:0];
+endmodule
+EOT
diff --git a/tests/verilog/conflict_pwire.ys b/tests/verilog/conflict_pwire.ys
new file mode 100644
index 000000000..ecc30d33a
--- /dev/null
+++ b/tests/verilog/conflict_pwire.ys
@@ -0,0 +1,8 @@
+logger -expect error "Cannot add pwire `\\x' because a signal with the same name was already created" 1
+read_verilog -pwires <<EOT
+module top;
+ wire x;
+ assign x = 1;
+ localparam x = 2;
+endmodule
+EOT
diff --git a/tests/verilog/conflict_wire_memory.ys b/tests/verilog/conflict_wire_memory.ys
new file mode 100644
index 000000000..77520fea9
--- /dev/null
+++ b/tests/verilog/conflict_wire_memory.ys
@@ -0,0 +1,7 @@
+logger -expect error "Cannot add signal `\\x' because a memory with the same name was already created" 1
+read_verilog <<EOT
+module top;
+ reg [2:0] x [0:0];
+ reg [2:0] x;
+endmodule
+EOT
diff --git a/tests/verilog/const_arst.ys b/tests/verilog/const_arst.ys
new file mode 100644
index 000000000..df720575c
--- /dev/null
+++ b/tests/verilog/const_arst.ys
@@ -0,0 +1,24 @@
+read_verilog <<EOT
+module test (
+ input clk, d,
+ output reg q
+);
+wire nop = 1'h0;
+always @(posedge clk, posedge nop) begin
+ if (nop) q <= 1'b0;
+ else q <= d;
+end
+endmodule
+EOT
+prep -top test
+write_verilog const_arst.v
+design -stash gold
+read_verilog const_arst.v
+prep -top test
+design -stash gate
+design -copy-from gold -as gold A:top
+design -copy-from gate -as gate A:top
+miter -equiv -flatten -make_assert gold gate miter
+prep -top miter
+clk2fflogic
+sat -set-init-zero -tempinduct -prove-asserts -verify
diff --git a/tests/verilog/const_sr.ys b/tests/verilog/const_sr.ys
new file mode 100644
index 000000000..c1406b0a0
--- /dev/null
+++ b/tests/verilog/const_sr.ys
@@ -0,0 +1,25 @@
+read_verilog <<EOT
+module test (
+ input clk, rst, d,
+ output reg q
+);
+wire nop = 1'h0;
+always @(posedge clk, posedge nop, posedge rst) begin
+ if (rst) q <= 1'b0;
+ else if (nop) q <= 1'b1;
+ else q <= d;
+end
+endmodule
+EOT
+prep -top test
+write_verilog const_sr.v
+design -stash gold
+read_verilog const_sr.v
+prep -top test
+design -stash gate
+design -copy-from gold -as gold A:top
+design -copy-from gate -as gate A:top
+miter -equiv -flatten -make_assert gold gate miter
+prep -top miter
+clk2fflogic
+sat -set-init-zero -tempinduct -prove-asserts -verify
diff --git a/tests/verilog/delay_mintypmax.ys b/tests/verilog/delay_mintypmax.ys
new file mode 100644
index 000000000..74359f557
--- /dev/null
+++ b/tests/verilog/delay_mintypmax.ys
@@ -0,0 +1,213 @@
+logger -expect-no-warnings
+read_verilog <<EOT
+module test (a, b, c, y);
+ input a;
+ input signed [1:0] b;
+ input signed [2:0] c;
+ output y;
+ assign #(12.5 : 14.5 : 20) y = ^(a ? b : c);
+endmodule
+EOT
+
+design -reset
+logger -expect-no-warnings
+read_verilog << EOT
+module test (input [7:0] a, b, c, d, output [7:0] x, y, z);
+ assign #(20:20:25) x = a + b, y = b + c, z = c + d;
+endmodule
+EOT
+
+design -reset
+logger -expect-no-warnings
+read_verilog << EOT
+module test (input [7:0] a, b, c, d, output [7:0] x, y, z);
+ assign #(20:20:25, 40:45:50, 60:65:75) x = a + b, y = b + c, z = c + d;
+endmodule
+EOT
+
+design -reset
+logger -expect-no-warnings
+read_verilog <<EOT
+module test (a, b, c, y);
+ localparam TIME_STEP = 0.011;
+ input signed [3:0] a;
+ input signed [1:0] b;
+ input signed [1:0] c;
+ output [5:0] y;
+ assign #(TIME_STEP:TIME_STEP:TIME_STEP) y = (a >> b) >>> c;
+endmodule
+EOT
+
+design -reset
+logger -expect-no-warnings
+read_verilog <<EOT
+module test;
+ wire o, a, b;
+ and #(1:2:3, 4:5:6) and_gate (o, a, b);
+ wire #(1:2:3, 4:5:6, 7:8:9) x;
+ assign o = x;
+endmodule
+EOT
+
+design -reset
+logger -expect-no-warnings
+read_verilog <<EOT
+module test;
+ localparam TIME_TYP = 0.7;
+ wire o, a, b;
+ and #(0:TIME_TYP:2) and_gate (o, a, b);
+ wire #(2:TIME_TYP:4) x;
+ assign o = x;
+endmodule
+EOT
+
+design -reset
+logger -expect warning "Yosys has only limited support for tri-state logic at the moment." 1
+read_verilog <<EOT
+module test (input en, input a, input b, output c);
+ wire [15:0] add0_res = a + b;
+ assign #(15:20:30) c = (en) ? a : 1'bz;
+endmodule
+EOT
+
+design -reset
+logger -expect-no-warnings
+read_verilog <<EOT
+module test (input en, d, t_min, t, t_max);
+ reg o;
+ always @*
+ if (en)
+ o = #(t_min : t : t_max, t_min : t : t_max) ~d;
+endmodule
+EOT
+
+design -reset
+logger -expect-no-warnings
+read_verilog <<EOT
+module test #(parameter DELAY_RISE = 0, DELAY_FALL = 0, DELAY_Z = 0)
+ (input clock, input reset, input req_0, input req_1, output gnt_0, output gnt_1);
+ parameter SIZE = 3;
+ parameter IDLE = 3'b001, GNT0 = 3'b010, GNT1 = 3'b100;
+ reg [SIZE-1:0] state;
+ reg [SIZE-1:0] next_state;
+ reg gnt_0, gnt_1;
+
+ always @ (state or req_0 or req_1)
+ begin : FSM_COMBO
+ next_state = 3'b000;
+ case (state)
+ IDLE : if (req_0 == 1'b1) begin
+ next_state = #(DELAY_RISE-1 : DELAY_RISE : DELAY_RISE+1) GNT0;
+ end else if (req_1 == 1'b1) begin
+ next_state = #(DELAY_FALL/1.2 : DELAY_FALL : DELAY_FALL*2.5) GNT1;
+ end else begin
+ next_state = #(DELAY_Z : DELAY_Z : DELAY_Z) IDLE;
+ end
+ GNT0 : if (req_0 == 1'b1) begin
+ #(DELAY_RISE : DELAY_RISE : DELAY_FALL) next_state = GNT0;
+ end else begin
+ #DELAY_RISE next_state = IDLE;
+ end
+ GNT1 : if (req_1 == 1'b1) begin
+ #10 next_state = GNT1;
+ end else begin
+ #(10:10:15, 20:25:25) next_state = IDLE;
+ end
+ default : next_state = IDLE;
+ endcase
+ end
+
+ always @ (posedge clock)
+ begin : FSM_SEQ
+ if (reset == 1'b1) begin
+ #(10:10:15) state <= IDLE;
+ end else begin
+ #(10) state <= next_state;
+ end
+ end
+
+ always @ (posedge clock)
+ begin : FSM_OUTPUT
+ if (reset == 1'b1) begin
+ gnt_0 <= #(8:9:10) 1'b0;
+ gnt_1 <= #1 1'b0;
+ end else begin
+ case (state)
+ IDLE : begin
+ gnt_0 <= #(8:9:10) 1'b0;
+ gnt_1 <= #1 1'b0;
+ end
+ GNT0 : begin
+ gnt_0 <= #(4:5:6,8:9:10) 1'b1;
+ gnt_1 <= #1 1'b0;
+ end
+ GNT1 : begin
+ gnt_0 <= #(2:3:4,4:5:6,8:9:10) 1'b0;
+ gnt_1 <= #1 1'b1;
+ end
+ default : begin
+ gnt_0 <= 1'b0;
+ gnt_1 <= 1'b0;
+ end
+ endcase
+ end
+ end
+endmodule
+EOT
+
+design -reset
+logger -expect-no-warnings
+read_verilog <<EOT
+module test;
+ reg q;
+ initial begin
+ q = 1;
+ #(1:2:2) q = 0;
+ end
+endmodule
+EOT
+
+design -reset
+logger -expect-no-warnings
+read_verilog <<EOT
+module test #(parameter hyst = 16)
+ (input [0:1] inA, input rst, output reg out);
+ parameter real updatePeriod = 100.0;
+ initial out = 1'b0;
+ always #(updatePeriod-5:updatePeriod:updatePeriod+5) begin
+ if (rst) out <= 1'b0;
+ else if (inA[0] > inA[1]) out <= 1'b1;
+ else if (inA[0] < inA[1] - hyst) out <= 1'b0;
+ end
+endmodule
+EOT
+
+design -reset
+logger -expect-no-warnings
+read_verilog <<EOT
+module test;
+ reg clk;
+ initial clk = 1'b0;
+ always #(100:180:230) clk = ~clk;
+endmodule
+EOT
+
+design -reset
+logger -expect-no-warnings
+read_verilog <<EOT
+module test;
+ reg clk;
+ initial clk = 1'b0;
+ always clk = #(100:180:230, 100:180:230) ~clk;
+ task t_test;
+ sig_036_A <= #(2, 4, 5.5) 0;
+ sig_036_B <= #(1.3, 3) 0;
+ sig_036_S <= #(2) 0;
+ #(100 : 200 : 300, 400 : 500 : 600, 700 : 800 : 900);
+ sig_036_A <= #(1.5:2.5:3.0, 3:4:5, 7) ~0;
+ sig_036_B <= #(2, 4:6:6) ~0;
+ sig_036_S <= #(1.5:2.5:3.0) ~0;
+ #100;
+ endtask
+endmodule
+EOT
diff --git a/tests/verilog/delay_risefall.ys b/tests/verilog/delay_risefall.ys
new file mode 100644
index 000000000..ffbe1909d
--- /dev/null
+++ b/tests/verilog/delay_risefall.ys
@@ -0,0 +1,225 @@
+logger -expect-no-warnings
+read_verilog <<EOT
+module test (a, b, c, y);
+ input a;
+ input signed [1:0] b;
+ input signed [2:0] c;
+ output y;
+ assign #(12.5, 14.5) y = ^(a ? b : c);
+endmodule
+EOT
+
+design -reset
+logger -expect-no-warnings
+read_verilog << EOT
+module test (input [7:0] a, b, c, d, output [7:0] x, y, z);
+ assign #(20, 20, 25) x = a + b, y = b + c, z = c + d;
+endmodule
+EOT
+
+design -reset
+logger -expect-no-warnings
+read_verilog <<EOT
+module test (a, b, c, y);
+ localparam TIME_STEP = 0.011;
+ input signed [3:0] a;
+ input signed [1:0] b;
+ input signed [1:0] c;
+ output [5:0] y;
+ assign #(TIME_STEP, TIME_STEP, TIME_STEP) y = (a >> b) >>> c;
+endmodule
+EOT
+
+design -reset
+logger -expect-no-warnings
+read_verilog <<EOT
+module test;
+ localparam TIME_STEP = 0.7;
+ wire o, a, b;
+ and #(TIME_STEP, 2) and_gate (o, a, b);
+ wire #(0, TIME_STEP, TIME_STEP) x;
+ assign o = x;
+endmodule
+EOT
+
+design -reset
+logger -expect warning "Yosys has only limited support for tri-state logic at the moment." 1
+read_verilog <<EOT
+module test (input en, input a, input b, output c);
+ wire [15:0] add0_res = a + b;
+ assign #(3, 3) c = (en) ? a : 1'bz;
+endmodule
+EOT
+
+design -reset
+logger -expect-no-warnings
+read_verilog <<EOT
+module test (input en, d, t_rise, t_fall);
+ reg o;
+ always @*
+ if (en)
+ o = #(t_rise, t_fall, 50) ~d;
+endmodule
+EOT
+
+design -reset
+logger -expect-no-warnings
+read_verilog <<EOT
+module test #(parameter DELAY_RISE = 0, DELAY_FALL = 0, DELAY_Z = 0)
+ (input clock, input reset, input req_0, input req_1, output gnt_0, output gnt_1);
+ parameter SIZE = 3;
+ parameter IDLE = 3'b001, GNT0 = 3'b010, GNT1 = 3'b100;
+ reg [SIZE-1:0] state;
+ reg [SIZE-1:0] next_state;
+ reg gnt_0, gnt_1;
+
+ always @ (state or req_0 or req_1)
+ begin : FSM_COMBO
+ next_state = 3'b000;
+ case (state)
+ IDLE : if (req_0 == 1'b1) begin
+ next_state = #(DELAY_RISE * 2) GNT0;
+ end else if (req_1 == 1'b1) begin
+ next_state = #(DELAY_RISE * 2.5, DELAY_FALL) GNT1;
+ end else begin
+ next_state = #(DELAY_RISE * 2.5, DELAY_FALL, DELAY_Z) IDLE;
+ end
+ GNT0 : if (req_0 == 1'b1) begin
+ #(DELAY_RISE, DELAY_FALL) next_state = GNT0;
+ end else begin
+ #DELAY_RISE next_state = IDLE;
+ end
+ GNT1 : if (req_1 == 1'b1) begin
+ #10 next_state = GNT1;
+ end else begin
+ #(10) next_state = IDLE;
+ end
+ default : next_state = IDLE;
+ endcase
+ end
+
+ always @ (posedge clock)
+ begin : FSM_SEQ
+ if (reset == 1'b1) begin
+ #3 state <= IDLE;
+ end else begin
+ #(1, 3) state <= next_state;
+ end
+ end
+
+ always @ (posedge clock)
+ begin : FSM_OUTPUT
+ if (reset == 1'b1) begin
+ gnt_0 <= #(DELAY_RISE, DELAY_FALL, DELAY_Z) 1'b0;
+ gnt_1 <= #1 1'b0;
+ end else begin
+ case (state)
+ IDLE : begin
+ gnt_0 <= #(DELAY_RISE, DELAY_FALL, DELAY_Z) 1'b0;
+ gnt_1 <= #1 1'b0;
+ end
+ GNT0 : begin
+ gnt_0 <= #(DELAY_RISE, DELAY_FALL) 1'b1;
+ gnt_1 <= #1 1'b0;
+ end
+ GNT1 : begin
+ gnt_0 <= #(DELAY_RISE) 1'b0;
+ gnt_1 <= #1 1'b1;
+ end
+ default : begin
+ gnt_0 <= 1'b0;
+ gnt_1 <= 1'b0;
+ end
+ endcase
+ end
+ end
+endmodule
+EOT
+
+design -reset
+logger -expect-no-warnings
+read_verilog <<EOT
+module test;
+ reg q;
+ initial #(1,2) q = 1;
+endmodule
+EOT
+
+design -reset
+logger -expect-no-warnings
+read_verilog <<EOT
+module test #(parameter hyst = 16)
+ (input [0:1] inA, input rst, output reg out);
+ parameter real updatePeriod = 100.0;
+ initial out = 1'b0;
+ always #updatePeriod begin
+ if (rst) out <= 1'b0;
+ else if (inA[0] > inA[1]) out <= 1'b1;
+ else if (inA[0] < inA[1] - hyst) out <= 1'b0;
+ end
+endmodule
+EOT
+
+design -reset
+logger -expect-no-warnings
+read_verilog <<EOT
+module test #(parameter hyst = 16)
+ (input [0:1] inA, input rst, output reg out);
+ parameter updatePeriod = (100:125:200);
+ initial out = 1'b0;
+ always #updatePeriod begin
+ if (rst) out <= 1'b0;
+ else if (inA[0] > inA[1]) out <= 1'b1;
+ else if (inA[0] < inA[1] - hyst) out <= 1'b0;
+ end
+endmodule
+EOT
+
+design -reset
+logger -expect-no-warnings
+read_verilog <<EOT
+module test;
+ reg clk;
+ initial clk = 1'b0;
+ always #(100, 180, 230) clk = ~clk;
+endmodule
+EOT
+
+design -reset
+logger -expect-no-warnings
+read_verilog <<EOT
+module test;
+ reg clk;
+ initial clk = 1'b0;
+ always clk = #(100, 180, 230) ~clk;
+ task t_test;
+ sig_036_A <= #(2, 4, 5.5) 0;
+ sig_036_B <= #(1.3, 3) 0;
+ sig_036_S <= #(2) 0;
+ #(100, 200, 300);
+ sig_036_A <= #(2 : 3 : 5) ~0;
+ sig_036_B <= #(4 : 6 : 6, 10) ~0;
+ sig_036_S <= #(1 : 2 : 3, 2 : 2 : 3, 10) ~0;
+ #100;
+ endtask
+endmodule
+EOT
+
+design -reset
+logger -expect-no-warnings
+read_verilog <<EOT
+module test (clk, en, i, o);
+ input clk, en, i;
+ reg p;
+ output o;
+ always @ (posedge clk)
+ begin
+ if (en) begin
+ p <= #(5:15:25, 20, 30) i;
+ end else begin
+ #(5, 3:5:8, 10) p <= i;
+ end
+ end
+ assign #(10, 20, 15:20:30) o = p;
+endmodule
+EOT
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_arg_mismatch_1.ys b/tests/verilog/func_arg_mismatch_1.ys
new file mode 100644
index 000000000..a0e82db0c
--- /dev/null
+++ b/tests/verilog/func_arg_mismatch_1.ys
@@ -0,0 +1,12 @@
+logger -expect error "Incompatible re-declaration of wire" 1
+read_verilog -sv <<EOT
+module top;
+ function automatic integer f;
+ input [0:0] inp;
+ integer inp;
+ f = inp;
+ endfunction
+ integer x, y;
+ initial x = f(y);
+endmodule
+EOT
diff --git a/tests/verilog/func_arg_mismatch_2.ys b/tests/verilog/func_arg_mismatch_2.ys
new file mode 100644
index 000000000..c2c29c1fb
--- /dev/null
+++ b/tests/verilog/func_arg_mismatch_2.ys
@@ -0,0 +1,12 @@
+logger -expect error "Incompatible re-declaration of constant function wire" 1
+read_verilog -sv <<EOT
+module top;
+ function automatic integer f;
+ input [0:0] inp;
+ integer inp;
+ f = inp;
+ endfunction
+ integer x;
+ initial x = f(0);
+endmodule
+EOT
diff --git a/tests/verilog/func_arg_mismatch_3.ys b/tests/verilog/func_arg_mismatch_3.ys
new file mode 100644
index 000000000..892824c09
--- /dev/null
+++ b/tests/verilog/func_arg_mismatch_3.ys
@@ -0,0 +1,12 @@
+logger -expect error "Incompatible re-declaration of wire" 1
+read_verilog -sv <<EOT
+module top;
+ function automatic integer f;
+ input [1:0] inp;
+ integer inp;
+ f = inp;
+ endfunction
+ integer x, y;
+ initial x = f(y);
+endmodule
+EOT
diff --git a/tests/verilog/func_arg_mismatch_4.ys b/tests/verilog/func_arg_mismatch_4.ys
new file mode 100644
index 000000000..87ec1c299
--- /dev/null
+++ b/tests/verilog/func_arg_mismatch_4.ys
@@ -0,0 +1,12 @@
+logger -expect error "Incompatible re-declaration of constant function wire" 1
+read_verilog -sv <<EOT
+module top;
+ function automatic integer f;
+ input [1:0] inp;
+ integer inp;
+ f = inp;
+ endfunction
+ integer x;
+ initial x = f(0);
+endmodule
+EOT
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/genblk_case.v b/tests/verilog/genblk_case.v
new file mode 100644
index 000000000..081fb09d3
--- /dev/null
+++ b/tests/verilog/genblk_case.v
@@ -0,0 +1,26 @@
+module top;
+ parameter YES = 1;
+ generate
+ if (YES) wire y;
+ else wire n;
+
+ if (!YES) wire n;
+ else wire y;
+
+ case (YES)
+ 1: wire y;
+ 0: wire n;
+ endcase
+
+ case (!YES)
+ 0: wire y;
+ 1: wire n;
+ endcase
+
+ if (YES) wire y;
+ else wire n;
+
+ if (!YES) wire n;
+ else wire y;
+ endgenerate
+endmodule
diff --git a/tests/verilog/genblk_case.ys b/tests/verilog/genblk_case.ys
new file mode 100644
index 000000000..3c1bb51f9
--- /dev/null
+++ b/tests/verilog/genblk_case.ys
@@ -0,0 +1,15 @@
+read_verilog genblk_case.v
+
+select -assert-count 0 top/genblk1.n
+select -assert-count 0 top/genblk2.n
+select -assert-count 0 top/genblk3.n
+select -assert-count 0 top/genblk4.n
+select -assert-count 0 top/genblk5.n
+select -assert-count 0 top/genblk6.n
+
+select -assert-count 1 top/genblk1.y
+select -assert-count 1 top/genblk2.y
+select -assert-count 1 top/genblk3.y
+select -assert-count 1 top/genblk4.y
+select -assert-count 1 top/genblk5.y
+select -assert-count 1 top/genblk6.y
diff --git a/tests/verilog/genblk_port_decl.ys b/tests/verilog/genblk_port_decl.ys
new file mode 100644
index 000000000..589d3d2e1
--- /dev/null
+++ b/tests/verilog/genblk_port_decl.ys
@@ -0,0 +1,12 @@
+logger -expect error "Cannot declare module port `\\x' within a generate block\." 1
+read_verilog <<EOT
+module top(x);
+ generate
+ if (1) begin : blk
+ output wire x;
+ assign x = 1;
+ end
+ endgenerate
+ output wire x;
+endmodule
+EOT
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/hidden_decl.ys b/tests/verilog/hidden_decl.ys
new file mode 100644
index 000000000..aed7847dc
--- /dev/null
+++ b/tests/verilog/hidden_decl.ys
@@ -0,0 +1,11 @@
+logger -expect error "Identifier `\\y' is implicitly declared and `default_nettype is set to none" 1
+read_verilog <<EOT
+`default_nettype none
+module top1;
+ wire x;
+ generate
+ if (1) wire y;
+ endgenerate
+ assign x = y;
+endmodule
+EOT
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/include_self.v b/tests/verilog/include_self.v
new file mode 100644
index 000000000..23ffc7104
--- /dev/null
+++ b/tests/verilog/include_self.v
@@ -0,0 +1,30 @@
+`ifdef GUARD_5
+module top;
+ wire x;
+endmodule
+
+`elsif GUARD_4
+`define GUARD_5
+`include "include_self.v"
+
+`elsif GUARD_3
+`define GUARD_4
+`include "include_self.v"
+
+`elsif GUARD_2
+`define GUARD_3
+`include "include_self.v"
+
+`elsif GUARD_1
+`define GUARD_2
+`include "include_self.v"
+
+`elsif GUARD_0
+`define GUARD_1
+`include "include_self.v"
+
+`else
+`define GUARD_0
+`include "include_self.v"
+
+`endif
diff --git a/tests/verilog/include_self.ys b/tests/verilog/include_self.ys
new file mode 100644
index 000000000..07d840d68
--- /dev/null
+++ b/tests/verilog/include_self.ys
@@ -0,0 +1,2 @@
+read_verilog include_self.v
+select -assert-count 1 top/x
diff --git a/tests/verilog/int_types.sv b/tests/verilog/int_types.sv
new file mode 100644
index 000000000..8133f8218
--- /dev/null
+++ b/tests/verilog/int_types.sv
@@ -0,0 +1,47 @@
+`define TEST(typ, width, is_signed) \
+ if (1) begin \
+ typ x = -1; \
+ localparam typ y = -1; \
+ logic [127:0] a = x; \
+ logic [127:0] b = y; \
+ if ($bits(x) != width) \
+ $error(`"typ doesn't have expected size width`"); \
+ if ($bits(x) != $bits(y)) \
+ $error(`"localparam typ doesn't match size of typ`"); \
+ function automatic typ f; \
+ input integer x; \
+ f = x; \
+ endfunction \
+ logic [127:0] c = f(-1); \
+ always @* begin \
+ assert (x == y); \
+ assert (a == b); \
+ assert (a == c); \
+ assert ((a == -1) == is_signed); \
+ end \
+ end
+
+`define TEST_INTEGER_ATOM(typ, width) \
+ `TEST(typ, width, 1) \
+ `TEST(typ signed, width, 1) \
+ `TEST(typ unsigned, width, 0)
+
+`define TEST_INTEGER_VECTOR(typ) \
+ `TEST(typ, 1, 0) \
+ `TEST(typ signed, 1, 1) \
+ `TEST(typ unsigned, 1, 0) \
+ `TEST(typ [1:0], 2, 0) \
+ `TEST(typ signed [1:0], 2, 1) \
+ `TEST(typ unsigned [1:0], 2, 0)
+
+module top;
+ `TEST_INTEGER_ATOM(integer, 32)
+ `TEST_INTEGER_ATOM(int, 32)
+ `TEST_INTEGER_ATOM(shortint, 16)
+ `TEST_INTEGER_ATOM(longint, 64)
+ `TEST_INTEGER_ATOM(byte, 8)
+
+ `TEST_INTEGER_VECTOR(reg)
+ `TEST_INTEGER_VECTOR(logic)
+ `TEST_INTEGER_VECTOR(bit)
+endmodule
diff --git a/tests/verilog/int_types.ys b/tests/verilog/int_types.ys
new file mode 100644
index 000000000..c17c44b4c
--- /dev/null
+++ b/tests/verilog/int_types.ys
@@ -0,0 +1,7 @@
+read_verilog -sv int_types.sv
+hierarchy
+proc
+flatten
+opt -full
+select -module top
+sat -verify -seq 1 -tempinduct -prove-asserts -show-all
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/macro_unapplied.ys b/tests/verilog/macro_unapplied.ys
new file mode 100644
index 000000000..81eb10b8b
--- /dev/null
+++ b/tests/verilog/macro_unapplied.ys
@@ -0,0 +1,17 @@
+logger -expect-no-warnings
+read_verilog -sv <<EOT
+`define MACRO(a = 1, b = 2) initial $display("MACRO(a = %d, b = %d)", a, b)
+module top;
+ `MACRO();
+endmodule
+EOT
+
+design -reset
+
+logger -expect error "Expected to find '\(' to begin macro arguments for 'MACRO', but instead found ';'" 1
+read_verilog -sv <<EOT
+`define MACRO(a = 1, b = 2) initial $display("MACRO(a = %d, b = %d)", a, b)
+module top;
+ `MACRO;
+endmodule
+EOT
diff --git a/tests/verilog/macro_unapplied_newline.ys b/tests/verilog/macro_unapplied_newline.ys
new file mode 100644
index 000000000..a3f88d5b4
--- /dev/null
+++ b/tests/verilog/macro_unapplied_newline.ys
@@ -0,0 +1,5 @@
+logger -expect error "Expected to find '\(' to begin macro arguments for 'foo', but instead found '\\x0a'" 1
+read_verilog -sv <<EOT
+`define foo(a=1) (a)
+`foo
+EOT
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_int_types.sv b/tests/verilog/param_int_types.sv
new file mode 100644
index 000000000..3228369b8
--- /dev/null
+++ b/tests/verilog/param_int_types.sv
@@ -0,0 +1,19 @@
+module gate(out);
+ parameter integer a = -1;
+ parameter int b = -2;
+ parameter shortint c = -3;
+ parameter longint d = -4;
+ parameter byte e = -5;
+ output wire [1023:0] out;
+ assign out = {a, b, c, d, e};
+endmodule
+
+module gold(out);
+ integer a = -1;
+ int b = -2;
+ shortint c = -3;
+ longint d = -4;
+ byte e = -5;
+ output wire [1023:0] out;
+ assign out = {a, b, c, d, e};
+endmodule
diff --git a/tests/verilog/param_int_types.ys b/tests/verilog/param_int_types.ys
new file mode 100644
index 000000000..7727801cf
--- /dev/null
+++ b/tests/verilog/param_int_types.ys
@@ -0,0 +1,5 @@
+read_verilog -sv param_int_types.sv
+proc
+equiv_make gold gate equiv
+equiv_simple
+equiv_status -assert
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/port_int_types.sv b/tests/verilog/port_int_types.sv
new file mode 100644
index 000000000..40e2cf14a
--- /dev/null
+++ b/tests/verilog/port_int_types.sv
@@ -0,0 +1,50 @@
+`define INITS \
+ assign a = -1; \
+ assign b = -2; \
+ assign c = -3; \
+ assign d = -4; \
+ assign a_ext = a; \
+ assign b_ext = b; \
+ assign c_ext = c; \
+ assign d_ext = d;
+
+module gate_a(
+ output byte a,
+ output byte unsigned b,
+ output shortint c,
+ output shortint unsigned d,
+ output [31:0] a_ext,
+ output [31:0] b_ext,
+ output [31:0] c_ext,
+ output [31:0] d_ext
+);
+ `INITS
+endmodule
+
+module gate_b(
+ a, b, c, d,
+ a_ext, b_ext, c_ext, d_ext
+);
+ output byte a;
+ output byte unsigned b;
+ output shortint c;
+ output shortint unsigned d;
+ output [31:0] a_ext;
+ output [31:0] b_ext;
+ output [31:0] c_ext;
+ output [31:0] d_ext;
+ `INITS
+endmodule
+
+module gold(
+ output signed [7:0] a,
+ output unsigned [7:0] b,
+ output signed [15:0] c,
+ output unsigned [15:0] d,
+ output [31:0] a_ext,
+ output [31:0] b_ext,
+ output [31:0] c_ext,
+ output [31:0] d_ext
+);
+ `INITS
+endmodule
diff --git a/tests/verilog/port_int_types.ys b/tests/verilog/port_int_types.ys
new file mode 100644
index 000000000..75888e1a8
--- /dev/null
+++ b/tests/verilog/port_int_types.ys
@@ -0,0 +1,11 @@
+read_verilog -sv port_int_types.sv
+equiv_make gold gate_a equiv
+equiv_simple
+equiv_status -assert
+
+design -reset
+
+read_verilog -sv port_int_types.sv
+equiv_make gold gate_b equiv
+equiv_simple
+equiv_status -assert
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/run-test.sh b/tests/verilog/run-test.sh
index ea56b70f0..2f91cf0fd 100755
--- a/tests/verilog/run-test.sh
+++ b/tests/verilog/run-test.sh
@@ -1,20 +1,4 @@
#!/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
+set -eu
+source ../gen-tests-makefile.sh
+run_tests --yosys-scripts --bash
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_else.ys b/tests/verilog/unmatched_else.ys
new file mode 100644
index 000000000..413f413c3
--- /dev/null
+++ b/tests/verilog/unmatched_else.ys
@@ -0,0 +1,6 @@
+logger -expect error "Found `else outside of macro conditional branch!" 1
+read_verilog <<EOT
+module top;
+`else
+endmodule
+EOT
diff --git a/tests/verilog/unmatched_elsif.ys b/tests/verilog/unmatched_elsif.ys
new file mode 100644
index 000000000..e0ed0aa49
--- /dev/null
+++ b/tests/verilog/unmatched_elsif.ys
@@ -0,0 +1,6 @@
+logger -expect error "Found `elsif outside of macro conditional branch!" 1
+read_verilog <<EOT
+module top;
+`elsif
+endmodule
+EOT
diff --git a/tests/verilog/unmatched_endif.ys b/tests/verilog/unmatched_endif.ys
new file mode 100644
index 000000000..39d60381d
--- /dev/null
+++ b/tests/verilog/unmatched_endif.ys
@@ -0,0 +1,6 @@
+logger -expect error "Found `endif outside of macro conditional branch!" 1
+read_verilog <<EOT
+module top;
+`endif
+endmodule
+EOT
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/verilog/unnamed_block.ys b/tests/verilog/unnamed_block.ys
new file mode 100644
index 000000000..0f209a089
--- /dev/null
+++ b/tests/verilog/unnamed_block.ys
@@ -0,0 +1,28 @@
+read_verilog <<EOT
+module top;
+ initial begin : blk
+ integer x;
+ end
+endmodule
+EOT
+
+delete
+
+read_verilog -sv <<EOT
+module top;
+ initial begin
+ integer x;
+ end
+endmodule
+EOT
+
+delete
+
+logger -expect error "Local declaration in unnamed block is only supported in SystemVerilog mode!" 1
+read_verilog <<EOT
+module top;
+ initial begin
+ integer x;
+ end
+endmodule
+EOT
diff --git a/tests/verilog/unnamed_genblk.sv b/tests/verilog/unnamed_genblk.sv
new file mode 100644
index 000000000..41828b1b0
--- /dev/null
+++ b/tests/verilog/unnamed_genblk.sv
@@ -0,0 +1,39 @@
+// This test is taken directly from Section 27.6 of IEEE 1800-2017
+
+module top;
+ parameter genblk2 = 0;
+ genvar i;
+
+ // The following generate block is implicitly named genblk1
+
+ if (genblk2) logic a; // top.genblk1.a
+ else logic b; // top.genblk1.b
+
+ // The following generate block is implicitly named genblk02
+ // as genblk2 is already a declared identifier
+
+ if (genblk2) logic a; // top.genblk02.a
+ else logic b; // top.genblk02.b
+
+ // The following generate block would have been named genblk3
+ // but is explicitly named g1
+
+ for (i = 0; i < 1; i = i + 1) begin : g1 // block name
+ // The following generate block is implicitly named genblk1
+ // as the first nested scope inside g1
+ if (1) logic a; // top.g1[0].genblk1.a
+ end
+
+ // The following generate block is implicitly named genblk4 since
+ // it belongs to the fourth generate construct in scope "top".
+ // The previous generate block would have been
+ // named genblk3 if it had not been explicitly named g1
+
+ for (i = 0; i < 1; i = i + 1)
+ // The following generate block is implicitly named genblk1
+ // as the first nested generate block in genblk4
+ if (1) logic a; // top.genblk4[0].genblk1.a
+
+ // The following generate block is implicitly named genblk5
+ if (1) logic a; // top.genblk5.a
+endmodule
diff --git a/tests/verilog/unnamed_genblk.ys b/tests/verilog/unnamed_genblk.ys
new file mode 100644
index 000000000..2b9aa9d69
--- /dev/null
+++ b/tests/verilog/unnamed_genblk.ys
@@ -0,0 +1,8 @@
+read_verilog -sv unnamed_genblk.sv
+select -assert-count 0 top/genblk1.a
+select -assert-count 1 top/genblk02.b
+select -assert-count 0 top/genblk1.a
+select -assert-count 1 top/genblk02.b
+select -assert-count 1 top/g1[0].genblk1.a
+select -assert-count 1 top/genblk4[0].genblk1.a
+select -assert-count 1 top/genblk5.a
diff --git a/tests/verilog/wire_and_var.sv b/tests/verilog/wire_and_var.sv
new file mode 100644
index 000000000..79c7c04c6
--- /dev/null
+++ b/tests/verilog/wire_and_var.sv
@@ -0,0 +1,33 @@
+`define TEST(kwd) \
+ kwd kwd``_1; \
+ kwd kwd``_2; \
+ initial kwd``_1 = 1; \
+ assign kwd``_2 = 1;
+
+`define TEST_VAR(kwd) \
+ var kwd var_``kwd``_1; \
+ var kwd var_``kwd``_2; \
+ initial var_``kwd``_1 = 1; \
+ assign var_``kwd``_2 = 1;
+
+`define TEST_WIRE(kwd) \
+ wire kwd wire_``kwd``_1; \
+ wire kwd wire_``kwd``_2; \
+ initial wire_``kwd``_1 = 1; \
+ assign wire_``kwd``_2 = 1;
+
+module top;
+
+`TEST(wire) // wire assigned in a block
+`TEST(reg) // reg assigned in a continuous assignment
+`TEST(logic)
+`TEST(integer)
+
+`TEST_VAR(reg) // reg assigned in a continuous assignment
+`TEST_VAR(logic)
+`TEST_VAR(integer)
+
+`TEST_WIRE(logic) // wire assigned in a block
+`TEST_WIRE(integer) // wire assigned in a block
+
+endmodule
diff --git a/tests/verilog/wire_and_var.ys b/tests/verilog/wire_and_var.ys
new file mode 100644
index 000000000..9359a9d55
--- /dev/null
+++ b/tests/verilog/wire_and_var.ys
@@ -0,0 +1,9 @@
+logger -expect warning "wire '\\wire_1' is assigned in a block" 1
+logger -expect warning "reg '\\reg_2' is assigned in a continuous assignment" 1
+
+logger -expect warning "reg '\\var_reg_2' is assigned in a continuous assignment" 1
+
+logger -expect warning "wire '\\wire_logic_1' is assigned in a block" 1
+logger -expect warning "wire '\\wire_integer_1' is assigned in a block" 1
+
+read_verilog -sv wire_and_var.sv
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