diff --git a/.github/test.sh b/.github/test.sh deleted file mode 100755 index 362020f3d..000000000 --- a/.github/test.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env sh - -echo "Using the bundled ivtest to run regression tests." -echo " pwd = $(pwd)" - -cd ivtest - -status=0 - -perl vvp_reg.pl || status=1 - -if [ "x$1" = "xno-pli1" ] ; then - perl vpi_reg.pl || status=1 -else - perl vpi_reg.pl --with-pli1 || status=1 -fi - -python3 vvp_reg.py || status=1 - -exit $status diff --git a/.github/workflows/deploy_docs.yml b/.github/workflows/deploy_docs.yml index 1641fec05..7abfd6fbf 100644 --- a/.github/workflows/deploy_docs.yml +++ b/.github/workflows/deploy_docs.yml @@ -19,10 +19,15 @@ jobs: - name: Install dependencies run: | sudo apt update -qq - sudo apt install -y make autoconf python3-sphinx + sudo apt install -y make autoconf python3-venv + python3 -m venv .venv + . .venv/bin/activate + pip install --upgrade pip + pip install -r Documentation/requirements.txt - name: Make Documentation run: | + . .venv/bin/activate cd Documentation make html diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5197876b9..0e9b818d0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,60 +14,82 @@ jobs: mac: strategy: fail-fast: false + matrix: + libvvp: [true] + suffix: [true] runs-on: macos-15-intel - name: '🍏 macOS' + name: 🍏 macOS${{ matrix.libvvp && ' +libvvp' || '' }}${{ matrix.suffix && ' +suffix' || '' }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install dependencies run: | brew install bison - pip3 install --break-system-packages docopt - name: Build, check and install run: | export PATH="/usr/local/opt/bison/bin:$PATH" + CONFIG_OPTS="--enable-libveriuser" + if [ "${{ matrix.libvvp }}" = "true" ]; then + CONFIG_OPTS="$CONFIG_OPTS --enable-libvvp" + fi + if [ "${{ matrix.suffix }}" = "true" ]; then + CONFIG_OPTS="$CONFIG_OPTS --enable-suffix" + fi autoconf - ./configure --enable-libveriuser + ./configure $CONFIG_OPTS make -j$(nproc) check sudo make install - name: Test - run: ./.github/test.sh + run: | + make check-installed lin: strategy: fail-fast: false matrix: - os: [ - '22.04', - '24.04' - ] + os: ['22.04', '24.04'] + # libvvp: [false, true] + # suffix: [false, true] runs-on: ubuntu-${{ matrix.os }} - name: '🐧 Ubuntu ${{ matrix.os }}' + name: 🐧 Ubuntu ${{ matrix.os }}${{ matrix.libvvp && ' +libvvp' || '' }}${{ matrix.suffix && ' +suffix' || '' }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install dependencies run: | sudo apt update -qq - sudo apt install -y make g++ git bison flex gperf libreadline-dev libbz2-dev autoconf python3-sphinx python3-docopt + sudo apt install -y make g++ git bison flex gperf libreadline-dev libbz2-dev autoconf python3-venv + python3 -m venv .venv + . .venv/bin/activate + pip install --upgrade pip + pip install -r Documentation/requirements.txt - name: Build, check and install run: | + CONFIG_OPTS="--enable-libveriuser" + if [ "${{ matrix.libvvp }}" = "true" ]; then + CONFIG_OPTS="$CONFIG_OPTS --enable-libvvp" + fi + if [ "${{ matrix.suffix }}" = "true" ]; then + CONFIG_OPTS="$CONFIG_OPTS --enable-suffix" + fi autoconf - ./configure --enable-libveriuser + ./configure $CONFIG_OPTS make -j$(nproc) check sudo make install - name: Test - run: ./.github/test.sh + run: + make check-installed - name: Documentation run: | + . .venv/bin/activate cd Documentation make html @@ -76,11 +98,14 @@ jobs: strategy: fail-fast: false matrix: + msystem: [MINGW64, UCRT64, CLANG64] + # libvvp: [false, true] + # suffix: [false, true] include: - { msystem: MINGW64, env: x86_64 } - { msystem: UCRT64, env: ucrt-x86_64 } - { msystem: CLANG64, env: clang-x86_64 } - name: 🟪 ${{ matrix.msystem}} + name: 🟪 ${{ matrix.msystem }}${{ matrix.libvvp && ' +libvvp' || '' }}${{ matrix.suffix && ' +suffix' || '' }} defaults: run: shell: msys2 {0} @@ -91,7 +116,7 @@ jobs: - run: git config --global core.autocrlf input shell: bash - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: msys2/setup-msys2@v2 with: @@ -103,16 +128,24 @@ jobs: python-pip mingw-w64-${{ matrix.env }}-perl - - uses: actions/setup-python@v5 + - uses: actions/setup-python@v6 with: python-version: '>=3.5' - name: Build and check run: | cd msys2 + CONFIG_OPTS="" if [ ${{ matrix.msystem }} != "CLANG64" ] ; then - export IVL_CONFIG_OPTIONS="--enable-libveriuser" + CONFIG_OPTS="$CONFIG_OPTS --enable-libveriuser" fi + if [ "${{ matrix.libvvp }}" = "true" ] ; then + CONFIG_OPTS="$CONFIG_OPTS --enable-libvvp" + fi + if [ "${{ matrix.suffix }}" = "true" ]; then + CONFIG_OPTS="$CONFIG_OPTS --enable-suffix" + fi + export IVL_CONFIG_OPTIONS="$CONFIG_OPTS" makepkg-mingw --noconfirm --noprogressbar -sCLf - name: Install @@ -120,13 +153,9 @@ jobs: - name: Test run: | - if [ ${{ matrix.msystem }} = "CLANG64" ] ; then - ./.github/test.sh no-pli1 - else - ./.github/test.sh - fi + make check-installed - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v7 with: - name: ${{ matrix.msystem }} + name: 🟪 ${{ matrix.msystem }}${{ matrix.libvvp && ' +libvvp' || '' }} path: msys2/*.zst diff --git a/.gitignore b/.gitignore index 7343305f2..8453660e6 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,10 @@ *.swp *~ +# Virtual environments +.conda/ +.venv/ + # Top level generic files tags TAGS @@ -31,16 +35,19 @@ Makefile /_pli_types.h config.h /tgt-pcb/pcb_config.h -/tgt-pcb/fp.cc -/tgt-pcb/fp.h -/tgt-pcb/fp.output -/tgt-pcb/fp_lex.cc /tgt-vvp/vvp_config.h /tgt-vhdl/vhdl_config.h +/vhdlpp/vhdlpp_config.h /vpi/vpi_config.h stamp-*-h -/version.h /version_tag.h +/version_base.h + +/driver-vpi/iverilog-vpi.man +/driver-vpi/res.rc +/driver/iverilog.man +/vvp/libvvp.pc +/vvp/vvp.man # Directories /devel/ @@ -53,8 +60,6 @@ dep *.vpi /cadpli/cadpli.vpl -/tgt-blif/Makefile - # lex, yacc and gperf output /driver/cflexor.c /driver/cfparse.c @@ -63,14 +68,6 @@ dep /ivlpp/lexor.c -/vhdlpp/lexor.cc -/vhdlpp/lexor_keyword.cc -/vhdlpp/parse.cc -/vhdlpp/parse.h -/vhdlpp/parse.output -/vhdlpp/vhdlpp_config.h -/vhdlpp/vhdlpp - /lexor.cc /lexor_keyword.cc /parse.cc @@ -79,6 +76,17 @@ dep /syn-rules.cc /syn-rules.output +/tgt-pcb/fp.cc +/tgt-pcb/fp.h +/tgt-pcb/fp.output +/tgt-pcb/fp_lex.cc + +/vhdlpp/lexor.cc +/vhdlpp/lexor_keyword.cc +/vhdlpp/parse.cc +/vhdlpp/parse.h +/vhdlpp/parse.output + /vpi/sdf_lexor.c /vpi/sdf_parse.c /vpi/sdf_parse.h @@ -98,17 +106,13 @@ dep # Program created files /vvp/tables.cc -/iverilog-vpi.man -/driver-vpi/res.rc -/driver/iverilog.man -/vvp/vvp.man - # The executables. *.exe /driver/iverilog -/iverilog-vpi +/driver-vpi/iverilog-vpi /ivl /ivlpp/ivlpp +/vhdlpp/vhdlpp /vvp/vvp /ivl.exp @@ -116,3 +120,4 @@ dep # Check output /check.vvp +/driver/top.vvp diff --git a/Documentation/conf.py b/Documentation/conf.py index 282a520c4..619872ce1 100644 --- a/Documentation/conf.py +++ b/Documentation/conf.py @@ -73,16 +73,29 @@ highlight_language = 'none' # -- Options for HTML output ------------------------------------------------- +# A dictionary of values to pass into the template engine's context for all pages. +# +html_context = { + # Edit this page + "source_type": "github", + "source_user": "steveicarus", + "source_repo": "iverilog", + "source_version": "master", + "source_docs_path": "/Documentation/", +} + # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'alabaster' +html_theme = 'shibuya' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # -# html_theme_options = {} +html_theme_options = { + "github_url": "https://github.com/steveicarus/iverilog", +} # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, diff --git a/Documentation/developer/version_stamps.rst b/Documentation/developer/version_stamps.rst index 3e84ddb37..5342d9aff 100644 --- a/Documentation/developer/version_stamps.rst +++ b/Documentation/developer/version_stamps.rst @@ -17,7 +17,7 @@ the "make version" target, or automatically if the version_tag.h file doesn't exist at all. This implies that a "make version" is something worth doing when you do a "git pull" or create commits. -The files below are now edited by the Makefile and the version.exe program: +The files below are now edited by the Makefile: * iverilog-vpi.man -- The .TH tag has a version string * driver/iverilog.man -- The .TH tag has a version string diff --git a/Documentation/requirements.txt b/Documentation/requirements.txt new file mode 100644 index 000000000..66dfcfe5a --- /dev/null +++ b/Documentation/requirements.txt @@ -0,0 +1,2 @@ +sphinx==8.1.3 +shibuya==2026.1.9 diff --git a/Documentation/usage/command_line_flags.rst b/Documentation/usage/command_line_flags.rst index fb3f7c7bc..302021957 100644 --- a/Documentation/usage/command_line_flags.rst +++ b/Documentation/usage/command_line_flags.rst @@ -68,6 +68,16 @@ These flags affect the general behavior of the compiler. This flag enables the IEEE1800-2012 standard, which includes SystemVerilog. + * 2017 + + This flag enables the IEEE1800-2017 standard, which includes + SystemVerilog. + + * 2023 + + This flag enables the IEEE1800-2023 standard, which includes + SystemVerilog. + * verilog-ams This flag enables Verilog-AMS features that are supported by Icarus diff --git a/Documentation/usage/installation.rst b/Documentation/usage/installation.rst index 090f020f0..e79d26fa5 100644 --- a/Documentation/usage/installation.rst +++ b/Documentation/usage/installation.rst @@ -373,7 +373,5 @@ Next, compile with the command:: $ make -The configure generated the cross compiler flags, but there are a few -bits that need to be compiled with the native compiler. (version.exe -for example is used by the build process but is not installed.) The +The configure generated the cross compiler flags. The configure script should have gotten all that right. diff --git a/Makefile.in b/Makefile.in index 160af3de5..2503db9c7 100644 --- a/Makefile.in +++ b/Makefile.in @@ -36,9 +36,12 @@ prefix = @prefix@ exec_prefix = @exec_prefix@ srcdir = @srcdir@ datarootdir = @datarootdir@ +VERSION_MAJOR = @VERSION_MAJOR@ +VERSION_MINOR = @VERSION_MINOR@ SUBDIRS = ivlpp vhdlpp vvp vpi tgt-null tgt-stub tgt-vvp \ - tgt-vhdl tgt-vlog95 tgt-pcb tgt-blif tgt-sizer driver + tgt-vhdl tgt-vlog95 tgt-pcb tgt-blif tgt-sizer driver \ + ivtest # Only run distclean for these directories. NOTUSED = tgt-fpga tgt-pal tgt-verilog @@ -48,11 +51,7 @@ else NOTUSED += libveriuser cadpli endif -ifeq (@MINGW32@,yes) SUBDIRS += driver-vpi -else -NOTUSED += driver-vpi -endif # To get the version headers to build correctly we only want to look # for C++ files in the source directory. All other files will require @@ -67,9 +66,7 @@ bindir = @bindir@ libdir = @libdir@ # This is actually the directory where we install our own header files. # It is a little different from the generic includedir. -includedir = @includedir@/iverilog$(suffix) -mandir = @mandir@ -pdfdir = @docdir@ +ivl_includedir = @includedir@/iverilog$(suffix) dllib=@DLLIB@ @@ -132,7 +129,7 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \ PGate.o PGenerate.o PModport.o PNamedItem.o PPackage.o PScope.o PSpec.o PTimingCheck.o \ PTask.o PUdp.o PWire.o Statement.o AStatement.o $M $(FF) $(TT) -all: dep config.h _pli_types.h version_tag.h ivl@EXEEXT@ version.exe iverilog-vpi.man +all: dep config.h _pli_types.h version_tag.h version_base.h ivl@EXEEXT@ $(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true # In the windows world, the installer will need a dosify program to @@ -143,35 +140,26 @@ dosify$(BUILDEXT): $(srcdir)/dosify.c $(BUILDCC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o dosify$(BUILDEXT) $(srcdir)/dosify.c endif -# This rule rules the compiler in the trivial hello.vl program to make -# sure the basics were compiled properly. +# This rule runs the compiler using the trivial hello.vl program to make sure +# the base programs are compiled properly. check: all $(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true + rm -f check.vvp test -r check.conf || cp $(srcdir)/check.conf . - driver/iverilog -B. -BMvpi -BPivlpp -tcheck -ocheck.vvp $(srcdir)/examples/hello.vl -ifeq (@WIN32@,yes) -ifeq (@install_suffix@,) - vvp/vvp -M- -M./vpi ./check.vvp | grep 'Hello, World' -else - # On Windows if we have a suffix we must run the vvp part of - # the test with a suffix since it was built/linked that way. - ln vvp/vvp.exe vvp/vvp$(suffix).exe - vvp/vvp$(suffix) -M- -M./vpi ./check.vvp | grep 'Hello, World' - rm vvp/vvp$(suffix).exe -endif -else - $(ENV_VVP) vvp/vvp -M- -M./vpi ./check.vvp | grep 'Hello, World' -endif + driver/iverilog@EXEEXT@ -B. -BMvpi -BPivlpp -tcheck -ocheck.vvp $(srcdir)/examples/hello.vl && \ + $(ENV_VVP) vvp/vvp$(suffix)@EXEEXT@ -M- -M./vpi ./check.vvp | grep 'Hello, World' + +check-installed check-installed-vpi check-installed-vvp check-installed-vvp-py: + $(MAKE) -C ivtest $@ clean: $(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true rm -f *.o parse.cc parse.h lexor.cc - rm -f ivl.exp iverilog-vpi.man iverilog-vpi.pdf iverilog-vpi.ps - rm -f iverilog_man.ps iverilog_man.pdf iverilog_man_`./version.exe %M_%n`.pdf + rm -f ivl.exp + rm -f iverilog_man.ps iverilog_man.pdf iverilog_man_$(VERSION_MAJOR)_$(VERSION_MINOR).pdf rm -f parse.output syn-rules.output dosify$(BUILDEXT) ivl@EXEEXT@ check.vvp - rm -f lexor_keyword.cc libivl.a libvpi.a iverilog-vpi syn-rules.cc + rm -f lexor_keyword.cc libivl.a libvpi.a syn-rules.cc rm -rf dep - rm -f version.exe distclean: clean $(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true @@ -179,13 +167,14 @@ distclean: clean rm -f Makefile config.status config.log config.cache rm -f stamp-config-h config.h rm -f stamp-_pli_types-h _pli_types.h + rm -f stamp-version_base-h version_base.h ifneq (@srcdir@,.) rm -f version_tag.h check.conf rmdir $(SUBDIRS) $(NOTUSED) endif rm -rf autom4te.cache -cppcheck: $(O:.o=.cc) $(srcdir)/dosify.c $(srcdir)/version.c +cppcheck: $(O:.o=.cc) $(srcdir)/dosify.c cppcheck --enable=all --std=c99 --std=c++11 -f \ --check-level=exhaustive \ --suppressions-list=$(srcdir)/cppcheck-global.sup \ @@ -216,6 +205,11 @@ stamp-_pli_types-h: $(srcdir)/_pli_types.h.in config.status ./config.status _pli_types.h _pli_types.h: stamp-_pli_types-h +stamp-version_base-h: $(srcdir)/version_base.h.in config.status + @rm -f $@ + ./config.status version_base.h +version_base.h: stamp-version_base-h + $(srcdir)/configure: $(srcdir)/configure.ac $(srcdir)/aclocal.m4 cd $(srcdir) && autoconf @@ -234,26 +228,6 @@ ivl@EXEEXT@: $O $(CXX) $(LDFLAGS) -o ivl@EXEEXT@ $O $(dllib) endif -ifeq (@MINGW32@,no) -all: iverilog-vpi - -iverilog-vpi: $(srcdir)/iverilog-vpi.sh Makefile - sed -e 's;@SHARED@;@shared@;' -e 's;@PIC@;@PICFLAG@;' \ - -e 's;@ENABLE_PLI1@;@LIBVERIUSER@;' \ - -e 's;@SUFFIX@;$(suffix);' \ - -e 's;@IVCC@;$(CC);' \ - -e 's;@IVCXX@;$(CXX);' \ - -e 's;@IVCFLAGS@;$(CFLAGS);' \ - -e 's;@IVCXXFLAGS@;$(CXXFLAGS);' \ - -e 's;@IVCTARGETFLAGS@;$(CTARGETFLAGS);' \ - -e 's;@INCLUDEDIR@;$(includedir);' \ - -e 's;@LIBDIR@;@libdir@;' $< > $@ - chmod +x $@ -endif - -version.exe: $(srcdir)/version.c $(srcdir)/version_base.h version_tag.h - $(BUILDCC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o version.exe -I. -I$(srcdir) $(srcdir)/version.c - %.o: %.cc config.h | dep $(CXX) $(CPPFLAGS) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o mv $*.d dep/$*.d @@ -280,22 +254,12 @@ lexor_keyword.o: lexor_keyword.cc parse.h lexor_keyword.cc: $(srcdir)/lexor_keyword.gperf gperf -o -i 7 -C -k 1-4,6,9,$$ -H keyword_hash -N check_identifier -t $< > $@ || (rm -f $@ ; false) -iverilog-vpi.man: $(srcdir)/iverilog-vpi.man.in version.exe - ./version.exe `head -1 $<`'\n' > $@ - tail -n +2 $< >> $@ - -iverilog-vpi.ps: iverilog-vpi.man - $(MAN) -t ./$< > $@ - -iverilog-vpi.pdf: iverilog-vpi.ps - $(PS2PDF) $< $@ - -iverilog_man.ps: driver/iverilog.man vvp/vvp.man iverilog-vpi.man +iverilog_man.ps: driver/iverilog.man vvp/vvp.man driver-vpi/iverilog-vpi.man $(GROFF) -man -rC1 -rD1 -T ps $^ > $@ -iverilog_man.pdf: iverilog_man.ps version.exe +iverilog_man.pdf: iverilog_man.ps $(PS2PDF) $< $@ - cp $@ iverilog_man_`./version.exe %M_%n`.pdf + cp $@ iverilog_man_$(VERSION_MAJOR)_$(VERSION_MINOR).pdf # For VERSION_TAG in driver/main.c, first try git-describe, then look for a # release_tag.h file in the source tree (included in snapshots and releases), @@ -321,33 +285,6 @@ version_tag.h version: echo '#define VERSION_TAG ""' > version_tag.h; \ fi -ifeq (@MINGW32@,yes) -ifeq ($(MAN),none) -INSTALL_DOC = installman -INSTALL_PDFDIR = $(prefix) -else -ifeq ($(PS2PDF),none) -INSTALL_DOC = installman -INSTALL_PDFDIR = $(prefix) -else -INSTALL_DOC = installpdf installman -INSTALL_PDFDIR = $(pdfdir) -all: dep iverilog-vpi.pdf -endif -endif -INSTALL_DOCDIR = $(mandir)/man1 -else -INSTALL_DOC = installman -INSTALL_DOCDIR = $(mandir)/man1 -INSTALL_PDFDIR = $(prefix) -endif - -ifeq (@MINGW32@,yes) -WIN32_INSTALL = -else -WIN32_INSTALL = installwin32 -endif - install: all installdirs installfiles $(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true @@ -359,37 +296,24 @@ F = ./ivl@EXEEXT@ \ $(srcdir)/sv_vpi_user.h \ $(srcdir)/vpi_user.h \ $(srcdir)/acc_user.h \ - $(srcdir)/veriuser.h \ - $(INSTALL_DOC) \ - $(WIN32_INSTALL) - -installwin32: ./iverilog-vpi installdirs - $(INSTALL_SCRIPT) ./iverilog-vpi "$(DESTDIR)$(bindir)/iverilog-vpi$(suffix)" - -installman: iverilog-vpi.man installdirs - $(INSTALL_DATA) iverilog-vpi.man "$(DESTDIR)$(mandir)/man1/iverilog-vpi$(suffix).1" - -installpdf: iverilog-vpi.pdf installdirs - $(INSTALL_DATA) iverilog-vpi.pdf "$(DESTDIR)$(pdfdir)/iverilog-vpi$(suffix).pdf" + $(srcdir)/veriuser.h installfiles: $(F) | installdirs $(INSTALL_PROGRAM) ./ivl@EXEEXT@ "$(DESTDIR)$(libdir)/ivl$(suffix)/ivl@EXEEXT@" $(INSTALL_DATA) $(srcdir)/constants.vams "$(DESTDIR)$(libdir)/ivl$(suffix)/include/constants.vams" $(INSTALL_DATA) $(srcdir)/disciplines.vams "$(DESTDIR)$(libdir)/ivl$(suffix)/include/disciplines.vams" - $(INSTALL_DATA) $(srcdir)/ivl_target.h "$(DESTDIR)$(includedir)/ivl_target.h" - $(INSTALL_DATA) ./_pli_types.h "$(DESTDIR)$(includedir)/_pli_types.h" - $(INSTALL_DATA) $(srcdir)/sv_vpi_user.h "$(DESTDIR)$(includedir)/sv_vpi_user.h" - $(INSTALL_DATA) $(srcdir)/vpi_user.h "$(DESTDIR)$(includedir)/vpi_user.h" - $(INSTALL_DATA) $(srcdir)/acc_user.h "$(DESTDIR)$(includedir)/acc_user.h" - $(INSTALL_DATA) $(srcdir)/veriuser.h "$(DESTDIR)$(includedir)/veriuser.h" + $(INSTALL_DATA) $(srcdir)/ivl_target.h "$(DESTDIR)$(ivl_includedir)/ivl_target.h" + $(INSTALL_DATA) ./_pli_types.h "$(DESTDIR)$(ivl_includedir)/_pli_types.h" + $(INSTALL_DATA) $(srcdir)/sv_vpi_user.h "$(DESTDIR)$(ivl_includedir)/sv_vpi_user.h" + $(INSTALL_DATA) $(srcdir)/vpi_user.h "$(DESTDIR)$(ivl_includedir)/vpi_user.h" + $(INSTALL_DATA) $(srcdir)/acc_user.h "$(DESTDIR)$(ivl_includedir)/acc_user.h" + $(INSTALL_DATA) $(srcdir)/veriuser.h "$(DESTDIR)$(ivl_includedir)/veriuser.h" installdirs: $(srcdir)/mkinstalldirs $(srcdir)/mkinstalldirs "$(DESTDIR)$(bindir)" \ - "$(DESTDIR)$(includedir)" \ + "$(DESTDIR)$(ivl_includedir)" \ "$(DESTDIR)$(libdir)/ivl$(suffix)" \ - "$(DESTDIR)$(libdir)/ivl$(suffix)/include" \ - "$(DESTDIR)$(INSTALL_DOCDIR)" \ - "$(DESTDIR)$(INSTALL_PDFDIR)" + "$(DESTDIR)$(libdir)/ivl$(suffix)/include" uninstall: $(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true @@ -397,13 +321,13 @@ uninstall: do rm -f "$(DESTDIR)$(libdir)/ivl$(suffix)/$$f"; done -rmdir "$(DESTDIR)$(libdir)/ivl$(suffix)/include" -rmdir "$(DESTDIR)$(libdir)/ivl$(suffix)" - for f in verilog$(suffix) iverilog-vpi$(suffix) gverilog$(suffix)@EXEEXT@; \ + for f in verilog$(suffix) gverilog$(suffix)@EXEEXT@; \ do rm -f "$(DESTDIR)$(bindir)/$$f"; done for f in ivl_target.h vpi_user.h _pli_types.h sv_vpi_user.h acc_user.h veriuser.h; \ - do rm -f "$(DESTDIR)$(includedir)/$$f"; done - -test X$(suffix) = X || rmdir "$(DESTDIR)$(includedir)" - rm -f "$(DESTDIR)$(mandir)/man1/iverilog-vpi$(suffix).1" \ - "$(DESTDIR)$(pdfdir)/iverilog-vpi$(suffix).pdf" + do rm -f "$(DESTDIR)$(ivl_includedir)/$$f"; done + -test X$(suffix) = X || rmdir "$(DESTDIR)$(ivl_includedir)" -include $(patsubst %.o, dep/%.d, $O) + +.PHONY: check-installed check-installed-vpi check-installed-vvp check-installed-vvp-py diff --git a/Module.cc b/Module.cc index 6aefe59ab..abbaf6bc8 100644 --- a/Module.cc +++ b/Module.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2022 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -21,13 +21,65 @@ # include "Module.h" # include "PGate.h" +# include "PModport.h" # include "PWire.h" +# include "parse_api.h" # include "ivl_assert.h" +# include using namespace std; list Module::user_defparms; +Module::port_t::port_t() +: port_kind(P_SIGNAL), default_value(0), interface_unpacked_dimensions(0), lexical_pos(0) +{ +} + +bool resolve_interface_formal_port(const LineInfo*li, Design*des, + const Module::port_t*port, + interface_formal_port_t&res, + bool emit_errors) +{ + ivl_assert(*li, port); + ivl_assert(*li, port->is_interface_port()); + + res = interface_formal_port_t(); + + map::const_iterator mod = + pform_modules.find(port->interface_type); + if (mod == pform_modules.end() || !mod->second->is_interface) { + if (emit_errors) { + cerr << li->get_fileline() << ": error: Interface port " + << port->name << " uses unknown interface type `" + << port->interface_type << "'." << endl; + des->errors += 1; + } + return false; + } + + res.module = mod->second; + + if (port->modport_name.str()) { + map::const_iterator mp = + mod->second->modports.find(port->modport_name); + if (mp == mod->second->modports.end()) { + if (emit_errors) { + cerr << li->get_fileline() << ": error: Interface port " + << port->name << " uses unknown modport `" + << port->modport_name << "' of interface `" + << port->interface_type << "'." << endl; + des->errors += 1; + } + return false; + } + + res.modport = mp->second; + } + + return true; +} + /* n is a permallocated string. */ Module::Module(LexicalScope*parent, perm_string n) : PScopeExtra(n, parent) @@ -63,12 +115,18 @@ const vector& Module::get_port(unsigned idx) const ivl_assert(*this, idx < ports.size()); static const vector zero; - if (ports[idx]) + if (ports[idx] && !ports[idx]->is_interface_port()) return ports[idx]->expr; else return zero; } +const Module::port_t* Module::get_port_info(unsigned idx) const +{ + ivl_assert(*this, idx < ports.size()); + return ports[idx]; +} + unsigned Module::find_port(const char*name) const { ivl_assert(*this, name != 0); diff --git a/Module.h b/Module.h index eecfbe781..cd4fde766 100644 --- a/Module.h +++ b/Module.h @@ -1,7 +1,7 @@ #ifndef IVL_Module_H #define IVL_Module_H /* - * Copyright (c) 1998-2025 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -43,6 +43,7 @@ class PFunction; class PWire; class PProcess; class Design; +class LineInfo; class NetScope; /* @@ -65,9 +66,25 @@ class Module : public PScopeExtra, public PNamedItem { default value. */ public: struct port_t { + enum port_kind_t { P_SIGNAL, P_INTERFACE }; + + port_t(); + + port_kind_t port_kind; perm_string name; std::vector expr; PExpr*default_value; + + /* Interface formal port metadata. For signal ports these + fields are empty/zero. The modport name is optional in the + representation, although the parser initially only accepts + the explicit interface_type.modport form. */ + perm_string interface_type; + perm_string modport_name; + std::list*interface_unpacked_dimensions; + unsigned lexical_pos; + + bool is_interface_port() const { return port_kind == P_INTERFACE; } }; public: @@ -148,6 +165,7 @@ class Module : public PScopeExtra, public PNamedItem { unsigned port_count() const; const std::vector& get_port(unsigned idx) const; + const port_t* get_port_info(unsigned idx) const; unsigned find_port(const char*name) const; // Return port name ("" for undeclared port) @@ -181,4 +199,16 @@ class Module : public PScopeExtra, public PNamedItem { Module& operator= (const Module&); }; +struct interface_formal_port_t { + interface_formal_port_t() : module(0), modport(0) { } + + const Module*module; + const PModport*modport; +}; + +extern bool resolve_interface_formal_port(const LineInfo*li, Design*des, + const Module::port_t*port, + interface_formal_port_t&res, + bool emit_errors); + #endif /* IVL_Module_H */ diff --git a/PDelays.cc b/PDelays.cc index 20645434a..97e1d577b 100644 --- a/PDelays.cc +++ b/PDelays.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2025 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -130,10 +130,11 @@ static NetExpr* make_delay_nets(Design*des, NetScope*scope, NetExpr*expr) return expr; } -static NetExpr* calc_decay_time(NetExpr *rise, NetExpr *fall) +static const NetExpr *calc_decay_time(const NetExpr *rise, + const NetExpr *fall) { - const NetEConst *c_rise = dynamic_cast(rise); - const NetEConst *c_fall = dynamic_cast(fall); + const NetEConst *c_rise = dynamic_cast(rise); + const NetEConst *c_fall = dynamic_cast(fall); if (c_rise && c_fall) { if (c_rise->value() < c_fall->value()) return rise; else return fall; @@ -142,44 +143,43 @@ static NetExpr* calc_decay_time(NetExpr *rise, NetExpr *fall) return 0; } -void PDelays::eval_delays(Design*des, NetScope*scope, - NetExpr*&rise_time, - NetExpr*&fall_time, - NetExpr*&decay_time, +void PDelays::eval_delays(Design*des, NetScope*scope, delay_exprs_t &delays, bool as_nets_flag) const { assert(scope); - if (delay_[0]) { - rise_time = calculate_val(des, scope, delay_[0]); + NetExpr *rise = calculate_val(des, scope, delay_[0]); if (as_nets_flag) - rise_time = make_delay_nets(des, scope, rise_time); + rise = make_delay_nets(des, scope, rise); + delays.rise = rise; if (delay_[1]) { - fall_time = calculate_val(des, scope, delay_[1]); + NetExpr *fall = calculate_val(des, scope, delay_[1]); if (as_nets_flag) - fall_time = make_delay_nets(des, scope, fall_time); + fall = make_delay_nets(des, scope, fall); + delays.fall = fall; if (delay_[2]) { - decay_time = calculate_val(des, scope, delay_[2]); + NetExpr *decay = calculate_val(des, scope, delay_[2]); if (as_nets_flag) - decay_time = make_delay_nets(des, scope, - decay_time); + decay = make_delay_nets(des, scope, decay); + delays.decay = decay; } else { // If this is zero then we need to do the min() // at run time. - decay_time = calc_decay_time(rise_time, fall_time); + delays.decay = calc_decay_time(delays.rise, + delays.fall); } } else { assert(delay_[2] == 0); - fall_time = rise_time; - decay_time = rise_time; + delays.fall = delays.rise; + delays.decay = delays.rise; } } else { - rise_time = 0; - fall_time = 0; - decay_time = 0; + delays.rise = nullptr; + delays.fall = nullptr; + delays.decay = nullptr; } } diff --git a/PDelays.h b/PDelays.h index 30709070d..87a727e57 100644 --- a/PDelays.h +++ b/PDelays.h @@ -1,7 +1,7 @@ #ifndef IVL_PDelays_H #define IVL_PDelays_H /* - * Copyright (c) 1999-2021 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -27,6 +27,7 @@ class Design; class NetScope; class NetExpr; class PExpr; +struct delay_exprs_t; /* * Various PForm objects can carry delays. These delays include rise, @@ -46,10 +47,7 @@ class PDelays { unsigned delay_count() const; - void eval_delays(Design*des, NetScope*scope, - NetExpr*&rise_time, - NetExpr*&fall_time, - NetExpr*&decay_time, + void eval_delays(Design*des, NetScope*scope, delay_exprs_t &delays, bool as_nets_flag =false) const; void dump_delays(std::ostream&out) const; diff --git a/PExpr.h b/PExpr.h index 99c1df05d..f4c256aff 100644 --- a/PExpr.h +++ b/PExpr.h @@ -1,7 +1,7 @@ #ifndef IVL_PExpr_H #define IVL_PExpr_H /* - * Copyright (c) 1998-2025 Stephen Williams + * Copyright (c) 1998-2026 Stephen Williams * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -691,12 +691,16 @@ class PEString : public PExpr { virtual unsigned test_width(Design*des, NetScope*scope, width_mode_t&mode) override; - virtual NetEConst*elaborate_expr(Design*des, NetScope*scope, + virtual NetExpr*elaborate_expr(Design*des, NetScope*scope, ivl_type_t type, unsigned flags) const override; virtual NetEConst*elaborate_expr(Design*des, NetScope*, unsigned expr_wid, unsigned) const override; + NetExpr *elaborate_expr_uarray_(Design *des, NetScope *scope, + const netuarray_t *uarray_type, + const std::vector &dims, + unsigned int cur_dim) const; private: char*text_; }; diff --git a/PGate.cc b/PGate.cc index 6da02060e..944d4e2dd 100644 --- a/PGate.cc +++ b/PGate.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2025 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -41,29 +41,23 @@ void PGate::set_pins_(list*pins) } PGate::PGate(perm_string name, list*pins, const list*del) -: name_(name), pins_(pins? pins->size() : 0), ranges_(0) +: name_(name), pins_(pins? pins->size() : 0), ranges_(nullptr) { if (pins) set_pins_(pins); if (del) delay_.set_delays(del); - str0_ = IVL_DR_STRONG; - str1_ = IVL_DR_STRONG; } PGate::PGate(perm_string name, list*pins, PExpr*del) -: name_(name), pins_(pins? pins->size() : 0), ranges_(0) +: name_(name), pins_(pins? pins->size() : 0), ranges_(nullptr) { if (pins) set_pins_(pins); if (del) delay_.set_delay(del); - str0_ = IVL_DR_STRONG; - str1_ = IVL_DR_STRONG; } PGate::PGate(perm_string name, list*pins) -: name_(name), pins_(pins? pins->size() : 0), ranges_(0) +: name_(name), pins_(pins? pins->size() : 0), ranges_(nullptr) { if (pins) set_pins_(pins); - str0_ = IVL_DR_STRONG; - str1_ = IVL_DR_STRONG; } PGate::~PGate() @@ -76,24 +70,14 @@ void PGate::set_ranges(list*ranges) ranges_ = ranges; } -ivl_drive_t PGate::strength0() const +drive_strength_t PGate::strength() const { - return str0_; + return strength_; } -void PGate::strength0(ivl_drive_t s) +void PGate::strength(const drive_strength_t &str) { - str0_ = s; -} - -ivl_drive_t PGate::strength1() const -{ - return str1_; -} - -void PGate::strength1(ivl_drive_t s) -{ - str1_ = s; + strength_ = str; } void PGate::elaborate_scope(Design*, NetScope*) const @@ -109,15 +93,10 @@ void PGate::elaborate_scope(Design*, NetScope*) const * numbers of expressions. */ -void PGate::eval_delays(Design*des, NetScope*scope, - NetExpr*&rise_expr, - NetExpr*&fall_expr, - NetExpr*&decay_expr, +void PGate::eval_delays(Design*des, NetScope*scope, delay_exprs_t &delays, bool as_net_flag) const { - delay_.eval_delays(des, scope, - rise_expr, fall_expr, decay_expr, - as_net_flag); + delay_.eval_delays(des, scope, delays, as_net_flag); } unsigned PGate::delay_count() const diff --git a/PGate.h b/PGate.h index 59c09954c..ca67bd4e6 100644 --- a/PGate.h +++ b/PGate.h @@ -31,6 +31,8 @@ class PExpr; class PUdp; class Module; +struct delay_exprs_t; +struct drive_strength_t; /* * A PGate represents a Verilog gate. The gate has a name and other @@ -66,10 +68,7 @@ class PGate : public PNamedItem { // This evaluates the delays as far as possible, but returns // an expression, and do not signal errors. - void eval_delays(Design*des, NetScope*scope, - NetExpr*&rise_time, - NetExpr*&fall_time, - NetExpr*&decay_time, + void eval_delays(Design*des, NetScope*scope, delay_exprs_t &delays, bool as_net_flag =false) const; unsigned delay_count() const; @@ -77,11 +76,9 @@ class PGate : public PNamedItem { unsigned pin_count() const { return pins_.size(); } PExpr*pin(unsigned idx) const { return pins_[idx]; } - ivl_drive_t strength0() const; - ivl_drive_t strength1() const; + drive_strength_t strength() const; - void strength0(ivl_drive_t); - void strength1(ivl_drive_t); + void strength(const drive_strength_t &str); std::map attributes; @@ -109,7 +106,7 @@ class PGate : public PNamedItem { std::list*ranges_; - ivl_drive_t str0_, str1_; + drive_strength_t strength_; void set_pins_(std::list*pins); @@ -133,7 +130,9 @@ class PGAssign : public PGate { virtual void elaborate(Design*des, NetScope*scope) const override; private: - void elaborate_unpacked_array_(Design*des, NetScope*scope, NetNet*lval) const; + void elaborate_unpacked_array_(Design*des, NetScope*scope, NetNet*lval, + const drive_strength_t &drive, + const delay_exprs_t &delays) const; }; @@ -236,11 +235,20 @@ class PGModule : public PGate { unsigned nparms_; friend class delayed_elaborate_scope_mod_instances; - void elaborate_mod_(Design*, Module*mod, NetScope*scope) const; + void elaborate_mod_(Design*, const Module*mod, NetScope*scope) const; void elaborate_udp_(Design*, PUdp *udp, NetScope*scope) const; void elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const; void elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*sc) const; bool elaborate_sig_mod_(Design*des, NetScope*scope, const Module*mod) const; + bool bind_interface_ports_(Design*des, const Module*mod, + NetScope*parent_scope, NetScope*instance_scope, + const std::vector&pins, + const std::vector&pins_fromwc) const; + bool match_module_ports_(Design*des, const Module*mod, + NetScope*scope, + std::vector&pins, + std::vector&pins_fromwc, + std::vector&pins_is_explicitly_not_connected) const; // Not currently used. #if 0 bool elaborate_sig_udp_(Design*des, NetScope*scope, PUdp*udp) const; diff --git a/PScope.h b/PScope.h index 5f8a6caf4..2d7a7b9d7 100644 --- a/PScope.h +++ b/PScope.h @@ -1,7 +1,7 @@ #ifndef IVL_PScope_H #define IVL_PScope_H /* - * Copyright (c) 2008-2025 Stephen Williams (steve@icarus.com) + * Copyright (c) 2008-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -121,6 +121,8 @@ class LexicalScope { bool overridable; // Whether the parameter is a type parameter bool type_flag = false; + // Type restriction for a type parameter + type_restrict_t type_restrict; // The lexical position of the declaration unsigned lexical_pos = 0; diff --git a/aclocal.m4 b/aclocal.m4 index 5f2a09eb8..32ca987c3 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -12,6 +12,7 @@ # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +m4_include([m4/_ac_am_config_header_hook.m4]) m4_include([m4/_ax_c_underscores_match_if.m4]) m4_include([m4/ax_c99_strtod.m4]) m4_include([m4/ax_c_picflag.m4]) diff --git a/cadpli/cppcheck.sup b/cadpli/cppcheck.sup index d08cd7dd5..8a7dbd07e 100644 --- a/cadpli/cppcheck.sup +++ b/cadpli/cppcheck.sup @@ -4,4 +4,4 @@ nullPointerOutOfMemory:cadpli.c:53 nullPointerOutOfMemory:cadpli.c:54 // Unused function -unusedFunction:ivl_dlfcn.h:73 +unusedFunction:ivl_dlfcn.h:87 diff --git a/compiler.h b/compiler.h index 01893d18b..56f706c70 100644 --- a/compiler.h +++ b/compiler.h @@ -165,6 +165,8 @@ enum generation_t { GN_VER2005_SV = 5, GN_VER2009 = 6, GN_VER2012 = 7, + GN_VER2017 = 8, + GN_VER2023 = 9, GN_DEFAULT = 4 }; diff --git a/configure.ac b/configure.ac index a397d47d9..9ad90e571 100644 --- a/configure.ac +++ b/configure.ac @@ -1,8 +1,35 @@ dnl Process this file with autoconf to produce a configure script. -AC_INIT + AC_CONFIG_MACRO_DIRS([m4]) +dnl Define project version +m4_define([VER_MAJOR], [14]) +m4_define([VER_MINOR], [0]) +m4_define([VER_EXTRA], [devel]) + +dnl define libvvp ABI version +m4_define([LIBVVP_SOVERSION], [1]) + +AC_INIT([iverilog], [VER_MAJOR.VER_MINOR (VER_EXTRA)]) +AC_SUBST([VERSION_MAJOR], [VER_MAJOR]) +AC_SUBST([VERSION_MINOR], [VER_MINOR]) +AC_SUBST([VERSION_EXTRA], [" (VER_EXTRA)"]) +AC_SUBST([VERSION], ["VER_MAJOR.VER_MINOR (VER_EXTRA)"]) +# used in res.rc +AC_SUBST([PRODUCTVERSION], ["VER_MAJOR,VER_MINOR,0,0"]) + +# setup libvvp soversion, which depends on abi not package version +AC_SUBST([LIBVVP_SOVERSION], [LIBVVP_SOVERSION]) +# setup libvvp version +AC_SUBST([LIBVVP_VERSION], [LIBVVP_SOVERSION.VER_MAJOR.VER_MINOR]) + AC_CONFIG_SRCDIR([netlist.h]) +# Need a stamp file like the other header files +AC_CONFIG_FILES([version_base.h],[ +_config_header=version_base.h +_stamp_name=stamp-`expr //$_config_header : '.*/\([[^./]]*\)\.[[^./]]*$'`-h +echo "timestamp for $_config_header" > `AS_DIRNAME(["$_config_header"])`/[]$_stamp_name +]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([_pli_types.h]) AC_CONFIG_HEADERS([vhdlpp/vhdlpp_config.h]) @@ -71,6 +98,20 @@ AC_SUBST(EXEEXT) # Combined check for Microsoft-related bogosities; sets WIN32 if found AX_WIN32 +# Detect which directory/file separator to use +AC_MSG_CHECKING([for directory/file separator]) + +AS_CASE([$host_os:$MSYSTEM], + [*mingw*:UCRT64|*mingw*:MINGW64|*mingw*:MINGW32|*mingw*:CLANG64|*mingw*:CLANGARM64], [ + PATH_SEP=\\\\ + ], + [ + PATH_SEP=/ + ] +) +AC_MSG_RESULT([$PATH_SEP]) +AC_SUBST([PATH_SEP]) + # Check to see if we are using the Sun compiler. If so then configure # some of the flags to match the Sun compiler syntax. This is also used # in the aclocal.m4 file to configure the flags used to build and link @@ -190,7 +231,14 @@ AC_FUNC_FSEEKO # Build VVP as a library and stub AC_ARG_ENABLE([libvvp], [AS_HELP_STRING([--enable-libvvp], [build VVP as a shared library])], - [AC_SUBST(LIBVVP, yes)],[]) + [enable_libvvp=yes], + [enable_libvvp=no]) + +AC_SUBST([LIBVVP], [$enable_libvvp]) + +AS_IF([test "x$enable_libvvp" = "xyes"], + [AC_MSG_NOTICE([Building with libvvp support enabled])], + [AC_MSG_NOTICE([Building with libvvp support disabled])]) AC_ARG_ENABLE([libveriuser], [AS_HELP_STRING([--enable-libveriuser], [include support for PLI 1 (deprecated)])], @@ -281,6 +329,9 @@ case "$host_os" in linux*) ENV_VVP="LD_LIBRARY_PATH=$VVP_BUILDDIR" ;; + *bsd*) + ENV_VVP="LD_LIBRARY_PATH=$VVP_BUILDDIR" + ;; darwin*) ENV_VVP="DYLD_LIBRARY_PATH=$VVP_BUILDDIR" ;; @@ -390,5 +441,32 @@ then AC_MSG_ERROR(cannot configure white space in libdir: $libdir) fi AC_MSG_RESULT(ok) -AC_CONFIG_FILES([Makefile ivlpp/Makefile vhdlpp/Makefile vvp/Makefile vpi/Makefile driver/Makefile driver-vpi/Makefile cadpli/Makefile libveriuser/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-vvp/Makefile tgt-vhdl/Makefile tgt-fpga/Makefile tgt-verilog/Makefile tgt-pal/Makefile tgt-vlog95/Makefile tgt-pcb/Makefile tgt-blif/Makefile tgt-sizer/Makefile]) +AC_CONFIG_FILES([ + Makefile + cadpli/Makefile + driver-vpi/Makefile + driver-vpi/iverilog-vpi.man + driver-vpi/res.rc + driver/Makefile + driver/iverilog.man + ivlpp/Makefile + ivtest/Makefile + libveriuser/Makefile + tgt-blif/Makefile + tgt-fpga/Makefile + tgt-null/Makefile + tgt-pal/Makefile + tgt-pcb/Makefile + tgt-sizer/Makefile + tgt-stub/Makefile + tgt-verilog/Makefile + tgt-vhdl/Makefile + tgt-vlog95/Makefile + tgt-vvp/Makefile + vhdlpp/Makefile + vpi/Makefile + vvp/Makefile + vvp/libvvp.pc + vvp/vvp.man +]) AC_OUTPUT diff --git a/cppcheck.sup b/cppcheck.sup index 360f39ef5..f4e70d72d 100644 --- a/cppcheck.sup +++ b/cppcheck.sup @@ -10,47 +10,49 @@ nullPointerOutOfMemory ctuuninitvar:parse_misc.cc:61 // Skip strdup() not constant. -constVariablePointer:main.cc:400 -constVariablePointer:main.cc:404 -constVariablePointer:main.cc:654 +constVariablePointer:main.cc:421 +constVariablePointer:main.cc:425 +constVariablePointer:main.cc:675 // const auto should be const constVariablePointer:elab_expr.cc:344 -constVariablePointer:elab_expr.cc:413 +constVariablePointer:elab_expr.cc:347 +constVariablePointer:elab_expr.cc:416 // The reference cannot be const since it is updated in the calling function. constParameterReference:net_udp.cc:37 // These cannot be static since they access object data functionStatic:net_link.cc:178 -functionStatic:net_link.cc:183 -functionStatic:net_link.cc:188 -functionStatic:net_link.cc:193 +functionStatic:net_link.cc:184 +functionStatic:net_link.cc:189 +functionStatic:net_link.cc:194 // This cannot be static when checking with valgrind functionStatic:libmisc/StringHeap.cc // Skip not initialized in the constructor for target scope +uninitMemberVar:t-dll.cc:41 uninitMemberVar:t-dll.cc:109 // By convention we put statics at the top scope. -variableScope:pform.cc:3461 +variableScope:pform.cc:3499 // These are correct and are used to find the base (zero) pin. -thisSubtraction:netlist.h:5309 -thisSubtraction:netlist.h:5318 +thisSubtraction:netlist.h:5376 +thisSubtraction:netlist.h:5385 // This is used when running a debugger // debugger_release -knownConditionTrueFalse:main.cc:931 +knownConditionTrueFalse:main.cc:955 // These should be checked, but are not real issues -knownConditionTrueFalse:elaborate.cc:7621 -knownConditionTrueFalse:elab_sig.cc:271 -knownConditionTrueFalse:elab_sig.cc:338 +knownConditionTrueFalse:elaborate.cc:7970 +knownConditionTrueFalse:elab_sig.cc:272 +knownConditionTrueFalse:elab_sig.cc:345 // Yes, it's a duplicate -duplicateCondition:elaborate.cc:7672 +duplicateCondition:elaborate.cc:8021 // To complicated to use std::find_if() useStlAlgorithm:map_named_args.cc:38 @@ -59,7 +61,7 @@ useStlAlgorithm:map_named_args.cc:38 derefInvalidIterator:netmisc.cc:420 // By convention we put statics at the top scope. -variableScope:t-dll.cc:2377 +variableScope:t-dll.cc:2309 // We check memory allocation with valgrind unsafeClassCanLeak:libmisc/StringHeap.h:79 @@ -720,31 +722,33 @@ unusedFunction:Statement.h:192 // chain_args() unusedFunction:Statement.h:341 // gn_modules_nest() -unusedFunction:compiler.h:228 +unusedFunction:compiler.h:247 // driven_mask() unusedFunction:link_const.cc:275 // find_root_scope() unusedFunction:net_design.cc:121 // assign_lval() -unusedFunction:net_link.cc:282 +unusedFunction:net_link.cc:283 // intersect() -unusedFunction:net_link.cc:689 +unusedFunction:net_link.cc:687 // get_def_fileline() unusedFunction:net_scope.cc:201 // get_module_port_info() -unusedFunction:net_scope.cc:591 +unusedFunction:net_scope.cc:600 // find_link_signal() -unusedFunction:netlist.cc:111 +unusedFunction:netlist.cc:113 // find_link() -unusedFunction:netlist.cc:297 +unusedFunction:netlist.cc:304 // set_module_port_index() -unusedFunction:netlist.cc:651 +unusedFunction:netlist.cc:658 // width_a() -unusedFunction:netlist.cc:1678 +unusedFunction:netlist.cc:1685 // width_b() -unusedFunction:netlist.cc:1683 +unusedFunction:netlist.cc:1690 // result_sig() -unusedFunction:netlist.cc:2184 +unusedFunction:netlist.cc:2191 +// soft_union() +unusedFunction:netstruct.h:93 // test_protected() unusedFunction:property_qual.h:50 // test_rand() @@ -756,13 +760,14 @@ unusedFunction:t-dll-expr.cc:55 // mul_expr_by_const_() unusedFunction:t-dll-expr.cc:91 // net_assign() -unusedFunction:t-dll.cc:2368 +unusedFunction:t-dll.cc:2300 // is_before() unusedFunction:verinum.cc:588 // Errors/limitations in the generated yacc and lex files constVariablePointer: cstyleCast: +duplicateBreak: nullPointer: redundantInitialization: syntaxError: diff --git a/cprop.cc b/cprop.cc index 9e7864b09..804fa4e91 100644 --- a/cprop.cc +++ b/cprop.cc @@ -180,9 +180,7 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj) << "Replace binary MUX with constant select=" << sel_val << " with a BUFZ to the selected input." << endl; - tmp->rise_time(obj->rise_time()); - tmp->fall_time(obj->fall_time()); - tmp->decay_time(obj->decay_time()); + tmp->delay_times(obj->delay_times()); connect(tmp->pin(0), obj->pin_Result()); if (sel_val == verinum::V1) diff --git a/design_dump.cc b/design_dump.cc index c1e74325d..fe5d9edf3 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2021 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -90,6 +90,30 @@ ostream& operator << (ostream&o, ivl_drive_t str) return o; } +ostream &operator << (ostream &o, const drive_strength_t &strength) +{ + o << strength.drive0 << "0 " << strength.drive1 << "1"; + return o; +} + +static void dump_delay_expr(ostream &o, const NetExpr *expr) +{ + if (expr) + o << *expr; + else + o << "0"; +} + +ostream &operator << (ostream &o, const delay_exprs_t &delays) +{ + dump_delay_expr(o, delays.rise); + o << ","; + dump_delay_expr(o, delays.fall); + o << ","; + dump_delay_expr(o, delays.decay); + return o; +} + ostream& operator << (ostream&o, ivl_variable_type_t val) { switch (val) { @@ -454,8 +478,7 @@ void NetNet::dump_net(ostream&o, unsigned ind) const o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")"; if (scope()) o << " scope=" << scope_path(scope()); - o << " #(" << rise_time() << "," << fall_time() << "," - << decay_time() << ") vector_width=" << vector_width() + o << " #(" << delay_times() << ") vector_width=" << vector_width() << " pin_count=" << pin_count(); if (pins_are_virtual()) { o << " pins_are_virtual" << endl; @@ -486,8 +509,7 @@ void NetNet::dump_net(ostream&o, unsigned ind) const void NetNode::dump_node(ostream&o, unsigned ind) const { o << setw(ind) << "" << "node: "; - o << typeid(*this).name() << " #(" << rise_time() - << "," << fall_time() << "," << decay_time() << ") " << name() + o << typeid(*this).name() << " #(" << delay_times() << ") " << name() << endl; dump_node_pins(o, ind+4); @@ -518,8 +540,7 @@ void NetPins::dump_node_pins(ostream&o, unsigned ind, const char**pin_names) con break; } - o << " (" << pin(idx).drive0() << "0 " - << pin(idx).drive1() << "1): "; + o << " (" << pin(idx).drive() << "): "; if (pin(idx).is_linked()) { const Nexus*nex = pin(idx).nexus(); @@ -622,11 +643,7 @@ void NetConcat::dump_node(ostream&o, unsigned ind) const o << setw(ind) << "" << "NetConcat: "; o << name(); - if (rise_time()) - o << " #(" << *rise_time() - << "," << *fall_time() << "," << *decay_time() << ")"; - else - o << " #(0,0,0)"; + o << " #(" << delay_times() << ")"; o << " scope=" << scope_path(scope()) << " width=" << width_ << endl; dump_node_pins(o, ind+4); @@ -651,14 +668,7 @@ void NetPow::dump_node(ostream&o, unsigned ind) const { o << setw(ind) << "" << "LPM_POW (NetPow): " << name() << " scope=" << scope_path(scope()) - << " delay=("; - if (rise_time()) - o << *rise_time() << "," << *fall_time() << "," - << *decay_time(); - else - o << "0,0,0"; - - o << ")" << endl; + << " delay=(" << delay_times() << ")" << endl; dump_node_pins(o, ind+4); dump_obj_attr(o, ind+4); } @@ -676,8 +686,7 @@ void NetBUFZ::dump_node(ostream&o, unsigned ind) const { o << setw(ind) << "" << "NetBUFZ: " << name() << " scope=" << scope_path(scope()) - << " delay=(" << rise_time() << "," << fall_time() << "," << - decay_time() << ") width=" << width() + << " delay=(" << delay_times() << ") width=" << width() << (transparent()? " " : " non-") << "transparent" << endl; dump_node_pins(o, ind+4); } @@ -693,10 +702,8 @@ void NetConst::dump_node(ostream&o, unsigned ind) const { o << setw(ind) << "" << "constant " << value_; o << ": " << name(); - if (rise_time()) - o << " #(" << *rise_time() - << "," << *fall_time() - << "," << *decay_time() << ")"; + if (delay_times().has_delay()) + o << " #(" << delay_times() << ")"; else o << " #(.,.,.)"; o << endl; @@ -729,10 +736,8 @@ void NetLiteral::dump_node(ostream&o, unsigned ind) const { o << setw(ind) << "" << "constant real " << real_ << ": " << name(); - if (rise_time()) - o << " #(" << *rise_time() - << "," << *fall_time() - << "," << *decay_time() << ")"; + if (delay_times().has_delay()) + o << " #(" << delay_times() << ")"; else o << " #(.,.,.)"; o << endl; @@ -810,8 +815,7 @@ void NetLogic::dump_node(ostream&o, unsigned ind) const o << "xor"; break; } - o << " #(" << rise_time() - << "," << fall_time() << "," << decay_time() << ") " << name() + o << " #(" << delay_times() << ") " << name() << " scope=" << scope_path(scope()) << endl; @@ -839,10 +843,8 @@ void NetPartSelect::dump_node(ostream&o, unsigned ind) const } o << setw(ind) << "" << "NetPartSelect(" << pt << "): " << name(); - if (rise_time()) - o << " #(" << *rise_time() - << "," << *fall_time() - << "," << *decay_time() << ")"; + if (delay_times().has_delay()) + o << " #(" << delay_times() << ")"; else o << " #(.,.,.)"; o << " off=" << off_ << " wid=" << wid_ < $@ + chmod +x $@ +endif main.o: $(srcdir)/main.c config.h $(CC) $(CPPFLAGS) $(CFLAGS) -c $(srcdir)/main.c @@ -95,20 +135,39 @@ else endif # Windows specific... -res.rc: $(srcdir)/res.rc.in ../version.exe - sed -e 's;@PRODUCTVERSION@;'`../version.exe '%M,%n,0,0'`';' \ - $(srcdir)/res.rc.in > $@ +res.rc: $(srcdir)/res.rc.in ../config.status + cd ..; ./config.status --file=driver-vpi/$@ res.o: res.rc $(WINDRES) -i res.rc -o res.o # +iverilog-vpi.man: $(srcdir)/iverilog-vpi.man.in ../config.status + cd ..; ./config.status --file=driver-vpi/$@ + +iverilog-vpi.ps: iverilog-vpi.man + $(MAN) -t ./$< > $@ + +iverilog-vpi.pdf: iverilog-vpi.ps + $(PS2PDF) $< $@ + install: all installdirs installfiles -F = ./iverilog-vpi@EXEEXT@ +F = $(INSTALL_DOC) +ifeq (@MINGW32@,yes) +F += ./iverilog-vpi@EXEEXT@ +endif +ifeq (@MINGW32@,no) +F += ./iverilog-vpi +endif installfiles: $(F) | installdirs +ifeq (@MINGW32@,yes) $(INSTALL_PROGRAM) ./iverilog-vpi@EXEEXT@ "$(DESTDIR)$(bindir)/iverilog-vpi$(suffix)@EXEEXT@" +endif +ifeq (@MINGW32@,no) + $(INSTALL_SCRIPT) ./iverilog-vpi "$(DESTDIR)$(bindir)/iverilog-vpi$(suffix)" +endif ifeq (@WIN32@,yes) ifneq ($(HOSTCC),$(CC)) $(INSTALL_PROGRAM) $(shell $(HOSTCC) --print-file-name=libwinpthread-1.dll) "$(DESTDIR)$(bindir)" @@ -117,8 +176,24 @@ ifneq ($(HOSTCC),$(CC)) endif endif +installman: iverilog-vpi.man installdirs + $(INSTALL_DATA) iverilog-vpi.man "$(DESTDIR)$(man1dir)/iverilog-vpi$(suffix).1" + +installpdf: iverilog-vpi.pdf installdirs + $(INSTALL_DATA) iverilog-vpi.pdf "$(DESTDIR)$(docdir)/iverilog-vpi$(suffix).pdf" + installdirs: $(srcdir)/../mkinstalldirs - $(srcdir)/../mkinstalldirs "$(DESTDIR)$(bindir)" + $(srcdir)/../mkinstalldirs \ + "$(DESTDIR)$(bindir)" \ + "$(DESTDIR)$(docdir)" \ + "$(DESTDIR)$(man1dir)" uninstall: +ifeq (@MINGW32@,yes) rm -f $(DESTDIR)$(bindir)/iverilog-vpi$(suffix)@EXEEXT@ +endif +ifeq (@MINGW32@,no) + rm -f $(DESTDIR)$(bindir)/iverilog-vpi$(suffix) +endif + rm -f "$(DESTDIR)$(man1dir)/iverilog-vpi$(suffix).1" \ + "$(DESTDIR)$(docdir)/iverilog-vpi$(suffix).pdf" diff --git a/iverilog-vpi.man.in b/driver-vpi/iverilog-vpi.man.in similarity index 98% rename from iverilog-vpi.man.in rename to driver-vpi/iverilog-vpi.man.in index 23741e1c2..13a85a586 100644 --- a/iverilog-vpi.man.in +++ b/driver-vpi/iverilog-vpi.man.in @@ -1,4 +1,4 @@ -.TH iverilog-vpi 1 "Jan 13th, 2026" "" "Version %M.%n%E" +.TH iverilog-vpi 1 "Jan 13th, 2026" "" "Version @VERSION@" .SH NAME iverilog-vpi - Compile front end for VPI modules diff --git a/iverilog-vpi.sh b/driver-vpi/iverilog-vpi.sh similarity index 100% rename from iverilog-vpi.sh rename to driver-vpi/iverilog-vpi.sh diff --git a/driver/Makefile.in b/driver/Makefile.in index 38ab633a9..91e472816 100644 --- a/driver/Makefile.in +++ b/driver/Makefile.in @@ -17,20 +17,26 @@ # SHELL = /bin/sh +EXEEXT = @EXEEXT@ +ENV_VVP=@ENV_VVP@ +PATH_SEP=@PATH_SEP@ + suffix = @install_suffix@ prefix = @prefix@ exec_prefix = @exec_prefix@ srcdir = @srcdir@ datarootdir = @datarootdir@ +builddir=@builddir@ +top_builddir=@top_builddir@ VPATH = $(srcdir) bindir = $(exec_prefix)/bin libdir = $(exec_prefix)/lib includedir = $(prefix)/include -mandir = @mandir@ -pdfdir = @docdir@ +man1dir = @mandir@/man1 +docdir = @docdir@ dllib=@DLLIB@ @@ -58,11 +64,22 @@ O = main.o substit.o cflexor.o cfparse.o all: dep iverilog@EXEEXT@ iverilog.man check: all + @echo "driver/iverilog: create a vvp file and then run it." + @rm -f top.vvp + @$(builddir)/iverilog@EXEEXT@ \ + -B$(top_builddir)$(PATH_SEP)tgt-vvp \ + -BI$(top_builddir) \ + -BM$(top_builddir)$(PATH_SEP)vpi \ + -BP$(top_builddir)$(PATH_SEP)ivlpp \ + -Bt$(top_builddir)$(PATH_SEP)tgt-vvp \ + $(verbose) -o top.vvp -s top $(srcdir)/hello_world.v && \ + $(ENV_VVP) $(top_builddir)/vvp/vvp$(suffix)@EXEEXT@ top.vvp clean: rm -f *.o cflexor.c cfparse.c cfparse.h cfparse.output rm -f iverilog@EXEEXT@ iverilog.man iverilog.pdf iverilog.ps rm -rf dep + rm -f top.vvp distclean: clean rm -f Makefile config.log @@ -96,15 +113,14 @@ cfparse%c cfparse%h: $(srcdir)/cfparse%y $(CC) $(CPPFLAGS) $(CFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o mv $*.d dep -main.o: main.c globals.h $(srcdir)/../version_base.h ../version_tag.h Makefile | dep +main.o: main.c globals.h ../version_base.h ../version_tag.h Makefile | dep $(CC) $(CPPFLAGS) $(CFLAGS) @DEPENDENCY_FLAG@ -c -DIVL_ROOT='"@libdir@/ivl$(suffix)"' -DIVL_SUFFIX='"$(suffix)"' -DIVL_INC='"@includedir@"' -DIVL_LIB='"@libdir@"' -DDLLIB='"@DLLIB@"' -DIVL_INCLUDE_INSTALL_DIR="\"$(realpath $(DESTDIR)/$(includedir))\"" $(srcdir)/main.c mv $*.d dep cflexor.o: cflexor.c cfparse.h -iverilog.man: $(srcdir)/iverilog.man.in ../version.exe - ../version.exe `head -1 $<`'\n' > $@ - tail -n +2 $< >> $@ +iverilog.man: $(srcdir)/iverilog.man.in ../config.status + cd ..; ./config.status --file=driver/$@ iverilog.ps: iverilog.man $(MAN) -t ./$< > $@ @@ -112,25 +128,15 @@ iverilog.ps: iverilog.man iverilog.pdf: iverilog.ps $(PS2PDF) $< $@ +INSTALL_DOC = +ifneq ($(MAN),none) +INSTALL_DOC += installman +ifneq ($(PS2PDF),none) ifeq (@MINGW32@,yes) -ifeq ($(MAN),none) -INSTALL_DOC = installman -INSTALL_PDFDIR = $(prefix) -else -ifeq ($(PS2PDF),none) -INSTALL_DOC = installman -INSTALL_PDFDIR = $(prefix) -else -INSTALL_DOC = installpdf installman -INSTALL_PDFDIR = $(pdfdir) +INSTALL_DOC += installpdf all: iverilog.pdf endif endif -INSTALL_DOCDIR = $(mandir)/man1 -else -INSTALL_DOC = installman -INSTALL_DOCDIR = $(mandir)/man1 -INSTALL_PDFDIR = $(prefix) endif install: all installdirs installfiles @@ -139,21 +145,23 @@ F = ./iverilog@EXEEXT@ \ $(INSTALL_DOC) installman: iverilog.man installdirs - $(INSTALL_DATA) iverilog.man "$(DESTDIR)$(mandir)/man1/iverilog$(suffix).1" + $(INSTALL_DATA) iverilog.man "$(DESTDIR)$(man1dir)/iverilog$(suffix).1" installpdf: iverilog.pdf installdirs - $(INSTALL_DATA) iverilog.pdf "$(DESTDIR)$(pdfdir)/iverilog$(suffix).pdf" + $(INSTALL_DATA) iverilog.pdf "$(DESTDIR)$(docdir)/iverilog$(suffix).pdf" installfiles: $(F) | installdirs $(INSTALL_PROGRAM) ./iverilog@EXEEXT@ "$(DESTDIR)$(bindir)/iverilog$(suffix)@EXEEXT@" installdirs: $(srcdir)/../mkinstalldirs - $(srcdir)/../mkinstalldirs "$(DESTDIR)$(bindir)" \ - "$(DESTDIR)$(INSTALL_DOCDIR)" \ - "$(DESTDIR)$(INSTALL_PDFDIR)" + $(srcdir)/../mkinstalldirs \ + "$(DESTDIR)$(bindir)" \ + "$(DESTDIR)$(docdir)" \ + "$(DESTDIR)$(man1dir)" uninstall: rm -f "$(DESTDIR)$(bindir)/iverilog$(suffix)@EXEEXT@" - rm -f "$(DESTDIR)$(mandir)/man1/iverilog$(suffix).1" "$(DESTDIR)$(pdfdir)/iverilog$(suffix).pdf" + rm -f "$(DESTDIR)$(man1dir)/iverilog$(suffix).1" \ + "$(DESTDIR)$(docdir)/iverilog$(suffix).pdf" -include $(patsubst %.o, dep/%.d, $O) diff --git a/driver/cppcheck.sup b/driver/cppcheck.sup index f33c05c09..82ce9a74e 100644 --- a/driver/cppcheck.sup +++ b/driver/cppcheck.sup @@ -1,10 +1,10 @@ // cppcheck is wrong this is correct usage -syntaxError:main.c:405 -syntaxError:main.c:408 +syntaxError:main.c:410 +syntaxError:main.c:413 // cppcheck is missing the code adds a \0 at the previous location. -knownConditionTrueFalse:main.c:1086 -redundantAssignment:main.c:1085 +knownConditionTrueFalse:main.c:1123 +redundantAssignment:main.c:1122 // Skip all memory issues since they should be handled by ivl_alloc.h memleakOnRealloc @@ -18,9 +18,12 @@ memleakOnRealloc:cfparse.y allocaCalled:cfparse.c constParameterPointer:cfparse.c constVariablePointer:cfparse.c +invalidPrintfArgType_sint:cfparse.c knownConditionTrueFalse:cfparse.c sizeofwithnumericparameter:cfparse.c +unsignedPositive:cfparse.c constVariablePointer: +duplicateBreak: nullPointer: redundantInitialization: staticFunction: diff --git a/driver/hello_world.v b/driver/hello_world.v new file mode 100644 index 000000000..33ca7ea79 --- /dev/null +++ b/driver/hello_world.v @@ -0,0 +1,3 @@ +module top; + initial $display("Hello World!"); +endmodule diff --git a/driver/iverilog.man.in b/driver/iverilog.man.in index 21dbf72dc..b5f4d1360 100644 --- a/driver/iverilog.man.in +++ b/driver/iverilog.man.in @@ -1,12 +1,12 @@ -.TH iverilog 1 "Jan 13th, 2026" "" "Version %M.%n%E" +.TH iverilog 1 "Jan 13th, 2026" "" "Version @VERSION@" .SH NAME iverilog - Icarus Verilog compiler .SH SYNOPSIS .B iverilog -[\-EiRSuVv] [\-Bpath] [\-ccmdfile|\-fcmdfile] [\-Dmacro[=defn]] +[\-EiRSuVv] [\-B[IMPVt]path] [\-ccmdfile|\-fcmdfile] [\-Dmacro[=defn]] [\-Pparameter=value] [\-pflag=value] [\-dname] -[\-g1995\:|\-g2001\:|\-g2005\:|\-g2005-sv\:|\-g2009\:|\-g2012\:|\-g] +[\-g1995\:|\-g2001\:|\-g2005\:|\-g2005-sv\:|\-g2009\:|\-g2012\:|\-g2017\:|\-g2023\:|\-g] [\-Iincludedir] [\-Lmoduledir] [\-mmodule] [\-M[mode=]file] [\-Nfile] [\-ooutputfilename] [\-stopmodule] [\-ttype] [\-Tmin/typ/max] [\-Wclass] [\-ypath] [\-lfile] @@ -21,13 +21,36 @@ further processing. The main target is \fIvvp\fP for simulation. .SH OPTIONS \fIiverilog\fP accepts the following options: .TP 8 -.B -B\fIbase\fP +.BI \-B path The \fIiverilog\fP program uses external programs and configuration -files to preprocess and compile the Verilog source. Normally, the path -used to locate these tools is built into the \fIiverilog\fP -program. However, the \fB\-B\fP switch allows the user to select a -different set of programs. The path given is used to locate -\fIivlpp\fP, \fIivl\fP, code generators and the VPI modules. +files to preprocess and compile Verilog source files. Normally, the +paths used to locate these tools are built into the +\fIiverilog\fP executable. The \fB\-B\fP option allows the user to +override these paths. +The specified path is used as the default base directory for locating +\fIivlpp\fP, \fIivl\fP, code generators, configuration files, and +VPI modules. +Specialized forms of this option may be used to override individual +tool paths: +.RS +.TP +.BI \-BI path +Directory for the \fIivl\fP parser. +.TP +.BI \-BM path +Directory for VPI modules. +.TP +.BI \-BP path +Directory for the \fIivlpp\fP preprocessor. +.TP +.BI \-BV path +Directory for the \fIvhdlpp\fP VHDL preprocessor. +.TP +.BI \-Bt path +Directory used to locate target configuration files for the +\fB\-t\fP\fItarget\fP option. The configuration file name is +\fItarget\fP.conf. +.RE .TP 8 .B -c\fIfile\fP -f\fIfile\fP These flags specify an input file that contains a list of Verilog @@ -63,11 +86,11 @@ is the Verilog input, but with file inclusions and macro references expanded and removed. This is useful, for example, to preprocess Verilog source for use by other compilers. .TP 8 -.B -g1995\fI|\fP-g2001\fI|\fP-g2001-noconfig\fI|\fP-g2005\fI|\fP-g2005-sv\fI|\fP-g2009\fI|\fP-g2012 +.B -g1995\fI|\fP-g2001\fI|\fP-g2001-noconfig\fI|\fP-g2005\fI|\fP-g2005-sv\fI|\fP-g2009\fI|\fP-g2012\fI|\fP-g2017\fI|\fP-g2023 Select the Verilog language \fIgeneration\fP to support in the compiler. This selects between \fIIEEE1364\-1995\fP, \fIIEEE1364\-2001\fP, -\fIIEEE1364\-2005\fP, \fIIEEE1800\-2005\fP, \fIIEEE1800\-2009\fP, or -\fIIEEE1800\-2012\fP. +\fIIEEE1364\-2005\fP, \fIIEEE1800\-2005\fP, \fIIEEE1800\-2009\fP, +\fIIEEE1800\-2012\fP, \fIIEEE1800\-2017\fP, or \fIIEEE1800\-2023\fP. Icarus Verilog currently defaults to the \fIIEEE1364\-2005\fP generation of the language. This flag is used to restrict the language to a set of keywords/features, this allows simulation of older Verilog code that may diff --git a/driver/main.c b/driver/main.c index 0fed62ee7..95d02e91b 100644 --- a/driver/main.c +++ b/driver/main.c @@ -38,8 +38,8 @@ const char NOTICE[] = ; const char HELP[] = -"Usage: iverilog [-EiRSuvV] [-B base] [-c cmdfile|-f cmdfile]\n" -" [-g1995|-g2001|-g2005|-g2005-sv|-g2009|-g2012] [-g]\n" +"Usage: iverilog [-EiRSuvV] [-B[IMPVt] base] [-c cmdfile|-f cmdfile]\n" +" [-g1995|-g2001|-g2005|-g2005-sv|-g2009|-g2012|-g2017|-g2023] [-g]\n" " [-D macro[=defn]] [-I includedir] [-L moduledir]\n" " [-M [mode=]depfile] [-m module]\n" " [-N file] [-o filename] [-p flag=value]\n" @@ -112,6 +112,8 @@ extern void cfreset(FILE*fd, const char*path); const char*base = 0; const char*vpi_dir = 0; +const char*tconfig_dir = 0; +const char*ivl_dir = 0; const char*ivlpp_dir = 0; const char*vhdlpp_dir= 0; const char*vhdlpp_work = 0; @@ -340,7 +342,7 @@ static int t_version_only(void) } fflush(0); - snprintf(tmp, sizeof tmp, "%s%civl -V -C\"%s\" -C\"%s\"", base, sep, + snprintf(tmp, sizeof tmp, "%s%civl -V -C\"%s\" -C\"%s\"", ivl_dir, sep, iconfig_path, iconfig_common_path); rc = system(tmp); if (rc != 0) { @@ -447,7 +449,7 @@ static int t_compile(void) #endif /* Build the ivl command. */ - snprintf(tmp, sizeof tmp, "%s%civl", base, sep); + snprintf(tmp, sizeof tmp, "%s%civl", ivl_dir, sep); rc = strlen(tmp); cmd = realloc(cmd, ncmd+rc+1); strcpy(cmd+ncmd, tmp); @@ -740,6 +742,12 @@ static int process_generation(const char*name) else if (strcmp(name,"2012") == 0) generation = "2012"; + else if (strcmp(name,"2017") == 0) + generation = "2017"; + + else if (strcmp(name,"2023") == 0) + generation = "2023"; + else if (strcmp(name,"1") == 0) { /* Deprecated: use 1995 */ generation = "1995"; gen_xtypes = "no-xtypes"; @@ -860,6 +868,8 @@ static int process_generation(const char*name) " 2005-sv -- IEEE1800-2005\n" " 2009 -- IEEE1800-2009\n" " 2012 -- IEEE1800-2012\n" + " 2017 -- IEEE1800-2017\n" + " 2023 -- IEEE1800-2023\n" "Other generation flags:\n" " assertions | supported-assertions | no-assertions\n" " specify | no-specify\n" @@ -1216,6 +1226,9 @@ int main(int argc, char **argv) character of the path indicates which path the user is specifying. */ switch (optarg[0]) { + case 'I': /* Path for the ivl parser */ + ivl_dir = optarg+1; + break; case 'M': /* Path for the VPI modules */ vpi_dir = optarg+1; break; @@ -1225,6 +1238,9 @@ int main(int argc, char **argv) case 'V': /* Path for the vhdlpp VHDL processor */ vhdlpp_dir = optarg+1; break; + case 't': /* Path to target.conf for the -ttarget option */ + tconfig_dir = optarg+1; + break; default: /* Otherwise, this is a default base. */ base=optarg; break; @@ -1367,8 +1383,12 @@ int main(int argc, char **argv) vpi_dir = base; if (ivlpp_dir == 0) ivlpp_dir = base; + if (ivl_dir == 0) + ivl_dir = base; if (vhdlpp_dir == 0) vhdlpp_dir = base; + if (tconfig_dir == 0) + tconfig_dir = base; if (version_flag || verbose_flag) { printf("Icarus Verilog version " VERSION " (" VERSION_TAG ")\n\n"); @@ -1378,7 +1398,7 @@ int main(int argc, char **argv) /* Make a common conf file path to reflect the target. */ snprintf(iconfig_common_path, sizeof iconfig_common_path, "%s%c%s%s.conf", - base, sep, targ, synth_flag? "-s" : ""); + tconfig_dir, sep, targ, synth_flag? "-s" : ""); /* Write values to the iconfig file. */ fprintf(iconfig_file, "basedir:%s\n", base); @@ -1388,11 +1408,13 @@ int main(int argc, char **argv) fprintf(iconfig_file, "module:%s%cvhdl_sys.vpi\n", vpi_dir, sep); fprintf(iconfig_file, "module:%s%cvhdl_textio.vpi\n", vpi_dir, sep); - /* If verilog-2005/09/12 is enabled or icarus-misc or verilog-ams, + /* If verilog-2005/09/12/17/23 is enabled or icarus-misc or verilog-ams, * then include the v2005_math library. */ if (strcmp(generation, "2005") == 0 || strcmp(generation, "2009") == 0 || strcmp(generation, "2012") == 0 || + strcmp(generation, "2017") == 0 || + strcmp(generation, "2023") == 0 || strcmp(gen_icarus, "icarus-misc") == 0 || strcmp(gen_verilog_ams, "verilog-ams") == 0) { fprintf(iconfig_file, "module:%s%cv2005_math.vpi\n", vpi_dir, sep); @@ -1407,7 +1429,9 @@ int main(int argc, char **argv) v2009 module. */ if (strcmp(generation, "2005-sv") == 0 || strcmp(generation, "2009") == 0 || - strcmp(generation, "2012") == 0) { + strcmp(generation, "2012") == 0 || + strcmp(generation, "2017") == 0 || + strcmp(generation, "2023") == 0) { fprintf(iconfig_file, "module:%s%cv2009.vpi\n", vpi_dir, sep); } diff --git a/elab_expr.cc b/elab_expr.cc index e92f34d71..5477d4360 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -499,6 +499,9 @@ NetExpr* PEAssignPattern::elaborate_expr_uarray_(Design *des, NetScope *scope, if (const auto ap = dynamic_cast(parms_[idx])) { expr = ap->elaborate_expr_uarray_(des, scope, uarray_type, dims, cur_dim, need_const); + } else if (const auto s = dynamic_cast(parms_[idx])) { + expr = s->elaborate_expr_uarray_(des, scope, uarray_type, + dims, cur_dim); } else if (dynamic_cast(parms_[idx])) { cerr << get_fileline() << ": sorry: " << "Array concatenation is not yet supported." @@ -6186,20 +6189,6 @@ NetExpr* PEIdent::calculate_up_do_base_(Design*des, NetScope*scope, unsigned PEIdent::test_width_parameter_(const NetExpr *par, width_mode_t&mode) { - // The width of an enumeration literal is the width of the - // enumeration base. - if (const NetEConstEnum*par_enum = dynamic_cast (par)) { - const netenum_t*use_enum = par_enum->enumeration(); - ivl_assert(*this, use_enum != 0); - - expr_type_ = use_enum->base_type(); - expr_width_ = use_enum->packed_width(); - min_width_ = expr_width_; - signed_flag_ = par_enum->has_sign(); - - return expr_width_; - } - expr_type_ = par->expr_type(); expr_width_ = par->expr_width(); min_width_ = expr_width_; @@ -6827,6 +6816,9 @@ NetExpr* PEIdent::elaborate_expr_(Design*des, NetScope*scope, // If the identifier names a signal (a variable or a net) // then create a NetESignal node to handle it. if (sr.net != 0) { + if (!check_interface_modport_access(this, des, sr, false)) + return 0; + if (NEED_CONST & flags) { cerr << get_fileline() << ": error: A reference to a net " "or variable (`" << path_ << "') is not allowed in " @@ -8816,19 +8808,8 @@ NetExpr* PENewArray::elaborate_expr(Design*des, NetScope*scope, NetExpr*size = size_->elaborate_expr(des, scope, use_wid, flags); NetExpr*init_val = 0; - if (dynamic_cast (init_)) { - // Special case: the initial value expression is an - // array_pattern. Elaborate the expression like the - // r-value to an assignment to array. + if (init_) { init_val = init_->elaborate_expr(des, scope, ntype, flags); - - } else if (init_) { - // Regular case: The initial value is an - // expression. Elaborate the expression as an element - // type. The run-time will assign this value to each element. - const netarray_t*array_type = dynamic_cast (ntype); - - init_val = init_->elaborate_expr(des, scope, array_type, flags); } NetENew*tmp = new NetENew(ntype, size, init_val); @@ -9151,13 +9132,86 @@ unsigned PEString::test_width(Design*, NetScope*, width_mode_t&) return expr_width_; } -NetEConst* PEString::elaborate_expr(Design*, NetScope*, ivl_type_t, unsigned) const +NetExpr* PEString::elaborate_expr_uarray_(Design *des, NetScope *, + const netuarray_t *uarray_type, + const std::vector &dims, + unsigned int cur_dim) const { - NetECString*tmp = new NetECString(value()); - tmp->cast_signed(signed_flag_); - tmp->set_line(*this); + // This is a special case. The LRM allows string literals to be + // assigned to unpacked arrays of bytes. + const auto element_type = uarray_type->element_type(); - return tmp; + if (dims.size() - 1 != cur_dim || !element_type->packed() || + element_type->base_type() != IVL_VT_BOOL || + element_type->packed_width() != 8 || !element_type->get_signed()) { + cerr << get_fileline() << ": error: " + << "String literal can not be implicitly cast to the target type." + << endl; + des->errors++; + return nullptr; + } + + + // The size doesn't have to match. Elements are copied left aligned, which + // is different from assignments of string literals to packed arrays where + // they are copied right aligned. + + vector elem_exprs(dims[cur_dim].width()); + bool asc = dims[cur_dim].get_msb() < dims[cur_dim].get_lsb(); + unsigned int elem_idx = asc ? 0 : elem_exprs.size() - 1; + + verinum text_val(text_); + + if (text_val.len() > elem_exprs.size() * 8) { + cerr << get_fileline() << ": warning: " + << "Target array smaller than assigned value. " + << "Value will be truncated." << endl; + } + + for (unsigned int i = 0; i < min((size_t)text_val.len() / 8, elem_exprs.size()); i++) { + verinum val(text_val >> (text_val.len() - 8 - i * 8), 8); + val.has_sign(true); + + elem_exprs[elem_idx] = new NetEConst(element_type, val); + + if (asc) + elem_idx++; + else + elem_idx--; + } + + // Add padding if necessary + for (unsigned int i = text_val.len() / 8; i < elem_exprs.size(); i++) { + verinum val(verinum::V0, 8); + val.has_sign(true); + + elem_exprs[elem_idx] = new NetEConst(element_type, val); + + if (asc) + elem_idx++; + else + elem_idx--; + } + + return new NetEArrayPattern(uarray_type, elem_exprs); +} + +NetExpr* PEString::elaborate_expr(Design *des, NetScope *scope, ivl_type_t type, unsigned) const +{ + NetExpr *expr; + + auto uarray_type = dynamic_cast(type); + if (uarray_type) { + expr = elaborate_expr_uarray_(des, scope, uarray_type, + uarray_type->static_dimensions(), 0); + } else { + expr = new NetECString(value()); + expr->cast_signed(signed_flag_); + } + + if (expr) + expr->set_line(*this); + return expr; } /* diff --git a/elab_lval.cc b/elab_lval.cc index 4f1859c43..1068954d1 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2025 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2026 Stephen Williams (steve@icarus.com) * Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -133,11 +133,13 @@ NetAssign_* PEConcat::elaborate_lval(Design*des, the compiler catch more errors. */ if (tmp == 0) continue; - if (tmp->expr_type() == IVL_VT_REAL) { + ivl_type_t tmp_type = tmp->net_type(); + if (tmp_type && !tmp_type->packed()) { cerr << parms_[idx]->get_fileline() << ": error: " - << "concatenation operand can not be real: " + << "concatenation operand must be packed: " << *parms_[idx] << endl; des->errors += 1; + delete tmp; continue; } diff --git a/elab_net.cc b/elab_net.cc index 6ec75d067..9db05d56d 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2025 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2026 Stephen Williams (steve@icarus.com) * Copyright CERN 2012 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -83,16 +83,22 @@ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope, } if (nets[idx] == 0) { - errors += 1; - } else if (nets[idx]->data_type() == IVL_VT_REAL) { - cerr << parms_[idx]->get_fileline() << ": error: " - << "concatenation operand can no be real: " - << *parms_[idx] << endl; errors += 1; - continue; } else { - width += nets[idx]->vector_width(); - } + ivl_type_t tmp_type = nets[idx]->array_type(); + if (!tmp_type) + tmp_type = nets[idx]->net_type(); + + if (tmp_type && !tmp_type->packed()) { + cerr << parms_[idx]->get_fileline() << ": error: " + << "concatenation operand must be packed: " + << *parms_[idx] << endl; + errors += 1; + continue; + } + + width += nets[idx]->vector_width(); + } } if (errors) { @@ -557,6 +563,9 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, return 0; } + if (!check_interface_modport_access(this, des, sr, true)) + return 0; + if (debug_elaborate) { cerr << get_fileline() << ": " << __func__ << ": " << "Found l-value path_=" << path_ @@ -616,6 +625,9 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, // array word assignment. bool widx_flag = false; + // Whether the signal is an array + const bool sig_is_array = sig->unpacked_dimensions() > 0; + // Detect the net is a structure and there was a method path // detected. We have already broken the path_ into the path to // the net, and the path of member names. For example, if the @@ -751,7 +763,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, } } - } else if (gn_system_verilog() && sig->unpacked_dimensions() > 0 && path_tail.index.empty()) { + } else if (gn_system_verilog() && sig_is_array && path_tail.index.empty()) { // In this case, we are doing a continuous assignment to // an unpacked array. The NetNet representation is a @@ -761,15 +773,14 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, // This can come up from code like this: // logic [...] data [0:3]; // assign data = ...; - // In this case, "sig" is "data", and sig->pin_count() - // is 4 to account for the unpacked size. + // In this case, "sig" is "data". if (debug_elaborate) { cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: " << "Net assign to unpacked array \"" << sig->name() << "\" with " << sig->pin_count() << " elements." << endl; } - } else if (sig->unpacked_dimensions() > 0) { + } else if (sig_is_array) { list unpacked_indices_const; @@ -931,7 +942,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, } } - if (sig->pin_count() > 1 && widx_flag) { + if (sig_is_array && widx_flag) { if (widx < 0 || widx >= (long) sig->pin_count()) return 0; NetNet*tmp = new NetNet(scope, scope->local_symbol(), @@ -941,7 +952,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, connect(sig->pin(widx), tmp->pin(0)); sig = tmp; - } else if (sig->pin_count() > 1) { + } else if (sig_is_array) { // If this turns out to be an l-value unpacked array, // then let the caller handle it. It will probably be diff --git a/elab_sig.cc b/elab_sig.cc index 19fa97a42..2d40012bf 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -44,6 +44,7 @@ # include "netqueue.h" # include "netscalar.h" # include "util.h" +# include "parse_api.h" # include "ivl_assert.h" using namespace std; @@ -298,6 +299,12 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const if (pp == 0) continue; + if (pp->is_interface_port()) { + interface_formal_port_t formal; + resolve_interface_formal_port(this, des, pp, formal, true); + continue; + } + // The port has a name and an array of expressions. The // expression are all identifiers that should reference // wires within the scope. @@ -451,6 +458,12 @@ bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope, NetScope::scope_vec_t instance = scope->instance_arrays[get_name()]; + vectorpins (rmod->port_count()); + vectorpins_fromwc (rmod->port_count(), false); + vectorpins_is_explicitly_not_connected (rmod->port_count(), false); + flag &= match_module_ports_(des, rmod, scope, pins, pins_fromwc, + pins_is_explicitly_not_connected); + for (unsigned idx = 0 ; idx < instance.size() ; idx += 1) { // I know a priori that the elaborate_scope created the scope // already, so just look it up as a child of the current scope. @@ -466,6 +479,9 @@ bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope, } ivl_assert(*this, my_scope->parent() == scope); + if (!bind_interface_ports_(des, rmod, scope, my_scope, pins, pins_fromwc)) + flag = false; + if (! rmod->elaborate_sig(des, my_scope)) flag = false; @@ -1176,8 +1192,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) pull = new NetLogic(scope, scope->local_symbol(), 1, pull_type, wid); pull->set_line(*this); - pull->pin(0).drive0(IVL_DR_SUPPLY); - pull->pin(0).drive1(IVL_DR_SUPPLY); + pull->pin(0).drive(drive_strength_t(IVL_DR_SUPPLY, + IVL_DR_SUPPLY)); des->add_node(pull); wtype = NetNet::WIRE; } diff --git a/elab_type.cc b/elab_type.cc index 9048e3afc..c905791e1 100644 --- a/elab_type.cc +++ b/elab_type.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2024 Stephen Williams (steve@icarus.com) + * Copyright (c) 2012-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -220,11 +220,13 @@ ivl_type_t struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const res->set_line(*this); - res->packed(packed_flag); + bool is_packed = packed_flag || (union_flag && soft_flag); + res->packed(is_packed); res->set_signed(signed_flag); - if (union_flag) - res->union_flag(true); + if (union_flag) { + res->union_flag(true, soft_flag); + } for (list::iterator cur = members->begin() ; cur != members->end() ; ++ cur) { @@ -242,7 +244,7 @@ ivl_type_t struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const ; cur_name != curp->names->end() ; ++ cur_name) { decl_assignment_t*namep = *cur_name; - if (packed_flag && namep->expr) { + if (is_packed && namep->expr) { cerr << namep->expr->get_fileline() << " error: " << "Packed structs must not have default member values." << endl; @@ -450,27 +452,7 @@ ivl_type_t typedef_t::elaborate_type(Design *des, NetScope *scope) if (!elab_type) return netvector_t::integer_type(); - bool type_ok = true; - switch (basic_type) { - case ENUM: - type_ok = dynamic_cast(elab_type); - break; - case STRUCT: { - const netstruct_t *struct_type = dynamic_cast(elab_type); - type_ok = struct_type && !struct_type->union_flag(); - break; - } - case UNION: { - const netstruct_t *struct_type = dynamic_cast(elab_type); - type_ok = struct_type && struct_type->union_flag(); - break; - } - case CLASS: - type_ok = dynamic_cast(elab_type); - break; - default: - break; - } + bool type_ok = basic_type.matches(elab_type); if (!type_ok) { cerr << data_type->get_fileline() << " error: " diff --git a/elaborate.cc b/elaborate.cc index 8658f6fab..c2ff5d887 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2025 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2026 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -52,6 +52,7 @@ # include "netscalar.h" # include "netclass.h" # include "netmisc.h" +# include "PModport.h" # include "util.h" # include "parse_api.h" # include "compiler.h" @@ -115,19 +116,16 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const { ivl_assert(*this, scope); - NetExpr* rise_time, *fall_time, *decay_time; - eval_delays(des, scope, rise_time, fall_time, decay_time, true); - - ivl_drive_t drive0 = strength0(); - ivl_drive_t drive1 = strength1(); + drive_strength_t drive = strength(); + delay_exprs_t delays; + eval_delays(des, scope, delays, true); ivl_assert(*this, pin(0)); ivl_assert(*this, pin(1)); /* Elaborate the l-value. */ // A continuous assignment can drive a variable if the default strength is used. - bool var_allowed_in_sv = (drive0 == IVL_DR_STRONG && - drive1 == IVL_DR_STRONG) ? true : false; + bool var_allowed_in_sv = !drive.has_drive(); NetNet*lval = pin(0)->elaborate_lnet(des, scope, var_allowed_in_sv); if (lval == 0) { return; @@ -135,8 +133,8 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const // If this turns out to be an assignment to an unpacked array, // then handle that special case elsewhere. - if (lval->pin_count() > 1) { - elaborate_unpacked_array_(des, scope, lval); + if (lval->unpacked_dimensions() > 0) { + elaborate_unpacked_array_(des, scope, lval, drive, delays); return; } @@ -214,7 +212,7 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const /* When we are given a non-default strength value and if the drive * source is a bit, part, indexed select or a concatenation we need * to add a driver (BUFZ) to convey the strength information. */ - if ((drive0 != IVL_DR_STRONG || drive1 != IVL_DR_STRONG) && + if (drive.has_drive() && ((dynamic_cast(rval_expr)) || (dynamic_cast(rval_expr)))) { need_driver_flag = true; @@ -242,11 +240,11 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const /* Set the drive and delays for the r-val. */ - if (drive0 != IVL_DR_STRONG || drive1 != IVL_DR_STRONG) - rval->pin(0).drivers_drive(drive0, drive1); + if (drive.has_drive()) + rval->pin(0).drivers_drive(drive); - if (rise_time || fall_time || decay_time) - rval->pin(0).drivers_delays(rise_time, fall_time, decay_time); + if (delays.has_delay()) + rval->pin(0).drivers_delays(delays); connect(lval->pin(0), rval->pin(0)); @@ -267,7 +265,8 @@ NetNet *elaborate_unpacked_array(Design *des, NetScope *scope, const LineInfo &l << endl; des->errors++; return nullptr; - } else if (dynamic_cast (expr)) { + } else if (dynamic_cast (expr) || + dynamic_cast (expr)) { auto net_expr = elaborate_rval_expr(des, scope, lval->array_type(), expr); if (! net_expr) return nullptr; expr_net = net_expr->synthesize(des, scope, net_expr); @@ -313,11 +312,14 @@ NetNet *elaborate_unpacked_array(Design *des, NetScope *scope, const LineInfo &l return expr_net; } -void PGAssign::elaborate_unpacked_array_(Design*des, NetScope*scope, NetNet*lval) const +void PGAssign::elaborate_unpacked_array_(Design*des, NetScope*scope, NetNet*lval, + const drive_strength_t &drive, + const delay_exprs_t &delays) const { NetNet *rval_net = elaborate_unpacked_array(des, scope, *this, lval, pin(1)); if (rval_net) - assign_unpacked_with_bufz(des, scope, lval, lval, rval_net); + assign_unpacked_with_bufz(des, scope, lval, lval, rval_net, drive, + delays); } void PGBuiltin::calculate_gate_and_lval_count_(unsigned&gate_count, @@ -825,8 +827,9 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const values are given, they are taken as specified. */ if (check_delay_count(des)) return; - NetExpr* rise_time, *fall_time, *decay_time; - eval_delays(des, scope, rise_time, fall_time, decay_time, true); + delay_exprs_t delays; + eval_delays(des, scope, delays, true); + drive_strength_t drive = strength(); struct attrib_list_t*attrib_list; unsigned attrib_list_n = 0; @@ -858,12 +861,8 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const attrib_list[adx].val); /* Set the delays and drive strength for all built in gates. */ - cur[idx]->rise_time(rise_time); - cur[idx]->fall_time(fall_time); - cur[idx]->decay_time(decay_time); - - cur[idx]->pin(0).drive0(strength0()); - cur[idx]->pin(0).drive1(strength1()); + cur[idx]->delay_times(delays); + cur[idx]->pin(0).drive(drive); cur[idx]->set_line(*this); des->add_node(cur[idx]); @@ -1203,6 +1202,17 @@ void elaborate_unpacked_port(Design *des, NetScope *scope, NetNet *port_net, PExpr *expr, NetNet::PortType port_type, const Module *mod, unsigned int port_idx) { + if (port_type == NetNet::POUTPUT && !dynamic_cast (expr)) { + perm_string port_name = mod->get_port_name(port_idx); + cerr << expr->get_fileline() << ": error: Output port expression" + " must support a continuous assignment." << endl; + cerr << expr->get_fileline() << ": : Port " + << port_idx + 1 << " (" << port_name << ") of " + << mod->mod_name() << " is connected to " << *expr << endl; + des->errors += 1; + return; + } + NetNet *expr_net = elaborate_unpacked_array(des, scope, *expr, port_net, expr); if (!expr_net) { @@ -1237,32 +1247,12 @@ void elaborate_unpacked_port(Design *des, NetScope *scope, NetNet *port_net, assign_unpacked_with_bufz(des, scope, port_net, port_net, expr_net); } -/* - * Instantiate a module by recursively elaborating it. Set the path of - * the recursive elaboration so that signal names get properly - * set. Connect the ports of the instantiated module to the signals of - * the parameters. This is done with BUFZ gates so that they look just - * like continuous assignment connections. - */ -void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const +bool PGModule::match_module_ports_(Design*des, const Module*rmod, + NetScope*scope, + vector&pins, + vector&pins_fromwc, + vector&pins_is_explicitly_not_connected) const { - - ivl_assert(*this, scope); - - if (debug_elaborate) { - cerr << get_fileline() << ": debug: Instantiate module " - << rmod->mod_name() << " with instance name " - << get_name() << " in scope " << scope_path(scope) << endl; - } - - // This is the array of pin expressions, shuffled to match the - // order of the declaration. If the source instantiation uses - // bind by order, this is the same as the source list. Otherwise, - // the source list is rearranged by name binding into this list. - vectorpins (rmod->port_count()); - vectorpins_fromwc (rmod->port_count(), false); - vectorpins_is_explicitly_not_connected (rmod->port_count(), false); - // If the instance has a pins_ member, then we know we are // binding by name. Therefore, make up a pins array that // reflects the positions of the named ports. @@ -1271,8 +1261,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const // Scan the bindings, matching them with port names. for (unsigned idx = 0 ; idx < npins_ ; idx += 1) { - - // Handle wildcard named port + // Handle wildcard named port. if (pins_[idx].name[0] == '*') { for (unsigned j = 0 ; j < nexp ; j += 1) { if (rmod->ports[j] && !pins[j] && !pins_is_explicitly_not_connected[j]) { @@ -1281,7 +1270,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const path_.push_back(name_component_t(rmod->ports[j]->name)); symbol_search_results sr; symbol_search(this, des, scope, path_, UINT_MAX, &sr); - if (sr.net != 0) { + if (sr.net != 0 || + (rmod->ports[j]->is_interface_port() && + sr.scope != 0 && sr.scope->is_interface())) { pins[j] = new PEIdent(rmod->ports[j]->name, UINT_MAX, true); pins[j]->set_lineno(get_lineno()); pins[j]->set_file(get_file()); @@ -1307,7 +1298,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const } // If I am overriding a wildcard port, delete and - // override it + // override it. if (pins_fromwc[pidx]) { delete pins[pidx]; pins_fromwc[pidx] = false; @@ -1331,36 +1322,387 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const pins_is_explicitly_not_connected[pidx] = true; } - } else if (pin_count() == 0) { - /* Handle the special case that no ports are connected. It is possible that this is an empty connect-by-name list, so we'll allow it and assume that is the case. */ - for (unsigned idx = 0 ; idx < rmod->port_count() ; idx += 1) pins[idx] = 0; } else { - /* Otherwise, this is a positional list of port connections. Use as many ports as provided. Trailing missing ports will be left unconnect or use the default - value if one is available */ - + value if one is available. */ if (pin_count() > rmod->port_count()) { cerr << get_fileline() << ": error: Wrong number " "of ports. Expecting at most " << rmod->port_count() << ", got " << pin_count() << "." << endl; des->errors += 1; - return; + return false; } std::copy(get_pins().begin(), get_pins().end(), pins.begin()); } + return true; +} + +struct interface_actual_scope_t { + interface_actual_scope_t() : scope(nullptr), modport(nullptr) { } + + NetScope*scope; + const PModport*modport; + perm_string display_name; +}; + +struct interface_actual_array_t { + std::map elements; + perm_string display_name; +}; + +static long interface_array_index(unsigned idx, long left, long right) +{ + long low = left < right ? left : right; + long high = left < right ? right : left; + return low < high ? low + idx : low - idx; +} + +static bool interface_formal_range(const Module::port_t*port, + Design*des, NetScope*scope, + const LineInfo*li, + long&left, long&right, + unsigned&count) +{ + if (!port->interface_unpacked_dimensions) { + left = 0; + right = 0; + count = 1; + return true; + } + + if (port->interface_unpacked_dimensions->size() != 1) { + cerr << li->get_fileline() << ": sorry: Interface port `" + << port->name << "' uses a multidimensional array, which " + "is not supported." << endl; + des->errors += 1; + return false; + } + + if (!evaluate_range(des, scope, li, + port->interface_unpacked_dimensions->front(), + left, right)) + return false; + + count = left > right ? left - right + 1 : right - left + 1; + return true; +} + +static bool resolve_interface_actual_scope(const PExpr*actual, + NetScope*parent_scope, + Design*des, + interface_actual_scope_t&res) +{ + res = interface_actual_scope_t(); + + const PEIdent*actual_ident = dynamic_cast(actual); + if (!actual_ident || actual_ident->path().package || + actual_ident->path().name.size() != 1 || + actual_ident->path().name.front().index.size() > 1) { + return false; + } + + const name_component_t&comp = actual_ident->path().name.front(); + res.display_name = comp.name; + + if (!comp.index.empty()) { + if (comp.index.front().sel != index_component_t::SEL_BIT) { + cerr << actual->get_fileline() << ": sorry: Interface array " + << "slice actuals are not supported." << endl; + des->errors += 1; + return true; + } + + bool error_flag = false; + hname_t actual_name = eval_path_component(des, parent_scope, + comp, error_flag); + if (error_flag) + return true; + + if (NetScope*child = parent_scope->child(actual_name)) + res.scope = child; + else if (actual_name.has_numbers()) { + const NetScope::interface_port_alias_t*alias = + parent_scope->find_interface_port_alias_element( + comp.name, actual_name.peek_number(0)); + if (alias) { + res.scope = alias->actual_scope; + res.modport = alias->modport; + } + } + + if (!res.scope) { + symbol_search_results sr; + symbol_search(actual, des, parent_scope, actual_ident->path(), + actual_ident->lexical_pos(), &sr); + res.scope = sr.scope; + if (sr.through_interface_alias()) + res.modport = sr.interface_alias_modport; + } + + return true; + } + + symbol_search_results sr; + symbol_search(actual, des, parent_scope, actual_ident->path(), + actual_ident->lexical_pos(), &sr); + + res.scope = sr.scope; + if (sr.through_interface_alias()) + res.modport = sr.interface_alias_modport; + else if (NetScope*child = parent_scope->child(hname_t(res.display_name))) + res.scope = child; + else if (const NetScope::interface_port_alias_t*alias = + parent_scope->find_interface_port_alias(res.display_name)) { + res.scope = alias->actual_scope; + res.modport = alias->modport; + } + + return true; +} + +static bool resolve_interface_actual_array(const PExpr*actual, + NetScope*parent_scope, + interface_actual_array_t&res) +{ + res = interface_actual_array_t(); + + const PEIdent*actual_ident = dynamic_cast(actual); + if (!actual_ident || actual_ident->path().package || + actual_ident->path().name.size() != 1 || + !actual_ident->path().name.front().index.empty()) + return false; + + perm_string name = actual_ident->path().name.front().name; + res.display_name = name; + + for (NetScope*scope = parent_scope ; scope ; scope = scope->parent()) { + auto arr = scope->instance_arrays.find(name); + if (arr != scope->instance_arrays.end()) { + for (unsigned idx = 0 ; idx < arr->second.size() ; idx += 1) { + NetScope*inst = arr->second[idx]; + if (!inst) + return false; + hname_t hname = inst->fullname(); + if (!hname.has_numbers()) + return false; + res.elements[hname.peek_number(0)] = + NetScope::interface_port_alias_t(inst, nullptr); + } + return true; + } + + const map*alias_arr = + scope->find_interface_port_alias_array(name); + if (alias_arr) { + res.elements = *alias_arr; + return true; + } + } + + return false; +} + +bool PGModule::bind_interface_ports_(Design*des, const Module*rmod, + NetScope*parent_scope, + NetScope*instance_scope, + const vector&pins, + const vector&) const +{ + bool flag = true; + + for (unsigned idx = 0 ; idx < rmod->port_count() ; idx += 1) { + const Module::port_t*port = rmod->get_port_info(idx); + if (!port || !port->is_interface_port()) + continue; + + if (!pins[idx]) { + cerr << get_fileline() << ": error: Interface port `" + << port->name << "' of module " << rmod->mod_name() + << " is not connected." << endl; + des->errors += 1; + flag = false; + continue; + } + + long formal_left = 0; + long formal_right = 0; + unsigned formal_count = 1; + if (!interface_formal_range(port, des, instance_scope, pins[idx], + formal_left, formal_right, formal_count)) { + flag = false; + continue; + } + bool formal_is_array = port->interface_unpacked_dimensions != nullptr; + + interface_formal_port_t formal; + resolve_interface_formal_port(pins[idx], des, port, formal, false); + if (!formal.module) + continue; + + if (formal_is_array) { + interface_actual_array_t actual_array; + if (!resolve_interface_actual_array(pins[idx], parent_scope, actual_array)) { + cerr << pins[idx]->get_fileline() << ": error: Interface " + << "array port `" << port->name << "' must be " + "connected to an interface instance array." << endl; + des->errors += 1; + flag = false; + continue; + } + + if (actual_array.elements.size() != formal_count) { + cerr << pins[idx]->get_fileline() << ": error: Interface " + << "array port `" << port->name << "' expects " + << formal_count << " element(s) but actual `" + << actual_array.display_name << "' has " + << actual_array.elements.size() << " element(s)." << endl; + des->errors += 1; + flag = false; + continue; + } + + unsigned pos = 0; + bool array_ok = true; + for (auto cur = actual_array.elements.begin() + ; cur != actual_array.elements.end() ; ++cur, ++pos) { + NetScope*actual_scope = cur->second.actual_scope; + if (!actual_scope || !actual_scope->is_interface()) { + cerr << pins[idx]->get_fileline() << ": error: Actual " + << "element for interface array port `" + << port->name << "' is not an interface instance." << endl; + des->errors += 1; + array_ok = false; + continue; + } + + if (actual_scope->module_name() != formal.module->mod_name()) { + cerr << pins[idx]->get_fileline() << ": error: Interface " + << "array port `" << port->name + << "' expects interface type `" << port->interface_type + << "' but actual `" << actual_array.display_name + << "' has element type `" << actual_scope->module_name() + << "'." << endl; + des->errors += 1; + array_ok = false; + continue; + } + + if (cur->second.modport && formal.modport && + cur->second.modport->name() != formal.modport->name()) { + cerr << pins[idx]->get_fileline() << ": error: Interface " + << "array port `" << port->name + << "' cannot forward actual `" << actual_array.display_name + << "' restricted by modport `" << cur->second.modport->name() + << "' to formal modport `" << formal.modport->name() + << "'." << endl; + des->errors += 1; + array_ok = false; + continue; + } + + const PModport*modport = formal.modport? + formal.modport : cur->second.modport; + long formal_index = interface_array_index(pos, formal_left, formal_right); + instance_scope->add_interface_port_alias_element( + port->name, formal_index, actual_scope, modport); + } + + flag = flag && array_ok; + continue; + } + + interface_actual_scope_t actual; + if (!resolve_interface_actual_scope(pins[idx], parent_scope, des, actual)) { + cerr << pins[idx]->get_fileline() << ": error: Interface port `" + << port->name << "' must be connected to a simple " + "interface instance name." << endl; + des->errors += 1; + flag = false; + continue; + } + + if (!actual.scope || !actual.scope->is_interface()) { + cerr << pins[idx]->get_fileline() << ": error: Actual for " + "interface port `" << port->name + << "' is not an interface instance." << endl; + des->errors += 1; + flag = false; + continue; + } + + if (actual.scope->module_name() != formal.module->mod_name()) { + cerr << pins[idx]->get_fileline() << ": error: Interface port `" + << port->name << "' expects interface type `" + << port->interface_type << "' but actual `" << actual.display_name + << "' has type `" << actual.scope->module_name() << "'." << endl; + des->errors += 1; + flag = false; + continue; + } + + if (actual.modport && formal.modport && + actual.modport->name() != formal.modport->name()) { + cerr << pins[idx]->get_fileline() << ": error: Interface port `" + << port->name << "' cannot forward actual `" << actual.display_name + << "' restricted by modport `" << actual.modport->name() + << "' to formal modport `" << formal.modport->name() + << "'." << endl; + des->errors += 1; + flag = false; + continue; + } + + const PModport*modport = formal.modport? formal.modport : actual.modport; + instance_scope->add_interface_port_alias(port->name, actual.scope, + modport); + } + + return flag; +} + +/* + * Instantiate a module by recursively elaborating it. Set the path of + * the recursive elaboration so that signal names get properly + * set. Connect the ports of the instantiated module to the signals of + * the parameters. This is done with BUFZ gates so that they look just + * like continuous assignment connections. + */ +void PGModule::elaborate_mod_(Design*des, const Module*rmod, NetScope*scope) const +{ + + ivl_assert(*this, scope); + + if (debug_elaborate) { + cerr << get_fileline() << ": debug: Instantiate module " + << rmod->mod_name() << " with instance name " + << get_name() << " in scope " << scope_path(scope) << endl; + } + + // This is the array of pin expressions, shuffled to match the + // order of the declaration. If the source instantiation uses + // bind by order, this is the same as the source list. Otherwise, + // the source list is rearranged by name binding into this list. + vectorpins (rmod->port_count()); + vectorpins_fromwc (rmod->port_count(), false); + vectorpins_is_explicitly_not_connected (rmod->port_count(), false); + + if (!match_module_ports_(des, rmod, scope, pins, pins_fromwc, + pins_is_explicitly_not_connected)) + return; + // Elaborate these instances of the module. The recursive // elaboration causes the module to generate a netlist with // the ports represented by NetNet objects. I will find them @@ -1392,6 +1734,13 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const bool using_default = false; perm_string port_name = rmod->get_port_name(idx); + const Module::port_t*port_info = rmod->get_port_info(idx); + if (port_info && port_info->is_interface_port()) { + for (unsigned inst = 0 ; inst < instance.size() ; inst += 1) + instance[inst]->add_module_port_info(idx, port_name, + PortType::PIMPLICIT, 0); + continue; + } // If the port is unconnected, substitute the default // value. The parser ensures that a default value only @@ -2106,7 +2455,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const { - NetExpr*rise_expr =0, *fall_expr =0, *decay_expr =0; + delay_exprs_t delays; perm_string my_name = get_name(); if (my_name == 0) @@ -2123,8 +2472,7 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const } else { PDelays tmp_del; tmp_del.set_delays(overrides_, false); - tmp_del.eval_delays(des, scope, rise_expr, fall_expr, - decay_expr, true); + tmp_del.eval_delays(des, scope, delays, true); } } @@ -2143,9 +2491,7 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const ivl_assert(*this, udp); NetUDP*net = new NetUDP(scope, my_name, udp->ports.size(), udp); net->set_line(*this); - net->rise_time(rise_expr); - net->fall_time(fall_expr); - net->decay_time(decay_expr); + net->delay_times(delays); struct attrib_list_t*attrib_list; unsigned attrib_list_n = 0; @@ -5125,6 +5471,9 @@ cerr << endl; case PEEvent::NEGEDGE: cerr << "negedge"; break; + case PEEvent::EDGE: + cerr << "edge"; + break; default: cerr << "unknown edge type!"; ivl_assert(*this, 0); diff --git a/ivlpp/Makefile.in b/ivlpp/Makefile.in index 2fa327d26..7fdd9e2fb 100644 --- a/ivlpp/Makefile.in +++ b/ivlpp/Makefile.in @@ -89,4 +89,4 @@ uninstall: rm -f "$(DESTDIR)$(libdir)/ivl$(suffix)/ivlpp@EXEEXT@" lexor.o: lexor.c globals.h -main.o: main.c globals.h $(srcdir)/../version_base.h ../version_tag.h +main.o: main.c globals.h ../version_base.h ../version_tag.h diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index b20d27119..6da2aaafe 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -1692,7 +1692,6 @@ static void expand_using_args(void) char* head; char* tail; char* dest; - int arg; int length; if (def_argc > cur_macro->argc) { @@ -1721,7 +1720,7 @@ static void expand_using_args(void) if (*tail != ARG_MARK) { tail++; } else { - arg = tail[1]; assert(arg < def_argc); + int arg = tail[1]; assert(arg < def_argc); const char*use_argv; int use_argl; diff --git a/ivtest/.gitignore b/ivtest/.gitignore index 612f61d30..0482bb8d0 100644 --- a/ivtest/.gitignore +++ b/ivtest/.gitignore @@ -34,4 +34,5 @@ tmp_blif.vvp dump.vcd dump.lxt dump.lx2 +dump.fst foo.vcd diff --git a/ivtest/Makefile.in b/ivtest/Makefile.in new file mode 100644 index 000000000..a68469b04 --- /dev/null +++ b/ivtest/Makefile.in @@ -0,0 +1,70 @@ +# +# This source code is free software; you can redistribute it +# and/or modify it in source code form under the terms of the GNU +# Library General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +SHELL = /bin/sh + +abs_srcdir=@abs_srcdir@ +srcdir=@srcdir@ +suffix = @install_suffix@ +ifeq (@install_suffix@,) +opts = +else +opts = --suffix=$(suffix) +endif + +all: + +check: + +check-installed: + @status=0; \ + $(MAKE) check-installed-vvp || status=1; \ + $(MAKE) check-installed-vvp-py || status=1; \ + $(MAKE) check-installed-vpi || status=1; \ + exit $$status + +check-installed-vpi: + @echo "Running vpi_reg.pl" +ifeq (@LIBVERIUSER@,yes) + cd $(abs_srcdir); perl vpi_reg.pl --with-pli1 $(opts) +else + cd $(abs_srcdir); perl vpi_reg.pl $(opts) +endif + +check-installed-vvp: + @echo "Running vvp_reg.pl" + cd $(abs_srcdir); perl vvp_reg.pl $(opts) + +check-installed-vvp-py: + @echo "Running vvp_reg.py" + cd $(abs_srcdir); python3 vvp_reg.py $(opts) + +clean: + rm -f $(srcdir)/*.vpi + rm -rf $(srcdir)/log $(srcdir)/vpi_log $(srcdir)/work + +distclean: clean + rm -f Makefile + +install: + +uninstall: + +Makefile: $(srcdir)/Makefile.in ../config.status + cd ..; ./config.status --file=ivtest/$@ + +.PHONY: check-installed check-installed-vpi check-installed-vvp check-installed-vvp-py diff --git a/ivtest/gold/br_gh710d-vvp-stdout.gold b/ivtest/gold/br_gh710d-vvp-stdout.gold new file mode 100644 index 000000000..ce8f6d257 --- /dev/null +++ b/ivtest/gold/br_gh710d-vvp-stdout.gold @@ -0,0 +1 @@ +FST info: dumpfile dump.fst opened for output. diff --git a/ivtest/gold/sv_interface_port_array_modport_restrict_fail-iverilog-stderr.gold b/ivtest/gold/sv_interface_port_array_modport_restrict_fail-iverilog-stderr.gold new file mode 100644 index 000000000..5228fdac6 --- /dev/null +++ b/ivtest/gold/sv_interface_port_array_modport_restrict_fail-iverilog-stderr.gold @@ -0,0 +1,2 @@ +ivltests/sv_interface_port_array_modport_restrict_fail.v:10: error: Cannot assign to input modport member `value' through interface port `bus'. +1 error(s) during elaboration. diff --git a/ivtest/gold/sv_interface_port_array_size_mismatch_fail-iverilog-stderr.gold b/ivtest/gold/sv_interface_port_array_size_mismatch_fail-iverilog-stderr.gold new file mode 100644 index 000000000..ded548edf --- /dev/null +++ b/ivtest/gold/sv_interface_port_array_size_mismatch_fail-iverilog-stderr.gold @@ -0,0 +1,2 @@ +ivltests/sv_interface_port_array_size_mismatch_fail.v:12: error: Interface array port `bus' expects 2 element(s) but actual `buses' has 1 element(s). +Elaboration failed diff --git a/ivtest/gold/sv_interface_port_forwarding_restrict_fail-iverilog-stderr.gold b/ivtest/gold/sv_interface_port_forwarding_restrict_fail-iverilog-stderr.gold new file mode 100644 index 000000000..90758da05 --- /dev/null +++ b/ivtest/gold/sv_interface_port_forwarding_restrict_fail-iverilog-stderr.gold @@ -0,0 +1,3 @@ +ivltests/sv_interface_port_forwarding_restrict_fail.v:23: error: Interface member `hidden' is not listed in modport `consumer'. +ivltests/sv_interface_port_forwarding_restrict_fail.v:23: error: Unable to elaborate r-value: bus.hidden +2 error(s) during elaboration. diff --git a/ivtest/gold/sv_interface_port_missing_modport_fail-iverilog-stderr.gold b/ivtest/gold/sv_interface_port_missing_modport_fail-iverilog-stderr.gold new file mode 100644 index 000000000..7b28ae5f5 --- /dev/null +++ b/ivtest/gold/sv_interface_port_missing_modport_fail-iverilog-stderr.gold @@ -0,0 +1,2 @@ +ivltests/sv_interface_port_missing_modport_fail.v:18: error: Interface port bus uses unknown modport `consumer' of interface `bus_if'. +1 error(s) during elaboration. diff --git a/ivtest/gold/sv_interface_port_missing_type_fail-iverilog-stderr.gold b/ivtest/gold/sv_interface_port_missing_type_fail-iverilog-stderr.gold new file mode 100644 index 000000000..601207b55 --- /dev/null +++ b/ivtest/gold/sv_interface_port_missing_type_fail-iverilog-stderr.gold @@ -0,0 +1,2 @@ +ivltests/sv_interface_port_missing_type_fail.v:7: error: Interface port bus uses unknown interface type `missing_if'. +1 error(s) during elaboration. diff --git a/ivtest/gold/sv_interface_port_modport_input_write_fail-iverilog-stderr.gold b/ivtest/gold/sv_interface_port_modport_input_write_fail-iverilog-stderr.gold new file mode 100644 index 000000000..f8f61b1f6 --- /dev/null +++ b/ivtest/gold/sv_interface_port_modport_input_write_fail-iverilog-stderr.gold @@ -0,0 +1,2 @@ +ivltests/sv_interface_port_modport_input_write_fail.v:21: error: Cannot assign to input modport member `value' through interface port `bus'. +1 error(s) during elaboration. diff --git a/ivtest/gold/sv_interface_port_non_interface_actual_fail-iverilog-stderr.gold b/ivtest/gold/sv_interface_port_non_interface_actual_fail-iverilog-stderr.gold new file mode 100644 index 000000000..4c603b47c --- /dev/null +++ b/ivtest/gold/sv_interface_port_non_interface_actual_fail-iverilog-stderr.gold @@ -0,0 +1,2 @@ +ivltests/sv_interface_port_non_interface_actual_fail.v:9: error: Actual for interface port `bus' is not an interface instance. +Elaboration failed diff --git a/ivtest/gold/sv_interface_port_positional_unconnected_fail-iverilog-stderr.gold b/ivtest/gold/sv_interface_port_positional_unconnected_fail-iverilog-stderr.gold new file mode 100644 index 000000000..8fc0533db --- /dev/null +++ b/ivtest/gold/sv_interface_port_positional_unconnected_fail-iverilog-stderr.gold @@ -0,0 +1,2 @@ +ivltests/sv_interface_port_positional_unconnected_fail.v:7: error: Interface port `bus' of module bus_user is not connected. +Elaboration failed diff --git a/ivtest/gold/sv_interface_port_unlisted_member_fail-iverilog-stderr.gold b/ivtest/gold/sv_interface_port_unlisted_member_fail-iverilog-stderr.gold new file mode 100644 index 000000000..4295dc034 --- /dev/null +++ b/ivtest/gold/sv_interface_port_unlisted_member_fail-iverilog-stderr.gold @@ -0,0 +1,3 @@ +ivltests/sv_interface_port_unlisted_member_fail.v:24: error: Interface member `hidden' is not listed in modport `consumer'. +ivltests/sv_interface_port_unlisted_member_fail.v:24: error: Unable to elaborate r-value: bus.hidden +2 error(s) during elaboration. diff --git a/ivtest/gold/sv_interface_port_unmodported_missing_type_fail-iverilog-stderr.gold b/ivtest/gold/sv_interface_port_unmodported_missing_type_fail-iverilog-stderr.gold new file mode 100644 index 000000000..24caf2d27 --- /dev/null +++ b/ivtest/gold/sv_interface_port_unmodported_missing_type_fail-iverilog-stderr.gold @@ -0,0 +1,2 @@ +ivltests/sv_interface_port_unmodported_missing_type_fail.v:7: error: Interface port bus uses unknown interface type `missing_if'. +1 error(s) during elaboration. diff --git a/ivtest/gold/sv_interface_port_wrong_type_fail-iverilog-stderr.gold b/ivtest/gold/sv_interface_port_wrong_type_fail-iverilog-stderr.gold new file mode 100644 index 000000000..44e3c706c --- /dev/null +++ b/ivtest/gold/sv_interface_port_wrong_type_fail-iverilog-stderr.gold @@ -0,0 +1,2 @@ +ivltests/sv_interface_port_wrong_type_fail.v:9: error: Interface port `bus' expects interface type `bus_if' but actual `bus' has type `other_if'. +Elaboration failed diff --git a/ivtest/ivltests/array_index_real_fail.v b/ivtest/ivltests/array_index_real_fail.v new file mode 100644 index 000000000..763e24ee9 --- /dev/null +++ b/ivtest/ivltests/array_index_real_fail.v @@ -0,0 +1,12 @@ +// Check that real expressions can not be used as array indices. + +module test; + + reg [1:0] a[1:0]; + real r; + + initial begin + a[r] = 2'b10; + end + +endmodule diff --git a/ivtest/ivltests/begin_keywords_1364_1995.v b/ivtest/ivltests/begin_keywords_1364_1995.v new file mode 100644 index 000000000..ab0209665 --- /dev/null +++ b/ivtest/ivltests/begin_keywords_1364_1995.v @@ -0,0 +1,9 @@ +// Check that `begin_keywords accepts the 1364-1995 keyword set. + +`begin_keywords "1364-1995" +module test; + initial begin + $display("PASSED"); + end +endmodule +`end_keywords diff --git a/ivtest/ivltests/begin_keywords_1364_2001.v b/ivtest/ivltests/begin_keywords_1364_2001.v new file mode 100644 index 000000000..e3873759d --- /dev/null +++ b/ivtest/ivltests/begin_keywords_1364_2001.v @@ -0,0 +1,9 @@ +// Check that `begin_keywords accepts the 1364-2001 keyword set. + +`begin_keywords "1364-2001" +module test; + initial begin + $display("PASSED"); + end +endmodule +`end_keywords diff --git a/ivtest/ivltests/begin_keywords_1364_2001_noconfig.v b/ivtest/ivltests/begin_keywords_1364_2001_noconfig.v new file mode 100644 index 000000000..d75c4d2e0 --- /dev/null +++ b/ivtest/ivltests/begin_keywords_1364_2001_noconfig.v @@ -0,0 +1,9 @@ +// Check that `begin_keywords accepts the 1364-2001-noconfig keyword set. + +`begin_keywords "1364-2001-noconfig" +module test; + initial begin + $display("PASSED"); + end +endmodule +`end_keywords diff --git a/ivtest/ivltests/begin_keywords_1364_2005.v b/ivtest/ivltests/begin_keywords_1364_2005.v new file mode 100644 index 000000000..4f759305a --- /dev/null +++ b/ivtest/ivltests/begin_keywords_1364_2005.v @@ -0,0 +1,9 @@ +// Check that `begin_keywords accepts the 1364-2005 keyword set. + +`begin_keywords "1364-2005" +module test; + initial begin + $display("PASSED"); + end +endmodule +`end_keywords diff --git a/ivtest/ivltests/begin_keywords_1800_2005.v b/ivtest/ivltests/begin_keywords_1800_2005.v new file mode 100644 index 000000000..7cced42c1 --- /dev/null +++ b/ivtest/ivltests/begin_keywords_1800_2005.v @@ -0,0 +1,9 @@ +// Check that `begin_keywords accepts the 1800-2005 keyword set. + +`begin_keywords "1800-2005" +module test; + initial begin + $display("PASSED"); + end +endmodule +`end_keywords diff --git a/ivtest/ivltests/begin_keywords_1800_2009.v b/ivtest/ivltests/begin_keywords_1800_2009.v new file mode 100644 index 000000000..a1add0a40 --- /dev/null +++ b/ivtest/ivltests/begin_keywords_1800_2009.v @@ -0,0 +1,9 @@ +// Check that `begin_keywords accepts the 1800-2009 keyword set. + +`begin_keywords "1800-2009" +module test; + initial begin + $display("PASSED"); + end +endmodule +`end_keywords diff --git a/ivtest/ivltests/begin_keywords_1800_2012.v b/ivtest/ivltests/begin_keywords_1800_2012.v new file mode 100644 index 000000000..61e4707a3 --- /dev/null +++ b/ivtest/ivltests/begin_keywords_1800_2012.v @@ -0,0 +1,9 @@ +// Check that `begin_keywords accepts the 1800-2012 keyword set. + +`begin_keywords "1800-2012" +module test; + initial begin + $display("PASSED"); + end +endmodule +`end_keywords diff --git a/ivtest/ivltests/begin_keywords_1800_2017.v b/ivtest/ivltests/begin_keywords_1800_2017.v new file mode 100644 index 000000000..08befd948 --- /dev/null +++ b/ivtest/ivltests/begin_keywords_1800_2017.v @@ -0,0 +1,9 @@ +// Check that `begin_keywords accepts the 1800-2017 keyword set. + +`begin_keywords "1800-2017" +module test; + initial begin + $display("PASSED"); + end +endmodule +`end_keywords diff --git a/ivtest/ivltests/begin_keywords_1800_2023.v b/ivtest/ivltests/begin_keywords_1800_2023.v new file mode 100644 index 000000000..f665f7504 --- /dev/null +++ b/ivtest/ivltests/begin_keywords_1800_2023.v @@ -0,0 +1,9 @@ +// Check that `begin_keywords accepts the 1800-2023 keyword set. + +`begin_keywords "1800-2023" +module test; + initial begin + $display("PASSED"); + end +endmodule +`end_keywords diff --git a/ivtest/ivltests/begin_keywords_vams_2_3.v b/ivtest/ivltests/begin_keywords_vams_2_3.v new file mode 100644 index 000000000..b4bd9709e --- /dev/null +++ b/ivtest/ivltests/begin_keywords_vams_2_3.v @@ -0,0 +1,9 @@ +// Check that `begin_keywords accepts the VAMS-2.3 keyword set. + +`begin_keywords "VAMS-2.3" +module test; + initial begin + $display("PASSED"); + end +endmodule +`end_keywords diff --git a/ivtest/ivltests/drive_strength4.v b/ivtest/ivltests/drive_strength4.v new file mode 100644 index 000000000..5e90987fa --- /dev/null +++ b/ivtest/ivltests/drive_strength4.v @@ -0,0 +1,62 @@ +// Check that drive strength can be specified between the net type and the data +// type in a net declaration and that vector gate arrays resolve strengths +// correctly. + +module test; + + reg [7:0] pullval; + wire (weak0, weak1) [7:0] value = pullval; + + reg [7:0] en0; + reg [7:0] en1; + reg failed = 1'b0; + + `define check(expr, val) \ + if ((expr) !== (val)) begin \ + $display("FAILED(%0d): `%s`, expected %0h, got %0h", `__LINE__, \ + `"expr`", (val), (expr)); \ + failed = 1'b1; \ + end + + buf (highz0, strong1) drive0 [7:0] (value, en0); + not (strong0, highz1) drive1 [7:0] (value, en1); + + initial begin + en0 = 8'h00; + en1 = 8'h00; + + pullval = 8'hff; + #1 `check(value, 8'hff) + + pullval = 8'h00; + #1 `check(value, 8'h00) + + en0 = 8'haa; + pullval = 8'hff; + #1 `check(value, 8'hff) + + pullval = 8'h00; + #1 `check(value, 8'haa) + + en0 = 8'h00; + en1 = 8'hff; + pullval = 8'hff; + #1 `check(value, 8'h00) + + pullval = 8'h00; + #1 `check(value, 8'h00) + + en0 = 8'hff; + en1 = 8'hff; + pullval = 8'hff; + #1 `check(value, 8'hxx) + + pullval = 8'h00; + #1 `check(value, 8'hxx) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/module_port_array_fail1.v b/ivtest/ivltests/module_port_array_fail1.v new file mode 100644 index 000000000..4d6483ec0 --- /dev/null +++ b/ivtest/ivltests/module_port_array_fail1.v @@ -0,0 +1,17 @@ +// Check that an output array port expression must be assignable. + +module M ( + output int out [0:1] +); + + initial begin + out = '{3, 4}; + end + +endmodule + +module test; + + M i_m('{1, 2}); // Error: output expression is not assignable + +endmodule diff --git a/ivtest/ivltests/named_event_edge_fail.v b/ivtest/ivltests/named_event_edge_fail.v new file mode 100644 index 000000000..fbc51908c --- /dev/null +++ b/ivtest/ivltests/named_event_edge_fail.v @@ -0,0 +1,11 @@ +// Check that edge event controls can not be used with named events. + +module test; + + event e; + + initial begin + @(edge e); + end + +endmodule diff --git a/ivtest/ivltests/named_event_negedge_fail.v b/ivtest/ivltests/named_event_negedge_fail.v new file mode 100644 index 000000000..34b9c21f5 --- /dev/null +++ b/ivtest/ivltests/named_event_negedge_fail.v @@ -0,0 +1,11 @@ +// Check that negedge event controls can not be used with named events. + +module test; + + event e; + + initial begin + @(negedge e); + end + +endmodule diff --git a/ivtest/ivltests/named_event_no_edges.v b/ivtest/ivltests/named_event_no_edges.v deleted file mode 100644 index 4bbee0336..000000000 --- a/ivtest/ivltests/named_event_no_edges.v +++ /dev/null @@ -1,15 +0,0 @@ -module top; - event my_event; - - // The following two line should be an error - // You can not take the edge of a named event. - always @(posedge my_event) $display("Posedge event."); - always @(negedge my_event) $display("Negedge event."); - // This should work correctly. - always @(my_event) $display("Any event edge."); - - initial begin - #1 ->my_event; - #1 $display("FAILED"); - end -endmodule diff --git a/ivtest/ivltests/named_event_posedge_fail.v b/ivtest/ivltests/named_event_posedge_fail.v new file mode 100644 index 000000000..fd441f4b5 --- /dev/null +++ b/ivtest/ivltests/named_event_posedge_fail.v @@ -0,0 +1,11 @@ +// Check that posedge event controls can not be used with named events. + +module test; + + event e; + + initial begin + @(posedge e); + end + +endmodule diff --git a/ivtest/ivltests/nb_ec_array.v b/ivtest/ivltests/nb_ec_array.v index eca60ee65..674509e4f 100644 --- a/ivtest/ivltests/nb_ec_array.v +++ b/ivtest/ivltests/nb_ec_array.v @@ -78,6 +78,23 @@ module top; pass = 1'b0; end + // These should execute as if there was no event control + result[0] <= repeat(0) @(posedge clk) 4'h4; + #1 + if ($simtime != 171 || result[0] !== 4'h4) begin + $display("Failed @ at %0t, expected 4'h4, got %h", + $simtime, result[0]); + pass = 1'b0; + end + + result[0] <= repeat(-1) @(posedge clk) 4'h5; + #1 + if ($simtime != 172 || result[0] !== 4'h5) begin + $display("Failed @ at %0t, expected 4'h5, got %h", + $simtime, result[0]); + pass = 1'b0; + end + if (pass) $display("PASSED"); $finish; end diff --git a/ivtest/ivltests/nb_ec_array_pv.v b/ivtest/ivltests/nb_ec_array_pv.v index a23ce06bc..357d96c0f 100644 --- a/ivtest/ivltests/nb_ec_array_pv.v +++ b/ivtest/ivltests/nb_ec_array_pv.v @@ -81,6 +81,16 @@ module top; pass = 1'b0; end + // These should execute as if there was no event control + result[0][3:0] <= repeat(0) @(posedge clk) 4'h3; + result[0][7:4] <= repeat(-1) @(posedge clk) 4'h4; + #1 + if ($simtime != 171 || result[0] !== 8'h43) begin + $display("Failed @ at %0t, expected 8'h43, got %h", + $simtime, result[0]); + pass = 1'b0; + end + if (pass) $display("PASSED"); $finish; end diff --git a/ivtest/ivltests/nb_ec_array_pv2.v b/ivtest/ivltests/nb_ec_array_pv2.v index b8434b5cb..bdb2c930e 100644 --- a/ivtest/ivltests/nb_ec_array_pv2.v +++ b/ivtest/ivltests/nb_ec_array_pv2.v @@ -84,6 +84,16 @@ module top; pass = 1'b0; end + // These should execute as if there was no event control + result[j][i+:4] <= repeat(0) @(posedge clk) 4'h3; + result[j][i+4+:4] <= repeat(-1) @(posedge clk) 4'h4; + #1 + if ($simtime != 171 || result[j] !== 8'h43) begin + $display("Failed @ at %0t, expected 8'h43, got %h", + $simtime, result[j]); + pass = 1'b0; + end + if (pass) $display("PASSED"); $finish; end diff --git a/ivtest/ivltests/nb_ec_pv.v b/ivtest/ivltests/nb_ec_pv.v index 4d65f5fc0..c44cdc3a2 100644 --- a/ivtest/ivltests/nb_ec_pv.v +++ b/ivtest/ivltests/nb_ec_pv.v @@ -78,6 +78,16 @@ module top; pass = 1'b0; end + // These should execute as if there was no event control + result[3:0] <= repeat(0) @(posedge clk) 4'h3; + result[7:4] <= repeat(-1) @(posedge clk) 4'h4; + #1 + if ($simtime != 171 || result !== 8'h43) begin + $display("Failed @ at %0t, expected 8'h43, got %h", + $simtime, result); + pass = 1'b0; + end + if (pass) $display("PASSED"); $finish; end diff --git a/ivtest/ivltests/nb_ec_pv2.v b/ivtest/ivltests/nb_ec_pv2.v index 80260b4a7..112ff0d21 100644 --- a/ivtest/ivltests/nb_ec_pv2.v +++ b/ivtest/ivltests/nb_ec_pv2.v @@ -5,6 +5,7 @@ module top; reg clk = 0; reg [7:0] result; reg [3:0] bit; + integer count; always #10 clk = ~clk; @@ -12,6 +13,7 @@ module top; // Since the bit is not defined this assignment will not happen. // We will check to verify this fact 1 time step after it should // happen (50). + #0; result[bit] <= repeat(3) @(posedge clk) 1'b0; if ($simtime != 0 || result !== 8'bx) begin $display("Failed repeat(3) blocked at %0t, expected 8'hxx, got %h", @@ -34,6 +36,41 @@ module top; pass = 1'b0; end + // These should execute as if there was no event control + count = 0; + result[bit] <= repeat(count) @(posedge clk) 1'b1; + #1 + if ($simtime != 71 || result !== 8'bxxxxxxx1) begin + $display("Failed @ at %0t, expected 8'bxxxxxxx1, got %h", + $simtime, result); + pass = 1'b0; + end + + count = -1; + result[bit+1] <= repeat(count) @(posedge clk) 1'b0; + #1 + if ($simtime != 72 || result !== 8'bxxxxxx01) begin + $display("Failed @ at %0t, expected 8'bxxxxxx01, got %h", + $simtime, result); + pass = 1'b0; + end + + result[bit+2] <= repeat(0) @(posedge clk) 1'b1; + #1 + if ($simtime != 73 || result !== 8'bxxxxx101) begin + $display("Failed @ at %0t, expected 8'bxxxxx101, got %h", + $simtime, result); + pass = 1'b0; + end + + result[bit+3] <= repeat(-1) @(posedge clk) 1'b0; + #1 + if ($simtime != 74 || result !== 8'bxxxx0101) begin + $display("Failed @ at %0t, expected 8'bxxxx0101, got %h", + $simtime, result); + pass = 1'b0; + end + if (pass) $display("PASSED"); $finish; end diff --git a/ivtest/ivltests/nb_ec_real.v b/ivtest/ivltests/nb_ec_real.v index 2ceba1a21..3334d247d 100644 --- a/ivtest/ivltests/nb_ec_real.v +++ b/ivtest/ivltests/nb_ec_real.v @@ -78,6 +78,23 @@ module top; pass = 1'b0; end + // These should execute as if there was no event control + result <= repeat(0) @(posedge clk) 4.0; + #1 + if ($simtime != 171 || result != 4.0) begin + $display("Failed @ at %0t, expected 4.0, got %f", + $simtime, result); + pass = 1'b0; + end + + result <= repeat(-1) @(posedge clk) 5.0; + #1 + if ($simtime != 172 || result != 5.0) begin + $display("Failed @ at %0t, expected 5.0, got %f", + $simtime, result); + pass = 1'b0; + end + if (pass) $display("PASSED"); $finish; end diff --git a/ivtest/ivltests/nb_ec_vector.v b/ivtest/ivltests/nb_ec_vector.v index 0c6238a37..5c3dd8b26 100644 --- a/ivtest/ivltests/nb_ec_vector.v +++ b/ivtest/ivltests/nb_ec_vector.v @@ -78,6 +78,23 @@ module top; pass = 1'b0; end + // These should execute as if there was no event control + result <= repeat(0) @(posedge clk) 4'h4; + #1 + if ($simtime != 171 || result !== 4'h4) begin + $display("Failed @ at %0t, expected 4'h4, got %h", + $simtime, result); + pass = 1'b0; + end + + result <= repeat(-1) @(posedge clk) 4'h5; + #1 + if ($simtime != 172 || result !== 4'h5) begin + $display("Failed @ at %0t, expected 4'h5, got %h", + $simtime, result); + pass = 1'b0; + end + if (pass) $display("PASSED"); $finish; end diff --git a/ivtest/ivltests/sv_ap_uarray_single1.v b/ivtest/ivltests/sv_ap_uarray_single1.v new file mode 100644 index 000000000..437345724 --- /dev/null +++ b/ivtest/ivltests/sv_ap_uarray_single1.v @@ -0,0 +1,27 @@ +// Check that procedural assignment of unpacked array assignment patterns to +// single element arrays is supported. + +module test; + + reg failed; + integer a[0:0]; + + `define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, \ + `"val`", exp, val); \ + failed = 1'b1; \ + end + + initial begin + failed = 1'b0; + a = '{42}; + + `check(a[0], 42); + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_ap_uarray_single2.v b/ivtest/ivltests/sv_ap_uarray_single2.v new file mode 100644 index 000000000..42a722f01 --- /dev/null +++ b/ivtest/ivltests/sv_ap_uarray_single2.v @@ -0,0 +1,28 @@ +// Check that continuous assignment of unpacked array assignment patterns to +// single element arrays is supported. + +module test; + + reg failed; + integer a[0:0]; + + assign a = '{42}; + + `define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, \ + `"val`", exp, val); \ + failed = 1'b1; \ + end + + initial begin + failed = 1'b0; + #1; + `check(a[0], 42); + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_array_assign_single_fail1.v b/ivtest/ivltests/sv_array_assign_single_fail1.v new file mode 100644 index 000000000..e4f297663 --- /dev/null +++ b/ivtest/ivltests/sv_array_assign_single_fail1.v @@ -0,0 +1,13 @@ +// Check that scalar expressions can not be procedurally assigned to single +// element unpacked arrays. + +module test; + + integer a[0:0]; + + initial begin + a = 1; + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_array_cassign10.v b/ivtest/ivltests/sv_array_cassign10.v new file mode 100644 index 000000000..5a5fa6856 --- /dev/null +++ b/ivtest/ivltests/sv_array_cassign10.v @@ -0,0 +1,39 @@ +// Check that continuous assignments to unpacked arrays preserve drive strength. + +module test; + + reg failed; + reg [8*3-1:0] s; + + wire driven[0:1]; + wire resolved[0:1]; + + assign (weak1, weak0) driven = '{1'b1, 1'b0}; + assign resolved[0] = 1'b0; + assign resolved[1] = 1'b1; + assign (weak1, weak0) resolved = '{1'b1, 1'b0}; + + `define check_str(val, exp) begin \ + $swrite(s, "%v", val); \ + if (s != exp) begin \ + $display("FAILED(%0d). '%s' expected %s, got %s", `__LINE__, \ + `"val`", exp, s); \ + failed = 1'b1; \ + end \ + end + + initial begin + failed = 1'b0; + + #0; + `check_str(driven[0], "We1"); + `check_str(driven[1], "We0"); + `check_str(resolved[0], "St0"); + `check_str(resolved[1], "St1"); + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_array_cassign9.v b/ivtest/ivltests/sv_array_cassign9.v new file mode 100644 index 000000000..4db9f0d05 --- /dev/null +++ b/ivtest/ivltests/sv_array_cassign9.v @@ -0,0 +1,44 @@ +// Check that continuous assignments to unpacked arrays preserve delay. + +module test; + + reg failed; + + wire delayed[0:1]; + reg value[0:1]; + + assign #5 delayed = value; + + `define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %b, got %b", `__LINE__, \ + `"val`", exp, val); \ + failed = 1'b1; \ + end + + initial begin + failed = 1'b0; + value[0] = 1'b1; + value[1] = 1'b0; + + #5; + `check(delayed[0], 1'b1) + `check(delayed[1], 1'b0) + + value[0] = 1'b0; + value[1] = 1'b1; + + #4; + `check(delayed[0], 1'b1) + `check(delayed[1], 1'b0) + + #1; + `check(delayed[0], 1'b0) + `check(delayed[1], 1'b1) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_array_cassign_single.v b/ivtest/ivltests/sv_array_cassign_single.v new file mode 100644 index 000000000..1a54abf1a --- /dev/null +++ b/ivtest/ivltests/sv_array_cassign_single.v @@ -0,0 +1,30 @@ +// Check that continuous array assignment to single element unpacked arrays is +// supported. + +module test; + + reg failed; + wire [31:0] a[0:0]; + reg [31:0] b[0:0]; + + assign a = b; + + `define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, \ + `"val`", exp, val); \ + failed = 1'b1; \ + end + + initial begin + failed = 1'b0; + b[0] = 32'd42; + #1; + `check(a[0], 32'd42); + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_array_cassign_single_fail1.v b/ivtest/ivltests/sv_array_cassign_single_fail1.v new file mode 100644 index 000000000..2ce3f7fda --- /dev/null +++ b/ivtest/ivltests/sv_array_cassign_single_fail1.v @@ -0,0 +1,10 @@ +// Check that scalar expressions can not be continuously assigned to single +// element unpacked arrays. + +module test; + + wire [31:0] a[0:0]; + + assign a = 1; + +endmodule diff --git a/ivtest/ivltests/sv_byte_array_string1.v b/ivtest/ivltests/sv_byte_array_string1.v new file mode 100644 index 000000000..bb0e621eb --- /dev/null +++ b/ivtest/ivltests/sv_byte_array_string1.v @@ -0,0 +1,45 @@ +// Check that string literals can be assigned to one-dimensional byte arrays. + +module test; + + bit failed = 1'b0; + + `define check(val, exp) do \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %02h, got %02h", `__LINE__, \ + `"val`", exp, val); \ + failed = 1'b1; \ + end \ + while(0) + + byte desc [3:0] = "AB\n"; + byte asc [0:3]; + byte unsized [4]; + + assign asc = "AB\n"; + + initial begin + #1; + + `check(desc[3], 8'h41); + `check(desc[2], 8'h42); + `check(desc[1], 8'h0a); + `check(desc[0], 8'h00); + + `check(asc[0], 8'h41); + `check(asc[1], 8'h42); + `check(asc[2], 8'h0a); + `check(asc[3], 8'h00); + + unsized = "AB\n"; + `check(unsized[0], 8'h41); + `check(unsized[1], 8'h42); + `check(unsized[2], 8'h0a); + `check(unsized[3], 8'h00); + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_byte_array_string2.v b/ivtest/ivltests/sv_byte_array_string2.v new file mode 100644 index 000000000..001a38830 --- /dev/null +++ b/ivtest/ivltests/sv_byte_array_string2.v @@ -0,0 +1,61 @@ +// Check that string literals can be assigned to nested byte arrays using +// assignment patterns. + +module test; + + bit failed = 1'b0; + + `define check(val, exp) do \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %02h, got %02h", `__LINE__, \ + `"val`", exp, val); \ + failed = 1'b1; \ + end \ + while(0) + + byte desc [0:1][3:0] = '{"AB\n", "CD\t"}; + byte asc [1:0][0:3]; + byte unsized [2][4]; + + assign asc = '{"AB\n", "CD\t"}; + + initial begin + #1; + + `check(desc[0][3], 8'h41); + `check(desc[0][2], 8'h42); + `check(desc[0][1], 8'h0a); + `check(desc[0][0], 8'h00); + + `check(desc[1][3], 8'h43); + `check(desc[1][2], 8'h44); + `check(desc[1][1], 8'h09); + `check(desc[1][0], 8'h00); + + `check(asc[0][0], 8'h43); + `check(asc[0][1], 8'h44); + `check(asc[0][2], 8'h09); + `check(asc[0][3], 8'h00); + + `check(asc[1][0], 8'h41); + `check(asc[1][1], 8'h42); + `check(asc[1][2], 8'h0a); + `check(asc[1][3], 8'h00); + + unsized = '{"AB\n", "CD\t"}; + `check(unsized[0][0], 8'h41); + `check(unsized[0][1], 8'h42); + `check(unsized[0][2], 8'h0a); + `check(unsized[0][3], 8'h00); + + `check(unsized[1][0], 8'h43); + `check(unsized[1][1], 8'h44); + `check(unsized[1][2], 8'h09); + `check(unsized[1][3], 8'h00); + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_byte_array_string3.v b/ivtest/ivltests/sv_byte_array_string3.v new file mode 100644 index 000000000..27ba42748 --- /dev/null +++ b/ivtest/ivltests/sv_byte_array_string3.v @@ -0,0 +1,46 @@ +// Check that string literals shorter than the target byte array are padded +// with null bytes. + +module test; + + bit failed = 1'b0; + + `define check(val, exp) do \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %02h, got %02h", `__LINE__, \ + `"val`", exp, val); \ + failed = 1'b1; \ + end \ + while(0) + + byte desc [3:0] = "AB"; + byte asc [0:3]; + byte unsized [4]; + + assign asc = "AB"; + + initial begin + #1; + + `check(desc[3], 8'h41); + `check(desc[2], 8'h42); + `check(desc[1], 8'h00); + `check(desc[0], 8'h00); + + `check(asc[0], 8'h41); + `check(asc[1], 8'h42); + `check(asc[2], 8'h00); + `check(asc[3], 8'h00); + + unsized = "AB"; + `check(unsized[0], 8'h41); + `check(unsized[1], 8'h42); + `check(unsized[2], 8'h00); + `check(unsized[3], 8'h00); + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_byte_array_string4.v b/ivtest/ivltests/sv_byte_array_string4.v new file mode 100644 index 000000000..0797f2fd3 --- /dev/null +++ b/ivtest/ivltests/sv_byte_array_string4.v @@ -0,0 +1,39 @@ +// Check that string literals longer than the target byte array are truncated. + +module test; + + bit failed = 1'b0; + + `define check(val, exp) do \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %02h, got %02h", `__LINE__, \ + `"val`", exp, val); \ + failed = 1'b1; \ + end \ + while(0) + + byte desc [1:0] = "ABC"; + byte asc [0:1]; + byte unsized [2]; + + assign asc = "ABC"; + + initial begin + #1; + + `check(desc[1], 8'h41); + `check(desc[0], 8'h42); + + `check(asc[0], 8'h41); + `check(asc[1], 8'h42); + + unsized = "ABCD"; + `check(unsized[0], 8'h41); + `check(unsized[1], 8'h42); + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_byte_array_string_fail1.v b/ivtest/ivltests/sv_byte_array_string_fail1.v new file mode 100644 index 000000000..6f53c54ed --- /dev/null +++ b/ivtest/ivltests/sv_byte_array_string_fail1.v @@ -0,0 +1,8 @@ +// Check that string literals cannot be assigned to unpacked arrays whose +// element type is 4-state. + +module test; + + logic [7:0] value [0:3] = "AB"; // Error: target element type is 4-state + +endmodule diff --git a/ivtest/ivltests/sv_byte_array_string_fail2.v b/ivtest/ivltests/sv_byte_array_string_fail2.v new file mode 100644 index 000000000..16a04116e --- /dev/null +++ b/ivtest/ivltests/sv_byte_array_string_fail2.v @@ -0,0 +1,8 @@ +// Check that string literals cannot be assigned directly to multi-dimensional +// byte arrays. + +module test; + + byte value [0:1][0:3] = "AB"; // Error: string is not nested + +endmodule diff --git a/ivtest/ivltests/sv_byte_array_string_fail3.v b/ivtest/ivltests/sv_byte_array_string_fail3.v new file mode 100644 index 000000000..990fcca7f --- /dev/null +++ b/ivtest/ivltests/sv_byte_array_string_fail3.v @@ -0,0 +1,17 @@ +// Check that string literals cannot be connected to output byte array ports. + +module M ( + output byte out [0:1] +); + + initial begin + out = "CD"; + end + +endmodule + +module test; + + M i_m("AB"); // Error: output expression is not assignable + +endmodule diff --git a/ivtest/ivltests/sv_byte_array_string_fail4.v b/ivtest/ivltests/sv_byte_array_string_fail4.v new file mode 100644 index 000000000..886a0761b --- /dev/null +++ b/ivtest/ivltests/sv_byte_array_string_fail4.v @@ -0,0 +1,8 @@ +// Check that string literals cannot be assigned to unpacked arrays whose +// element type is narrower than 8 bits. + +module test; + + bit [6:0] value [0:3] = "AB"; // Error: target element type is too narrow + +endmodule diff --git a/ivtest/ivltests/sv_byte_array_string_fail5.v b/ivtest/ivltests/sv_byte_array_string_fail5.v new file mode 100644 index 000000000..86ddac25b --- /dev/null +++ b/ivtest/ivltests/sv_byte_array_string_fail5.v @@ -0,0 +1,8 @@ +// Check that string literals cannot be assigned to unpacked arrays whose +// element type is wider than 8 bits. + +module test; + + bit [8:0] value [0:3] = "AB"; // Error: target element type is too wide + +endmodule diff --git a/ivtest/ivltests/sv_interface_port_array_basic.v b/ivtest/ivltests/sv_interface_port_array_basic.v new file mode 100644 index 000000000..6915b8c14 --- /dev/null +++ b/ivtest/ivltests/sv_interface_port_array_basic.v @@ -0,0 +1,46 @@ +// This tests a one-dimensional interface formal array connected to a +// whole interface instance array, then indexed inside the receiving +// module. + +interface bus_if (); + logic [7:0] value; + modport producer(output value); + modport consumer(input value); +endinterface + +module drive(input [7:0] val, bus_if.producer bus); + assign bus.value = val; +endmodule + +module sample(output [7:0] y, bus_if.consumer bus); + assign y = bus.value; +endmodule + +module child_array(output [7:0] y0, output [7:0] y1, + bus_if.consumer bus[2]); + sample c0(.y(y0), .bus(bus[0])); + sample c1(.y(y1), .bus(bus[1])); +endmodule + +module test; + bus_if buses[2](); + wire [7:0] y0; + wire [7:0] y1; + + drive d0(8'd21, buses[0]); + drive d1(8'd42, buses[1]); + child_array dut(.bus(buses), .y0(y0), .y1(y1)); + + initial begin + #1; + if (y0 !== 8'd21) begin + $display("FAILED: y0=%0d", y0); + $finish; + end + if (y1 !== 8'd42) begin + $display("FAILED: y1=%0d", y1); + $finish; + end + $display("PASSED"); + end +endmodule diff --git a/ivtest/ivltests/sv_interface_port_array_modport_restrict_fail.v b/ivtest/ivltests/sv_interface_port_array_modport_restrict_fail.v new file mode 100644 index 000000000..5a5e96fc9 --- /dev/null +++ b/ivtest/ivltests/sv_interface_port_array_modport_restrict_fail.v @@ -0,0 +1,16 @@ +// This tests that modport restrictions apply through indexed interface +// formal array elements. + +interface bus_if (); + logic value; + modport consumer(input value); +endinterface + +module bad(bus_if.consumer bus[1]); + assign bus[0].value = 1'b1; +endmodule + +module test; + bus_if buses[1](); + bad dut(.bus(buses)); +endmodule diff --git a/ivtest/ivltests/sv_interface_port_array_size_mismatch_fail.v b/ivtest/ivltests/sv_interface_port_array_size_mismatch_fail.v new file mode 100644 index 000000000..af2338918 --- /dev/null +++ b/ivtest/ivltests/sv_interface_port_array_size_mismatch_fail.v @@ -0,0 +1,13 @@ +// This tests rejection of a whole interface array actual whose size +// does not match the formal interface array size. + +interface bus_if (); +endinterface + +module child(bus_if bus[2]); +endmodule + +module test; + bus_if buses[1](); + child dut(.bus(buses)); +endmodule diff --git a/ivtest/ivltests/sv_interface_port_basic.v b/ivtest/ivltests/sv_interface_port_basic.v new file mode 100644 index 000000000..a9054a523 --- /dev/null +++ b/ivtest/ivltests/sv_interface_port_basic.v @@ -0,0 +1,47 @@ +// This tests a SystemVerilog interface-typed module port with an +// explicit modport and a named actual interface instance connection. +// +// This file is placed into the Public Domain, for any use, without +// warranty. + +module test; + logic [7:0] lhs; + logic [7:0] rhs; + + bus_if bus(); + + add_if dut(.bus(bus)); + + assign bus.lhs = lhs; + assign bus.rhs = rhs; + + initial begin + lhs = 8'd5; + rhs = 8'd7; + #1; + if (bus.sum !== 9'd12) begin + $display("FAILED"); + $finish; + end + $display("PASSED"); + end +endmodule + +interface bus_if #(parameter WIDTH = 8) (); + logic [WIDTH-1:0] lhs; + logic [WIDTH-1:0] rhs; + logic [WIDTH:0] sum; + + modport consumer( + input lhs, + input rhs, + output sum + ); + +endinterface + +module add_if #(parameter WIDTH = 8) ( + bus_if.consumer bus +); + assign bus.sum = bus.lhs + bus.rhs; +endmodule diff --git a/ivtest/ivltests/sv_interface_port_forwarding.v b/ivtest/ivltests/sv_interface_port_forwarding.v new file mode 100644 index 000000000..9fb52a87b --- /dev/null +++ b/ivtest/ivltests/sv_interface_port_forwarding.v @@ -0,0 +1,41 @@ +// This tests forwarding an interface-typed formal port to a child +// module while preserving the parent-facing modport view. +// +// This file is placed into the Public Domain, for any use, without +// warranty. + +module test; + bus_if bus(); + + assign bus.value = 1'b1; + parent dut(.bus(bus)); + + initial begin + #1; + if (bus.mirror !== 1'b1) begin + $display("FAILED"); + $finish; + end + $display("PASSED"); + end +endmodule + +module parent( + bus_if.consumer bus +); + child u_child(.bus(bus)); +endmodule + +module child( + bus_if bus +); + assign bus.mirror = bus.value; +endmodule + +interface bus_if (); + logic value; + logic mirror; + logic hidden; + + modport consumer(input value, output mirror); +endinterface diff --git a/ivtest/ivltests/sv_interface_port_forwarding_restrict_fail.v b/ivtest/ivltests/sv_interface_port_forwarding_restrict_fail.v new file mode 100644 index 000000000..79a1ced9f --- /dev/null +++ b/ivtest/ivltests/sv_interface_port_forwarding_restrict_fail.v @@ -0,0 +1,31 @@ +// This tests that forwarding an interface formal cannot widen access +// beyond the parent-facing modport restriction. +// +// This file is placed into the Public Domain, for any use, without +// warranty. + +module test; + bus_if bus(); + parent dut(.bus(bus)); +endmodule + +module parent( + bus_if.consumer bus +); + child u_child(.bus(bus)); +endmodule + +module child( + bus_if bus +); + logic sample; + + assign sample = bus.hidden; +endmodule + +interface bus_if (); + logic value; + logic hidden; + + modport consumer(input value); +endinterface diff --git a/ivtest/ivltests/sv_interface_port_indexed_actual.v b/ivtest/ivltests/sv_interface_port_indexed_actual.v new file mode 100644 index 000000000..979ef7fbb --- /dev/null +++ b/ivtest/ivltests/sv_interface_port_indexed_actual.v @@ -0,0 +1,33 @@ +// This tests connecting a scalar interface-typed formal to one element +// of an interface instance array. + +interface bus_if (); + logic [7:0] value; + modport producer(output value); + modport consumer(input value); +endinterface + +module drive(input [7:0] val, bus_if.producer bus); + assign bus.value = val; +endmodule + +module sample(output [7:0] y, bus_if.consumer bus); + assign y = bus.value; +endmodule + +module test; + bus_if buses[2](); + wire [7:0] y; + + drive d0(8'd37, buses[0]); + sample s0(.bus(buses[0]), .y(y)); + + initial begin + #1; + if (y !== 8'd37) begin + $display("FAILED: y=%0d", y); + $finish; + end + $display("PASSED"); + end +endmodule diff --git a/ivtest/ivltests/sv_interface_port_indexed_actual_generate.v b/ivtest/ivltests/sv_interface_port_indexed_actual_generate.v new file mode 100644 index 000000000..2ec7690b5 --- /dev/null +++ b/ivtest/ivltests/sv_interface_port_indexed_actual_generate.v @@ -0,0 +1,43 @@ +// This tests connecting scalar interface-typed formals to interface +// array elements selected by generated constant indices. + +interface bus_if (); + logic [7:0] value; + modport producer(output value); + modport consumer(input value); +endinterface + +module drive(input [7:0] val, bus_if.producer bus); + assign bus.value = val; +endmodule + +module sample(output [7:0] y, bus_if.consumer bus); + assign y = bus.value; +endmodule + +module test; + bus_if buses[2](); + wire [7:0] y[2]; + + genvar i; + generate + for (i = 0; i < 2; i = i + 1) begin : gen + localparam [7:0] VAL = 8'd11 + i; + drive d(VAL, buses[i]); + sample s(.y(y[i]), .bus(buses[i])); + end + endgenerate + + initial begin + #1; + if (y[0] !== 8'd11) begin + $display("FAILED: y[0]=%0d", y[0]); + $finish; + end + if (y[1] !== 8'd12) begin + $display("FAILED: y[1]=%0d", y[1]); + $finish; + end + $display("PASSED"); + end +endmodule diff --git a/ivtest/ivltests/sv_interface_port_missing_modport_fail.v b/ivtest/ivltests/sv_interface_port_missing_modport_fail.v new file mode 100644 index 000000000..b1fa58f7b --- /dev/null +++ b/ivtest/ivltests/sv_interface_port_missing_modport_fail.v @@ -0,0 +1,22 @@ +// This tests the diagnostic path for an interface-typed module port +// that names a modport missing from the interface definition. +// +// This file is placed into the Public Domain, for any use, without +// warranty. + +module test; + bus_if bus(); + bus_user dut(.bus(bus)); +endmodule + +interface bus_if (); + logic value; + + modport producer(output value); +endinterface + +module bus_user( + bus_if.consumer bus +); + initial $display("FAILED"); +endmodule diff --git a/ivtest/ivltests/sv_interface_port_missing_type_fail.v b/ivtest/ivltests/sv_interface_port_missing_type_fail.v new file mode 100644 index 000000000..df1a5a513 --- /dev/null +++ b/ivtest/ivltests/sv_interface_port_missing_type_fail.v @@ -0,0 +1,11 @@ +// This tests the diagnostic path for an interface-typed module port +// whose interface type name is not declared. +// +// This file is placed into the Public Domain, for any use, without +// warranty. + +module bus_user( + missing_if.consumer bus +); + initial $display("FAILED"); +endmodule diff --git a/ivtest/ivltests/sv_interface_port_modport_input_write_fail.v b/ivtest/ivltests/sv_interface_port_modport_input_write_fail.v new file mode 100644 index 000000000..d08f9016d --- /dev/null +++ b/ivtest/ivltests/sv_interface_port_modport_input_write_fail.v @@ -0,0 +1,22 @@ +// This tests rejection of an assignment through a member declared input +// by the selected interface modport. +// +// This file is placed into the Public Domain, for any use, without +// warranty. + +module test; + bus_if bus(); + bus_user dut(.bus(bus)); +endmodule + +interface bus_if (); + logic value; + + modport consumer(input value); +endinterface + +module bus_user( + bus_if.consumer bus +); + assign bus.value = 1'b1; +endmodule diff --git a/ivtest/ivltests/sv_interface_port_non_interface_actual_fail.v b/ivtest/ivltests/sv_interface_port_non_interface_actual_fail.v new file mode 100644 index 000000000..018f14543 --- /dev/null +++ b/ivtest/ivltests/sv_interface_port_non_interface_actual_fail.v @@ -0,0 +1,22 @@ +// This tests rejection of a non-interface actual connected to an +// interface-typed module port. +// +// This file is placed into the Public Domain, for any use, without +// warranty. + +module test; + logic value; + bus_user dut(.bus(value)); +endmodule + +interface bus_if (); + logic value; + + modport consumer(input value); +endinterface + +module bus_user( + bus_if.consumer bus +); + initial $display("FAILED"); +endmodule diff --git a/ivtest/ivltests/sv_interface_port_plain_ansi_regression.v b/ivtest/ivltests/sv_interface_port_plain_ansi_regression.v new file mode 100644 index 000000000..30ab169a2 --- /dev/null +++ b/ivtest/ivltests/sv_interface_port_plain_ansi_regression.v @@ -0,0 +1,29 @@ +// This protects ordinary partial ANSI port parsing near interface +// formal grammar. +// +// This file is placed into the Public Domain, for any use, without +// warranty. + +module test; + logic [3:0] value; + logic [3:0] result; + + plain dut(value, result); + + initial begin + value = 4'ha; + #1; + if (result !== 4'ha) begin + $display("FAILED"); + $finish; + end + $display("PASSED"); + end +endmodule + +module plain( + input logic [3:0] value, + output logic [3:0] result +); + assign result = value; +endmodule diff --git a/ivtest/ivltests/sv_interface_port_positional.v b/ivtest/ivltests/sv_interface_port_positional.v new file mode 100644 index 000000000..d0cb7d057 --- /dev/null +++ b/ivtest/ivltests/sv_interface_port_positional.v @@ -0,0 +1,33 @@ +// This tests positional binding of an interface-typed module port. +// +// This file is placed into the Public Domain, for any use, without +// warranty. + +module test; + bus_if bus(); + + assign bus.value = 1'b1; + bus_user dut(bus); + + initial begin + #1; + if (bus.sample !== 1'b1) begin + $display("FAILED"); + $finish; + end + $display("PASSED"); + end +endmodule + +module bus_user( + bus_if.consumer bus +); + assign bus.sample = bus.value; +endmodule + +interface bus_if (); + logic value; + logic sample; + + modport consumer(input value, output sample); +endinterface diff --git a/ivtest/ivltests/sv_interface_port_positional_unconnected_fail.v b/ivtest/ivltests/sv_interface_port_positional_unconnected_fail.v new file mode 100644 index 000000000..5b9627b52 --- /dev/null +++ b/ivtest/ivltests/sv_interface_port_positional_unconnected_fail.v @@ -0,0 +1,19 @@ +// This tests rejection of an unconnected positional interface port. +// +// This file is placed into the Public Domain, for any use, without +// warranty. + +module test; + bus_user dut(); +endmodule + +module bus_user( + bus_if.consumer bus +); +endmodule + +interface bus_if (); + logic value; + + modport consumer(input value); +endinterface diff --git a/ivtest/ivltests/sv_interface_port_typedef_ansi_regression.v b/ivtest/ivltests/sv_interface_port_typedef_ansi_regression.v new file mode 100644 index 000000000..0fc169015 --- /dev/null +++ b/ivtest/ivltests/sv_interface_port_typedef_ansi_regression.v @@ -0,0 +1,31 @@ +// This protects typedef-based ANSI ports from being interpreted as +// interface-typed formals. +// +// This file is placed into the Public Domain, for any use, without +// warranty. + +typedef logic [3:0] nibble_t; + +module test; + nibble_t value; + nibble_t result; + + typed dut(value, result); + + initial begin + value = 4'h6; + #1; + if (result !== 4'h6) begin + $display("FAILED"); + $finish; + end + $display("PASSED"); + end +endmodule + +module typed( + input nibble_t value, + output nibble_t result +); + assign result = value; +endmodule diff --git a/ivtest/ivltests/sv_interface_port_unlisted_member_fail.v b/ivtest/ivltests/sv_interface_port_unlisted_member_fail.v new file mode 100644 index 000000000..3457e330c --- /dev/null +++ b/ivtest/ivltests/sv_interface_port_unlisted_member_fail.v @@ -0,0 +1,25 @@ +// This tests rejection of access to an interface member that is not +// listed in the selected modport. +// +// This file is placed into the Public Domain, for any use, without +// warranty. + +module test; + bus_if bus(); + bus_user dut(.bus(bus)); +endmodule + +interface bus_if (); + logic visible; + logic hidden; + + modport consumer(input visible); +endinterface + +module bus_user( + bus_if.consumer bus +); + logic sample; + + assign sample = bus.hidden; +endmodule diff --git a/ivtest/ivltests/sv_interface_port_unmodported_basic.v b/ivtest/ivltests/sv_interface_port_unmodported_basic.v new file mode 100644 index 000000000..c8bad7778 --- /dev/null +++ b/ivtest/ivltests/sv_interface_port_unmodported_basic.v @@ -0,0 +1,40 @@ +// This tests a concrete interface-typed module port without an explicit +// modport restriction. +// +// This file is placed into the Public Domain, for any use, without +// warranty. + +module test; + logic [7:0] lhs; + logic [7:0] rhs; + + bus_if bus(); + + add_if dut(.bus(bus)); + + assign bus.lhs = lhs; + assign bus.rhs = rhs; + + initial begin + lhs = 8'd9; + rhs = 8'd4; + #1; + if (bus.sum !== 9'd13) begin + $display("FAILED"); + $finish; + end + $display("PASSED"); + end +endmodule + +module add_if( + bus_if bus +); + assign bus.sum = bus.lhs + bus.rhs; +endmodule + +interface bus_if (); + logic [7:0] lhs; + logic [7:0] rhs; + logic [8:0] sum; +endinterface diff --git a/ivtest/ivltests/sv_interface_port_unmodported_missing_type_fail.v b/ivtest/ivltests/sv_interface_port_unmodported_missing_type_fail.v new file mode 100644 index 000000000..b02bb3985 --- /dev/null +++ b/ivtest/ivltests/sv_interface_port_unmodported_missing_type_fail.v @@ -0,0 +1,11 @@ +// This tests the diagnostic path for an unmodported interface-typed +// module port whose interface type name is not declared. +// +// This file is placed into the Public Domain, for any use, without +// warranty. + +module bus_user( + missing_if bus +); + initial $display("FAILED"); +endmodule diff --git a/ivtest/ivltests/sv_interface_port_wildcard.v b/ivtest/ivltests/sv_interface_port_wildcard.v new file mode 100644 index 000000000..e13630fb6 --- /dev/null +++ b/ivtest/ivltests/sv_interface_port_wildcard.v @@ -0,0 +1,33 @@ +// This tests wildcard binding of an interface-typed module port. +// +// This file is placed into the Public Domain, for any use, without +// warranty. + +module test; + bus_if bus(); + + assign bus.value = 1'b1; + bus_user dut(.*); + + initial begin + #1; + if (bus.sample !== 1'b1) begin + $display("FAILED"); + $finish; + end + $display("PASSED"); + end +endmodule + +module bus_user( + bus_if.consumer bus +); + assign bus.sample = bus.value; +endmodule + +interface bus_if (); + logic value; + logic sample; + + modport consumer(input value, output sample); +endinterface diff --git a/ivtest/ivltests/sv_interface_port_wrong_type_fail.v b/ivtest/ivltests/sv_interface_port_wrong_type_fail.v new file mode 100644 index 000000000..33dfc40b1 --- /dev/null +++ b/ivtest/ivltests/sv_interface_port_wrong_type_fail.v @@ -0,0 +1,28 @@ +// This tests rejection of an actual interface instance whose type does +// not match the interface type of the formal module port. +// +// This file is placed into the Public Domain, for any use, without +// warranty. + +module test; + other_if bus(); + bus_user dut(.bus(bus)); +endmodule + +interface bus_if (); + logic value; + + modport consumer(input value); +endinterface + +interface other_if (); + logic value; + + modport consumer(input value); +endinterface + +module bus_user( + bus_if.consumer bus +); + initial $display("FAILED"); +endmodule diff --git a/ivtest/ivltests/sv_lval_concat_class_fail1.v b/ivtest/ivltests/sv_lval_concat_class_fail1.v new file mode 100644 index 000000000..09a0150ae --- /dev/null +++ b/ivtest/ivltests/sv_lval_concat_class_fail1.v @@ -0,0 +1,15 @@ +// Check that class objects can not be used in l-value concatenations. + +module test; + + class C; + endclass + + int x; + C c; + + initial begin + {x, c} = x; + end + +endmodule diff --git a/ivtest/ivltests/sv_lval_concat_class_fail2.v b/ivtest/ivltests/sv_lval_concat_class_fail2.v new file mode 100644 index 000000000..061c33898 --- /dev/null +++ b/ivtest/ivltests/sv_lval_concat_class_fail2.v @@ -0,0 +1,15 @@ +// Check that class objects can not be used in single operand l-value concatenations. + +module test; + + class C; + endclass + + int x; + C c; + + initial begin + {c} = x; + end + +endmodule diff --git a/ivtest/ivltests/sv_lval_concat_class_fail3.v b/ivtest/ivltests/sv_lval_concat_class_fail3.v new file mode 100644 index 000000000..22e6ebcb0 --- /dev/null +++ b/ivtest/ivltests/sv_lval_concat_class_fail3.v @@ -0,0 +1,14 @@ +// Check that class objects can not be used in continuous assignment l-value concatenations. + +module test; + + class C; + endclass + + int x; + C c; + int y; + + assign {x, c} = y; + +endmodule diff --git a/ivtest/ivltests/sv_lval_concat_class_fail4.v b/ivtest/ivltests/sv_lval_concat_class_fail4.v new file mode 100644 index 000000000..958c3d38d --- /dev/null +++ b/ivtest/ivltests/sv_lval_concat_class_fail4.v @@ -0,0 +1,13 @@ +// Check that class objects can not be used in single operand continuous assignment l-value concatenations. + +module test; + + class C; + endclass + + C c; + int y; + + assign {c} = y; + +endmodule diff --git a/ivtest/ivltests/sv_lval_concat_darray_fail1.v b/ivtest/ivltests/sv_lval_concat_darray_fail1.v new file mode 100644 index 000000000..66c4b93df --- /dev/null +++ b/ivtest/ivltests/sv_lval_concat_darray_fail1.v @@ -0,0 +1,12 @@ +// Check that dynamic arrays can not be used in l-value concatenations. + +module test; + + int x; + int d[]; + + initial begin + {x, d} = x; + end + +endmodule diff --git a/ivtest/ivltests/sv_lval_concat_darray_fail2.v b/ivtest/ivltests/sv_lval_concat_darray_fail2.v new file mode 100644 index 000000000..e0cec7842 --- /dev/null +++ b/ivtest/ivltests/sv_lval_concat_darray_fail2.v @@ -0,0 +1,12 @@ +// Check that dynamic arrays can not be used in single operand l-value concatenations. + +module test; + + int x; + int d[]; + + initial begin + {d} = x; + end + +endmodule diff --git a/ivtest/ivltests/sv_lval_concat_darray_fail3.v b/ivtest/ivltests/sv_lval_concat_darray_fail3.v new file mode 100644 index 000000000..0617fc040 --- /dev/null +++ b/ivtest/ivltests/sv_lval_concat_darray_fail3.v @@ -0,0 +1,11 @@ +// Check that dynamic arrays can not be used in continuous assignment l-value concatenations. + +module test; + + int x; + int d[]; + int y; + + assign {x, d} = y; + +endmodule diff --git a/ivtest/ivltests/sv_lval_concat_darray_fail4.v b/ivtest/ivltests/sv_lval_concat_darray_fail4.v new file mode 100644 index 000000000..c9848b0b9 --- /dev/null +++ b/ivtest/ivltests/sv_lval_concat_darray_fail4.v @@ -0,0 +1,10 @@ +// Check that dynamic arrays can not be used in single operand continuous assignment l-value concatenations. + +module test; + + int d[]; + int y; + + assign {d} = y; + +endmodule diff --git a/ivtest/ivltests/sv_lval_concat_queue_fail1.v b/ivtest/ivltests/sv_lval_concat_queue_fail1.v new file mode 100644 index 000000000..5fd60aaa2 --- /dev/null +++ b/ivtest/ivltests/sv_lval_concat_queue_fail1.v @@ -0,0 +1,12 @@ +// Check that queues can not be used in l-value concatenations. + +module test; + + int x; + int q[$]; + + initial begin + {x, q} = x; + end + +endmodule diff --git a/ivtest/ivltests/sv_lval_concat_queue_fail2.v b/ivtest/ivltests/sv_lval_concat_queue_fail2.v new file mode 100644 index 000000000..11f1474b9 --- /dev/null +++ b/ivtest/ivltests/sv_lval_concat_queue_fail2.v @@ -0,0 +1,12 @@ +// Check that queues can not be used in single operand l-value concatenations. + +module test; + + int x; + int q[$]; + + initial begin + {q} = x; + end + +endmodule diff --git a/ivtest/ivltests/sv_lval_concat_queue_fail3.v b/ivtest/ivltests/sv_lval_concat_queue_fail3.v new file mode 100644 index 000000000..cd80fa3a3 --- /dev/null +++ b/ivtest/ivltests/sv_lval_concat_queue_fail3.v @@ -0,0 +1,11 @@ +// Check that queues can not be used in continuous assignment l-value concatenations. + +module test; + + int x; + int q[$]; + int y; + + assign {x, q} = y; + +endmodule diff --git a/ivtest/ivltests/sv_lval_concat_queue_fail4.v b/ivtest/ivltests/sv_lval_concat_queue_fail4.v new file mode 100644 index 000000000..76754cb48 --- /dev/null +++ b/ivtest/ivltests/sv_lval_concat_queue_fail4.v @@ -0,0 +1,10 @@ +// Check that queues can not be used in single operand continuous assignment l-value concatenations. + +module test; + + int q[$]; + int y; + + assign {q} = y; + +endmodule diff --git a/ivtest/ivltests/sv_lval_concat_string_fail1.v b/ivtest/ivltests/sv_lval_concat_string_fail1.v new file mode 100644 index 000000000..9ba22b586 --- /dev/null +++ b/ivtest/ivltests/sv_lval_concat_string_fail1.v @@ -0,0 +1,12 @@ +// Check that strings can not be used in l-value concatenations. + +module test; + + int x; + string s; + + initial begin + {x, s} = x; + end + +endmodule diff --git a/ivtest/ivltests/sv_lval_concat_string_fail2.v b/ivtest/ivltests/sv_lval_concat_string_fail2.v new file mode 100644 index 000000000..09a3d5f41 --- /dev/null +++ b/ivtest/ivltests/sv_lval_concat_string_fail2.v @@ -0,0 +1,12 @@ +// Check that strings can not be used in single operand l-value concatenations. + +module test; + + int x; + string s; + + initial begin + {s} = x; + end + +endmodule diff --git a/ivtest/ivltests/sv_lval_concat_string_fail3.v b/ivtest/ivltests/sv_lval_concat_string_fail3.v new file mode 100644 index 000000000..336d0e669 --- /dev/null +++ b/ivtest/ivltests/sv_lval_concat_string_fail3.v @@ -0,0 +1,11 @@ +// Check that strings can not be used in continuous assignment l-value concatenations. + +module test; + + int x; + string s; + int y; + + assign {x, s} = y; + +endmodule diff --git a/ivtest/ivltests/sv_lval_concat_string_fail4.v b/ivtest/ivltests/sv_lval_concat_string_fail4.v new file mode 100644 index 000000000..404b6f0d2 --- /dev/null +++ b/ivtest/ivltests/sv_lval_concat_string_fail4.v @@ -0,0 +1,10 @@ +// Check that strings can not be used in single operand continuous assignment l-value concatenations. + +module test; + + string s; + int y; + + assign {s} = y; + +endmodule diff --git a/ivtest/ivltests/sv_lval_concat_uarray1.v b/ivtest/ivltests/sv_lval_concat_uarray1.v new file mode 100644 index 000000000..1d88e907b --- /dev/null +++ b/ivtest/ivltests/sv_lval_concat_uarray1.v @@ -0,0 +1,29 @@ +// Check that single element static unpacked array elements can be used in +// procedural l-value concatenations. + +module test; + + reg failed; + reg [7:0] a[0:0]; + reg [7:0] y; + + `define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %h, got %h", `__LINE__, \ + `"val`", exp, val); \ + failed = 1'b1; \ + end + + initial begin + failed = 1'b0; + y = 8'h78; + {a[0]} = y; + + `check(a[0], 8'h78); + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_lval_concat_uarray2.v b/ivtest/ivltests/sv_lval_concat_uarray2.v new file mode 100644 index 000000000..cfa60262c --- /dev/null +++ b/ivtest/ivltests/sv_lval_concat_uarray2.v @@ -0,0 +1,30 @@ +// Check that single element static unpacked array elements can be used in +// continuous l-value concatenations. + +module test; + + reg failed; + wire [7:0] a[0:0]; + reg [7:0] y; + + assign {a[0]} = y; + + `define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %h, got %h", `__LINE__, \ + `"val`", exp, val); \ + failed = 1'b1; \ + end + + initial begin + failed = 1'b0; + y = 8'h78; + #1; + `check(a[0], 8'h78); + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_lval_concat_uarray_fail1.v b/ivtest/ivltests/sv_lval_concat_uarray_fail1.v new file mode 100644 index 000000000..c70b74013 --- /dev/null +++ b/ivtest/ivltests/sv_lval_concat_uarray_fail1.v @@ -0,0 +1,12 @@ +// Check that static unpacked arrays can not be used in l-value concatenations. + +module test; + + int x; + int u[0:0]; + + initial begin + {x, u} = x; + end + +endmodule diff --git a/ivtest/ivltests/sv_lval_concat_uarray_fail2.v b/ivtest/ivltests/sv_lval_concat_uarray_fail2.v new file mode 100644 index 000000000..4d48ed593 --- /dev/null +++ b/ivtest/ivltests/sv_lval_concat_uarray_fail2.v @@ -0,0 +1,12 @@ +// Check that static unpacked arrays can not be used in single operand l-value concatenations. + +module test; + + int x; + int u[0:0]; + + initial begin + {u} = x; + end + +endmodule diff --git a/ivtest/ivltests/sv_lval_concat_uarray_fail3.v b/ivtest/ivltests/sv_lval_concat_uarray_fail3.v new file mode 100644 index 000000000..51b778028 --- /dev/null +++ b/ivtest/ivltests/sv_lval_concat_uarray_fail3.v @@ -0,0 +1,11 @@ +// Check that static unpacked arrays can not be used in continuous assignment l-value concatenations. + +module test; + + int x; + int u[0:0]; + int y; + + assign {x, u} = y; + +endmodule diff --git a/ivtest/ivltests/sv_lval_concat_uarray_fail4.v b/ivtest/ivltests/sv_lval_concat_uarray_fail4.v new file mode 100644 index 000000000..ae15eb28f --- /dev/null +++ b/ivtest/ivltests/sv_lval_concat_uarray_fail4.v @@ -0,0 +1,10 @@ +// Check that static unpacked arrays can not be used in single operand continuous assignment l-value concatenations. + +module test; + + int u[0:0]; + int y; + + assign {u} = y; + +endmodule diff --git a/ivtest/ivltests/sv_net_array_decl_assign.v b/ivtest/ivltests/sv_net_array_decl_assign.v new file mode 100644 index 000000000..48658d317 --- /dev/null +++ b/ivtest/ivltests/sv_net_array_decl_assign.v @@ -0,0 +1,27 @@ +// Check that net arrays can be initialized during declaration. + +module test; + + reg failed; + + wire [3:0] a[0:1] = '{4'h1, 4'h2}; + + `define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %b, got %b", `__LINE__, \ + `"val`", exp, val); \ + failed = 1'b1; \ + end + + initial begin + failed = 1'b0; + + `check(a[0], 4'h1) + `check(a[1], 4'h2) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_net_decl_assign.v b/ivtest/ivltests/sv_net_decl_assign.v new file mode 100644 index 000000000..31ec9b22b --- /dev/null +++ b/ivtest/ivltests/sv_net_decl_assign.v @@ -0,0 +1,33 @@ +// Check that net declarations can mix initialized and uninitialized entries. + +module test; + + reg failed; + + wire [3:0] a, b = 4'h5; + wire [3:0] c = 4'ha, d; + + assign a = b; + assign d = c; + + `define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %b, got %b", `__LINE__, \ + `"val`", exp, val); \ + failed = 1'b1; \ + end + + initial begin + failed = 1'b0; + + `check(a, 4'h5) + `check(b, 4'h5) + `check(c, 4'ha) + `check(d, 4'ha) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_package_lifetime.v b/ivtest/ivltests/sv_package_lifetime.v new file mode 100644 index 000000000..12b3b3338 --- /dev/null +++ b/ivtest/ivltests/sv_package_lifetime.v @@ -0,0 +1,40 @@ +// Check that static lifetime can be specified for variables declared in a +// package. + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %b, got %b", `__LINE__, `"val`", exp, val); \ + failed = 1'b1; \ + end + +package P; + static int x = 1; + const static int y = 2; + var static z; + var static logic [3:0] w = 4'h3; +endpackage + +package automatic Q; + int a = 4; + static int b = 5; +endpackage + +module test; + import P::*; + import Q::*; + + bit failed = 1'b0; + + initial begin + `check(x, 1) + `check(y, 2) + `check(z, 1'bx) + `check(w, 4'h3) + `check(a, 4) + `check(b, 5) + + if (!failed) begin + $display("PASSED"); + end + end +endmodule diff --git a/ivtest/ivltests/sv_package_lifetime_fail.v b/ivtest/ivltests/sv_package_lifetime_fail.v new file mode 100644 index 000000000..3b44251e3 --- /dev/null +++ b/ivtest/ivltests/sv_package_lifetime_fail.v @@ -0,0 +1,6 @@ +// Check that automatic lifetime cannot be specified for variables declared in +// a package. + +package P; + automatic int x; +endpackage diff --git a/ivtest/ivltests/sv_soft_packed_union.v b/ivtest/ivltests/sv_soft_packed_union.v new file mode 100644 index 000000000..6b0e7abc3 --- /dev/null +++ b/ivtest/ivltests/sv_soft_packed_union.v @@ -0,0 +1,81 @@ +// Check that soft packed unions can have members with different widths. + +module test; + + bit failed = 1'b0; + + typedef union soft packed { + logic [31:0] w; + logic [15:0] h; + logic [7:0] b; + } data_t; + + typedef union soft { + logic [31:0] w; + logic [7:0] b; + } implicit_packed_t; + + typedef union soft packed { + logic [15:0] w; + union soft { + logic [7:0] b; + logic [3:0] n; + } part; + } nested_t; + + data_t data; + implicit_packed_t implicit_packed; + nested_t nested; + + `define check(val, exp) do \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0h, got %0h", `__LINE__, \ + `"val`", exp, val); \ + failed = 1'b1; \ + end \ + while(0) + + initial begin + data.w = 32'h12345678; + `check($bits(data), 32); + `check($bits(data_t), 32); + `check(data.w, 32'h12345678); + `check(data.h, 16'h5678); + `check(data.b, 8'h78); + + data.h = 16'habcd; + `check(data.w, 32'h1234abcd); + `check(data.h, 16'habcd); + `check(data.b, 8'hcd); + + data.b = 8'hef; + `check(data.w, 32'h1234abef); + `check(data.h, 16'habef); + `check(data.b, 8'hef); + + implicit_packed.w = 32'hf0e1d2c3; + `check($bits(implicit_packed_t), 32); + `check(implicit_packed.b, 8'hc3); + + implicit_packed.b = 8'h34; + `check(implicit_packed.w, 32'hf0e1d234); + + nested.w = 16'hbeef; + `check($bits(nested_t), 16); + `check($bits(nested.part), 8); + `check(nested.part.b, 8'hef); + `check(nested.part.n, 4'hf); + + nested.part.n = 4'ha; + `check(nested.w, 16'hbeea); + `check(nested.part.b, 8'hea); + + nested.part.b = 8'h55; + `check(nested.w, 16'hbe55); + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_soft_packed_union_fail1.v b/ivtest/ivltests/sv_soft_packed_union_fail1.v new file mode 100644 index 000000000..c54b12e76 --- /dev/null +++ b/ivtest/ivltests/sv_soft_packed_union_fail1.v @@ -0,0 +1,12 @@ +// Check that soft packed unions can not have default member values. + +module test; + + typedef union soft { + logic [31:0] w = 32'h1; + logic [7:0] b; + } data_t; + + data_t data; + +endmodule diff --git a/ivtest/ivltests/sv_super_member_fail.v b/ivtest/ivltests/sv_super_member_fail.v new file mode 100644 index 000000000..503c1131d --- /dev/null +++ b/ivtest/ivltests/sv_super_member_fail.v @@ -0,0 +1,11 @@ +// Check that `super` access in a class without a parent class is rejected. + +module test; + + class C; + function void f; + super.x = 1; + endfunction + endclass + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_class1.v b/ivtest/ivltests/sv_type_param_restrict_class1.v new file mode 100644 index 000000000..9488edcc6 --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_class1.v @@ -0,0 +1,35 @@ +// Check that restricted class type parameter defaults are supported. + +class C0; + bit [7:0] value; +endclass + +module M #( + parameter type class T = C0 +); + T x; +endmodule + +module test; + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \ + failed = 1'b1; \ + end + + bit failed = 1'b0; + + M i_m(); + + initial begin + i_m.x = new; + + `check($bits(i_m.x.value), 8) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_class2.v b/ivtest/ivltests/sv_type_param_restrict_class2.v new file mode 100644 index 000000000..adcc6a626 --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_class2.v @@ -0,0 +1,41 @@ +// Check that restricted class type parameter overrides are supported. + +class C0; + bit [7:0] value; +endclass + +class C1; + bit [15:0] value; +endclass + +module M #( + parameter type class T = C0 +); + T x; +endmodule + +module test; + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \ + failed = 1'b1; \ + end + + bit failed = 1'b0; + + M #( + .T(C1) + ) i_m(); + + initial begin + i_m.x = new; + + `check($bits(i_m.x.value), 16) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_class_fail1.v b/ivtest/ivltests/sv_type_param_restrict_class_fail1.v new file mode 100644 index 000000000..d769159a9 --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_class_fail1.v @@ -0,0 +1,11 @@ +// Check that a class restricted type parameter rejects non-class defaults. + +module test #( + parameter type class T = int +); + + initial begin + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_class_fail2.v b/ivtest/ivltests/sv_type_param_restrict_class_fail2.v new file mode 100644 index 000000000..0c6781015 --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_class_fail2.v @@ -0,0 +1,21 @@ +// Check that a class restricted type parameter rejects non-class overrides. + +class class_t; +endclass + +module M #( + parameter type class T = class_t +); +endmodule + +module test; + + M #( + .T(int) + ) i_m(); + + initial begin + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_enum1.v b/ivtest/ivltests/sv_type_param_restrict_enum1.v new file mode 100644 index 000000000..60d920724 --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_enum1.v @@ -0,0 +1,33 @@ +// Check that restricted enum type parameter defaults are supported. + +typedef enum bit [2:0] { + A0, B0 +} T0; + +module M #( + parameter type enum T = T0 +); + T x; +endmodule + +module test; + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \ + failed = 1'b1; \ + end + + bit failed = 1'b0; + + M i_m(); + + initial begin + `check($bits(i_m.x), $bits(T0)) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_enum2.v b/ivtest/ivltests/sv_type_param_restrict_enum2.v new file mode 100644 index 000000000..028e8eec6 --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_enum2.v @@ -0,0 +1,39 @@ +// Check that restricted enum type parameter overrides are supported. + +typedef enum bit [2:0] { + A0, B0 +} T0; + +typedef enum bit [3:0] { + A1, B1 +} T1; + +module M #( + parameter type enum T = T0 +); + T x; +endmodule + +module test; + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \ + failed = 1'b1; \ + end + + bit failed = 1'b0; + + M #( + .T(T1) + ) i_m(); + + initial begin + `check($bits(i_m.x), $bits(T1)) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_enum_fail1.v b/ivtest/ivltests/sv_type_param_restrict_enum_fail1.v new file mode 100644 index 000000000..a36c1e8c7 --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_enum_fail1.v @@ -0,0 +1,11 @@ +// Check that an enum restricted type parameter rejects non-enum defaults. + +module test #( + parameter type enum T = int +); + + initial begin + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_enum_fail2.v b/ivtest/ivltests/sv_type_param_restrict_enum_fail2.v new file mode 100644 index 000000000..1e1f564ae --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_enum_fail2.v @@ -0,0 +1,22 @@ +// Check that an enum restricted type parameter rejects non-enum overrides. + +typedef enum bit { + ENUM_VALUE +} enum_t; + +module M #( + parameter type enum T = enum_t +); +endmodule + +module test; + + M #( + .T(int) + ) i_m(); + + initial begin + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_struct1.v b/ivtest/ivltests/sv_type_param_restrict_struct1.v new file mode 100644 index 000000000..a127b117e --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_struct1.v @@ -0,0 +1,33 @@ +// Check that restricted struct type parameter defaults are supported. + +typedef struct packed { + logic [3:0] x; +} T0; + +module M #( + parameter type struct T = T0 +); + T x; +endmodule + +module test; + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \ + failed = 1'b1; \ + end + + bit failed = 1'b0; + + M i_m(); + + initial begin + `check($bits(i_m.x), $bits(T0)) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_struct2.v b/ivtest/ivltests/sv_type_param_restrict_struct2.v new file mode 100644 index 000000000..c3b30f58b --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_struct2.v @@ -0,0 +1,39 @@ +// Check that restricted struct type parameter overrides are supported. + +typedef struct packed { + logic [3:0] x; +} T0; + +typedef struct packed { + logic [7:0] x; +} T1; + +module M #( + parameter type struct T = T0 +); + T x; +endmodule + +module test; + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \ + failed = 1'b1; \ + end + + bit failed = 1'b0; + + M #( + .T(T1) + ) i_m(); + + initial begin + `check($bits(i_m.x), $bits(T1)) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_struct_fail1.v b/ivtest/ivltests/sv_type_param_restrict_struct_fail1.v new file mode 100644 index 000000000..ff707bdf7 --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_struct_fail1.v @@ -0,0 +1,16 @@ +// Check that a struct restricted type parameter rejects non-struct defaults. + +typedef union packed { + logic [3:0] value; + logic [3:0] other; +} union_t; + +module test #( + parameter type struct T = union_t +); + + initial begin + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_struct_fail2.v b/ivtest/ivltests/sv_type_param_restrict_struct_fail2.v new file mode 100644 index 000000000..bd78897a7 --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_struct_fail2.v @@ -0,0 +1,27 @@ +// Check that a struct restricted type parameter rejects non-struct overrides. + +typedef struct packed { + logic [3:0] value; +} struct_t; + +typedef union packed { + logic [3:0] value; + logic [3:0] other; +} union_t; + +module M #( + parameter type struct T = struct_t +); +endmodule + +module test; + + M #( + .T(union_t) + ) i_m(); + + initial begin + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_union1.v b/ivtest/ivltests/sv_type_param_restrict_union1.v new file mode 100644 index 000000000..df337c21e --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_union1.v @@ -0,0 +1,34 @@ +// Check that restricted union type parameter defaults are supported. + +typedef union packed { + logic [3:0] x; + logic [3:0] y; +} T0; + +module M #( + parameter type union T = T0 +); + T x; +endmodule + +module test; + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \ + failed = 1'b1; \ + end + + bit failed = 1'b0; + + M i_m(); + + initial begin + `check($bits(i_m.x), $bits(T0)) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_union2.v b/ivtest/ivltests/sv_type_param_restrict_union2.v new file mode 100644 index 000000000..588a245b2 --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_union2.v @@ -0,0 +1,41 @@ +// Check that restricted union type parameter overrides are supported. + +typedef union packed { + logic [3:0] x; + logic [3:0] y; +} T0; + +typedef union packed { + logic [7:0] x; + logic [7:0] y; +} T1; + +module M #( + parameter type union T = T0 +); + T x; +endmodule + +module test; + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \ + failed = 1'b1; \ + end + + bit failed = 1'b0; + + M #( + .T(T1) + ) i_m(); + + initial begin + `check($bits(i_m.x), $bits(T1)) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_union_fail1.v b/ivtest/ivltests/sv_type_param_restrict_union_fail1.v new file mode 100644 index 000000000..1d581e36c --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_union_fail1.v @@ -0,0 +1,15 @@ +// Check that a union restricted type parameter rejects non-union defaults. + +typedef struct packed { + logic [3:0] value; +} struct_t; + +module test #( + parameter type union T = struct_t +); + + initial begin + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_union_fail2.v b/ivtest/ivltests/sv_type_param_restrict_union_fail2.v new file mode 100644 index 000000000..b49552c17 --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_union_fail2.v @@ -0,0 +1,27 @@ +// Check that a union restricted type parameter rejects non-union overrides. + +typedef struct packed { + logic [3:0] value; +} struct_t; + +typedef union packed { + logic [3:0] value; + logic [3:0] other; +} union_t; + +module M #( + parameter type union T = union_t +); +endmodule + +module test; + + M #( + .T(struct_t) + ) i_m(); + + initial begin + $display("FAILED"); + end + +endmodule diff --git a/ivtest/perl-lib/RegressionList.pm b/ivtest/perl-lib/RegressionList.pm index a089b4d18..a03a1beda 100644 --- a/ivtest/perl-lib/RegressionList.pm +++ b/ivtest/perl-lib/RegressionList.pm @@ -172,13 +172,15 @@ sub read_regression_list { $nameidx{$tname} = @testlist - 1; # The generation to use is passed if it does not match - # the default. To make sure the tests are protable we + # the default. To make sure the tests are portable we # use the force SV flag to force all tests to be run # as the latest SystemVerilog generation. This assumes # the correct `begin_keywords has been added to the # various files. if ($force_sv) { - my $fsv_flags = "-g2012"; + my $fsv_flags = "-g2023"; + $args{$tname} =~ s/-g2023//; + $args{$tname} =~ s/-g2017//; $args{$tname} =~ s/-g2012//; $args{$tname} =~ s/-g2009//; $args{$tname} =~ s/-g2005-sv//; diff --git a/ivtest/regress-vlg.list b/ivtest/regress-vlg.list index 9309d3afa..55fbc8cc5 100644 --- a/ivtest/regress-vlg.list +++ b/ivtest/regress-vlg.list @@ -719,7 +719,6 @@ multi_bit_strength normal ivltests gold=multi_bit_strength.gold multi_driver_delay normal ivltests multiply_large normal ivltests # Takes care of PR222 muxtest normal ivltests # Validates that X sel and inputs same, output not X -named_event_no_edges CE ivltests nb_assign normal ivltests nb_delay normal ivltests nb_ec_concat normal ivltests diff --git a/ivtest/regress-vvp.list b/ivtest/regress-vvp.list index 8a3639d4f..c1e149f8f 100644 --- a/ivtest/regress-vvp.list +++ b/ivtest/regress-vvp.list @@ -6,6 +6,7 @@ always4A vvp_tests/always4A.json always4B vvp_tests/always4B.json analog1 vvp_tests/analog1.json analog2 vvp_tests/analog2.json +array_index_real_fail vvp_tests/array_index_real_fail.json array_packed_sysfunct vvp_tests/array_packed_sysfunct.json array_packed_value_list vvp_tests/array_packed_value_list.json array_packed_write_read vvp_tests/array_packed_write_read.json @@ -13,6 +14,16 @@ array_slice_concat vvp_tests/array_slice_concat.json automatic_error11 vvp_tests/automatic_error11.json automatic_error12 vvp_tests/automatic_error12.json automatic_error13 vvp_tests/automatic_error13.json +begin_keywords_1364_1995 vvp_tests/begin_keywords_1364_1995.json +begin_keywords_1364_2001 vvp_tests/begin_keywords_1364_2001.json +begin_keywords_1364_2001_noconfig vvp_tests/begin_keywords_1364_2001_noconfig.json +begin_keywords_1364_2005 vvp_tests/begin_keywords_1364_2005.json +begin_keywords_1800_2005 vvp_tests/begin_keywords_1800_2005.json +begin_keywords_1800_2009 vvp_tests/begin_keywords_1800_2009.json +begin_keywords_1800_2012 vvp_tests/begin_keywords_1800_2012.json +begin_keywords_1800_2017 vvp_tests/begin_keywords_1800_2017.json +begin_keywords_1800_2023 vvp_tests/begin_keywords_1800_2023.json +begin_keywords_vams_2_3 vvp_tests/begin_keywords_vams_2_3.json bits4 vvp_tests/bits4.json bitsel11 vvp_tests/bitsel11.json br_gh13a vvp_tests/br_gh13a.json @@ -31,6 +42,7 @@ br_gh703 vvp_tests/br_gh703.json br_gh710a vvp_tests/br_gh710a.json br_gh710b vvp_tests/br_gh710b.json br_gh710c vvp_tests/br_gh710c.json +br_gh710d vvp_tests/br_gh710d.json br_gh939 vvp_tests/br_gh939.json br_gh1001 vvp_tests/br_gh1001.json br_gh1018 vvp_tests/br_gh1018.json @@ -117,6 +129,7 @@ dffsynth8 vvp_tests/dffsynth8.json dffsynth9 vvp_tests/dffsynth9.json dffsynth10 vvp_tests/dffsynth10.json dffsynth11 vvp_tests/dffsynth11.json +drive_strength4 vvp_tests/drive_strength4.json dumpfile vvp_tests/dumpfile.json early_sig_elab1 vvp_tests/early_sig_elab1.json early_sig_elab2 vvp_tests/early_sig_elab2.json @@ -150,8 +163,12 @@ mix_reset-synth vvp_tests/mix_reset-synth.json module_ordered_list1 vvp_tests/module_ordered_list1.json module_ordered_list2 vvp_tests/module_ordered_list2.json module_port_array1 vvp_tests/module_port_array1.json +module_port_array_fail1 vvp_tests/module_port_array_fail1.json module_port_array_init1 vvp_tests/module_port_array_init1.json monitor4 vvp_tests/monitor4.json +named_event_edge_fail vvp_tests/named_event_edge_fail.json +named_event_negedge_fail vvp_tests/named_event_negedge_fail.json +named_event_posedge_fail vvp_tests/named_event_posedge_fail.json non-polymorphic-abs vvp_tests/non-polymorphic-abs.json partsel_invalid_idx1 vvp_tests/partsel_invalid_idx1.json partsel_invalid_idx2 vvp_tests/partsel_invalid_idx2.json @@ -216,14 +233,30 @@ sv_ap_uarray5 vvp_tests/sv_ap_uarray5.json sv_ap_uarray6 vvp_tests/sv_ap_uarray6.json sv_ap_uarray_fail1 vvp_tests/sv_ap_uarray_fail1.json sv_ap_uarray_fail2 vvp_tests/sv_ap_uarray_fail2.json +sv_ap_uarray_single1 vvp_tests/sv_ap_uarray_single1.json +sv_ap_uarray_single2 vvp_tests/sv_ap_uarray_single2.json sv_argumentless_func vvp_tests/sv_argumentless_func.json sv_array_assign_fail1 vvp_tests/sv_array_assign_fail1.json sv_array_assign_fail2 vvp_tests/sv_array_assign_fail2.json +sv_array_assign_single_fail1 vvp_tests/sv_array_assign_single_fail1.json sv_array_cassign6 vvp_tests/sv_array_cassign6.json sv_array_cassign7 vvp_tests/sv_array_cassign7.json sv_array_cassign8 vvp_tests/sv_array_cassign8.json +sv_array_cassign9 vvp_tests/sv_array_cassign9.json +sv_array_cassign10 vvp_tests/sv_array_cassign10.json +sv_array_cassign_single vvp_tests/sv_array_cassign_single.json +sv_array_cassign_single_fail1 vvp_tests/sv_array_cassign_single_fail1.json sv_automatic_2state vvp_tests/sv_automatic_2state.json sv_call_chain_method1 vvp_tests/sv_call_chain_method1.json +sv_byte_array_string1 vvp_tests/sv_byte_array_string1.json +sv_byte_array_string2 vvp_tests/sv_byte_array_string2.json +sv_byte_array_string3 vvp_tests/sv_byte_array_string3.json +sv_byte_array_string4 vvp_tests/sv_byte_array_string4.json +sv_byte_array_string_fail1 vvp_tests/sv_byte_array_string_fail1.json +sv_byte_array_string_fail2 vvp_tests/sv_byte_array_string_fail2.json +sv_byte_array_string_fail3 vvp_tests/sv_byte_array_string_fail3.json +sv_byte_array_string_fail4 vvp_tests/sv_byte_array_string_fail4.json +sv_byte_array_string_fail5 vvp_tests/sv_byte_array_string_fail5.json sv_chained_constructor1 vvp_tests/sv_chained_constructor1.json sv_chained_constructor2 vvp_tests/sv_chained_constructor2.json sv_chained_constructor3 vvp_tests/sv_chained_constructor3.json @@ -236,8 +269,8 @@ sv_class_darray_prop_locators vvp_tests/sv_class_darray_prop_locators.json sv_class_queue_prop_locators vvp_tests/sv_class_queue_prop_locators.json sv_class_prop_nest_darray1 vvp_tests/sv_class_prop_nest_darray1.json sv_class_prop_nest_obj1 vvp_tests/sv_class_prop_nest_obj1.json -sv_class_prop_nest_real1 vvp_tests/sv_class_prop_nest_str1.json -sv_class_prop_nest_str1 vvp_tests/sv_class_prop_nest_real1.json +sv_class_prop_nest_real1 vvp_tests/sv_class_prop_nest_real1.json +sv_class_prop_nest_str1 vvp_tests/sv_class_prop_nest_str1.json sv_class_prop_nest_vec1 vvp_tests/sv_class_prop_nest_vec1.json sv_class_queue_prop_methods vvp_tests/sv_class_queue_prop_methods.json sv_const1 vvp_tests/sv_const1.json @@ -272,7 +305,50 @@ sv_default_port_value3 vvp_tests/sv_default_port_value3.json sv_foreach9 vvp_tests/sv_foreach9.json sv_foreach10 vvp_tests/sv_foreach10.json sv_interface vvp_tests/sv_interface.json +sv_interface_port_basic vvp_tests/sv_interface_port_basic.json +sv_interface_port_missing_type_fail vvp_tests/sv_interface_port_missing_type_fail.json +sv_interface_port_missing_modport_fail vvp_tests/sv_interface_port_missing_modport_fail.json +sv_interface_port_non_interface_actual_fail vvp_tests/sv_interface_port_non_interface_actual_fail.json +sv_interface_port_wrong_type_fail vvp_tests/sv_interface_port_wrong_type_fail.json +sv_interface_port_modport_input_write_fail vvp_tests/sv_interface_port_modport_input_write_fail.json +sv_interface_port_unlisted_member_fail vvp_tests/sv_interface_port_unlisted_member_fail.json +sv_interface_port_unmodported_basic vvp_tests/sv_interface_port_unmodported_basic.json +sv_interface_port_unmodported_missing_type_fail vvp_tests/sv_interface_port_unmodported_missing_type_fail.json +sv_interface_port_forwarding vvp_tests/sv_interface_port_forwarding.json +sv_interface_port_forwarding_restrict_fail vvp_tests/sv_interface_port_forwarding_restrict_fail.json +sv_interface_port_positional vvp_tests/sv_interface_port_positional.json +sv_interface_port_positional_unconnected_fail vvp_tests/sv_interface_port_positional_unconnected_fail.json +sv_interface_port_wildcard vvp_tests/sv_interface_port_wildcard.json +sv_interface_port_indexed_actual vvp_tests/sv_interface_port_indexed_actual.json +sv_interface_port_indexed_actual_generate vvp_tests/sv_interface_port_indexed_actual_generate.json +sv_interface_port_array_basic vvp_tests/sv_interface_port_array_basic.json +sv_interface_port_array_modport_restrict_fail vvp_tests/sv_interface_port_array_modport_restrict_fail.json +sv_interface_port_array_size_mismatch_fail vvp_tests/sv_interface_port_array_size_mismatch_fail.json +sv_interface_port_plain_ansi_regression vvp_tests/sv_interface_port_plain_ansi_regression.json +sv_interface_port_typedef_ansi_regression vvp_tests/sv_interface_port_typedef_ansi_regression.json sv_literals vvp_tests/sv_literals.json +sv_lval_concat_class_fail1 vvp_tests/sv_lval_concat_class_fail1.json +sv_lval_concat_class_fail2 vvp_tests/sv_lval_concat_class_fail2.json +sv_lval_concat_class_fail3 vvp_tests/sv_lval_concat_class_fail3.json +sv_lval_concat_class_fail4 vvp_tests/sv_lval_concat_class_fail4.json +sv_lval_concat_darray_fail1 vvp_tests/sv_lval_concat_darray_fail1.json +sv_lval_concat_darray_fail2 vvp_tests/sv_lval_concat_darray_fail2.json +sv_lval_concat_darray_fail3 vvp_tests/sv_lval_concat_darray_fail3.json +sv_lval_concat_darray_fail4 vvp_tests/sv_lval_concat_darray_fail4.json +sv_lval_concat_queue_fail1 vvp_tests/sv_lval_concat_queue_fail1.json +sv_lval_concat_queue_fail2 vvp_tests/sv_lval_concat_queue_fail2.json +sv_lval_concat_queue_fail3 vvp_tests/sv_lval_concat_queue_fail3.json +sv_lval_concat_queue_fail4 vvp_tests/sv_lval_concat_queue_fail4.json +sv_lval_concat_string_fail1 vvp_tests/sv_lval_concat_string_fail1.json +sv_lval_concat_string_fail2 vvp_tests/sv_lval_concat_string_fail2.json +sv_lval_concat_string_fail3 vvp_tests/sv_lval_concat_string_fail3.json +sv_lval_concat_string_fail4 vvp_tests/sv_lval_concat_string_fail4.json +sv_lval_concat_uarray1 vvp_tests/sv_lval_concat_uarray1.json +sv_lval_concat_uarray2 vvp_tests/sv_lval_concat_uarray2.json +sv_lval_concat_uarray_fail1 vvp_tests/sv_lval_concat_uarray_fail1.json +sv_lval_concat_uarray_fail2 vvp_tests/sv_lval_concat_uarray_fail2.json +sv_lval_concat_uarray_fail3 vvp_tests/sv_lval_concat_uarray_fail3.json +sv_lval_concat_uarray_fail4 vvp_tests/sv_lval_concat_uarray_fail4.json sv_mixed_assign1 vvp_tests/sv_mixed_assign1.json sv_mixed_assign2 vvp_tests/sv_mixed_assign2.json sv_mixed_assign_error1 vvp_tests/sv_mixed_assign_error1.json @@ -283,6 +359,10 @@ sv_module_port1 vvp_tests/sv_module_port1.json sv_module_port2 vvp_tests/sv_module_port2.json sv_module_port3 vvp_tests/sv_module_port3.json sv_module_port4 vvp_tests/sv_module_port4.json +sv_net_array_decl_assign vvp_tests/sv_net_array_decl_assign.json +sv_net_decl_assign vvp_tests/sv_net_decl_assign.json +sv_package_lifetime vvp_tests/sv_package_lifetime.json +sv_package_lifetime_fail vvp_tests/sv_package_lifetime_fail.json sv_parameter_type vvp_tests/sv_parameter_type.json sv_queue_assign_op vvp_tests/sv_queue_assign_op.json sv_queue_unique vvp_tests/sv_queue_unique.json @@ -297,6 +377,25 @@ sv_queue_reverse vvp_tests/sv_queue_reverse.json sv_queue_sort vvp_tests/sv_queue_sort.json sv_queue_sum vvp_tests/sv_queue_sum.json sv_queue_sum_with vvp_tests/sv_queue_sum_with.json +sv_soft_packed_union vvp_tests/sv_soft_packed_union.json +sv_soft_packed_union_fail1 vvp_tests/sv_soft_packed_union_fail1.json +sv_super_member_fail vvp_tests/sv_super_member_fail.json +sv_type_param_restrict_class1 vvp_tests/sv_type_param_restrict_class1.json +sv_type_param_restrict_class2 vvp_tests/sv_type_param_restrict_class2.json +sv_type_param_restrict_class_fail1 vvp_tests/sv_type_param_restrict_class_fail1.json +sv_type_param_restrict_class_fail2 vvp_tests/sv_type_param_restrict_class_fail2.json +sv_type_param_restrict_enum1 vvp_tests/sv_type_param_restrict_enum1.json +sv_type_param_restrict_enum2 vvp_tests/sv_type_param_restrict_enum2.json +sv_type_param_restrict_enum_fail1 vvp_tests/sv_type_param_restrict_enum_fail1.json +sv_type_param_restrict_enum_fail2 vvp_tests/sv_type_param_restrict_enum_fail2.json +sv_type_param_restrict_struct1 vvp_tests/sv_type_param_restrict_struct1.json +sv_type_param_restrict_struct2 vvp_tests/sv_type_param_restrict_struct2.json +sv_type_param_restrict_struct_fail1 vvp_tests/sv_type_param_restrict_struct_fail1.json +sv_type_param_restrict_struct_fail2 vvp_tests/sv_type_param_restrict_struct_fail2.json +sv_type_param_restrict_union1 vvp_tests/sv_type_param_restrict_union1.json +sv_type_param_restrict_union2 vvp_tests/sv_type_param_restrict_union2.json +sv_type_param_restrict_union_fail1 vvp_tests/sv_type_param_restrict_union_fail1.json +sv_type_param_restrict_union_fail2 vvp_tests/sv_type_param_restrict_union_fail2.json sv_wildcard_import8 vvp_tests/sv_wildcard_import8.json sdf_header vvp_tests/sdf_header.json task_return1 vvp_tests/task_return1.json diff --git a/ivtest/vlog95_reg.pl b/ivtest/vlog95_reg.pl index 25caee834..ad2fc8174 100755 --- a/ivtest/vlog95_reg.pl +++ b/ivtest/vlog95_reg.pl @@ -4,7 +4,7 @@ # # This script is based on code with the following Copyright. # -# Copyright (c) 1999-2025 Guy Hutchison (ghutchis@pacbell.net) +# Copyright (c) 1999-2026 Guy Hutchison (ghutchis@pacbell.net) # # This source code is free software; you can redistribute it # and/or modify it in source code form under the terms of the GNU @@ -183,6 +183,8 @@ sub execute_regression { $args{$tname} =~ s/-g2005(-sv)?//g; $args{$tname} =~ s/-g2009//g; $args{$tname} =~ s/-g2012//g; + $args{$tname} =~ s/-g2017//g; + $args{$tname} =~ s/-g2023//g; $args{$tname} =~ s/-gverilog-ams//g; $cmd = "iverilog$sfx -o vsim $gen_flag $args{$tname}"; $cmd .= " -s $testmod{$tname}" if ($testmod{$tname} ne ""); diff --git a/ivtest/vvp_reg.py b/ivtest/vvp_reg.py index 601dc45bb..6cc6d5ad2 100755 --- a/ivtest/vvp_reg.py +++ b/ivtest/vvp_reg.py @@ -64,7 +64,7 @@ def process_overrides(group: str, it_dict: dict, it_opts: dict): def force_gen(it_opts: dict): '''Remove the current generation and force it to the latest.''' - generations = ['-g2012', '-g2009', '-g2005-sv', + generations = ['-g2023', '-g2017', '-g2012', '-g2009', '-g2005-sv', '-g2005', '-g2001-noconfig', '-g2001', '-g1995', '-g2', '-g1'] for gen in generations: @@ -75,7 +75,7 @@ def force_gen(it_opts: dict): idx_to_replace = it_opts['iverilog_args'].index('-g2x') it_opts[idx_to_replace] = '-gicarus-misc' - it_opts['iverilog_args'].insert(0, '-g2012') + it_opts['iverilog_args'].insert(0, '-g2023') def process_test(item: list, cfg: list) -> str: diff --git a/ivtest/vvp_tests/array_index_real_fail.json b/ivtest/vvp_tests/array_index_real_fail.json new file mode 100644 index 000000000..a4b453e0a --- /dev/null +++ b/ivtest/vvp_tests/array_index_real_fail.json @@ -0,0 +1,4 @@ +{ + "type" : "CE", + "source" : "array_index_real_fail.v" +} diff --git a/ivtest/vvp_tests/begin_keywords_1364_1995.json b/ivtest/vvp_tests/begin_keywords_1364_1995.json new file mode 100644 index 000000000..4714ae520 --- /dev/null +++ b/ivtest/vvp_tests/begin_keywords_1364_1995.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "begin_keywords_1364_1995.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/begin_keywords_1364_2001.json b/ivtest/vvp_tests/begin_keywords_1364_2001.json new file mode 100644 index 000000000..a51d48856 --- /dev/null +++ b/ivtest/vvp_tests/begin_keywords_1364_2001.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "begin_keywords_1364_2001.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/begin_keywords_1364_2001_noconfig.json b/ivtest/vvp_tests/begin_keywords_1364_2001_noconfig.json new file mode 100644 index 000000000..ac1342d7d --- /dev/null +++ b/ivtest/vvp_tests/begin_keywords_1364_2001_noconfig.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "begin_keywords_1364_2001_noconfig.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/begin_keywords_1364_2005.json b/ivtest/vvp_tests/begin_keywords_1364_2005.json new file mode 100644 index 000000000..50d7b65f6 --- /dev/null +++ b/ivtest/vvp_tests/begin_keywords_1364_2005.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "begin_keywords_1364_2005.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/begin_keywords_1800_2005.json b/ivtest/vvp_tests/begin_keywords_1800_2005.json new file mode 100644 index 000000000..6fadb9da6 --- /dev/null +++ b/ivtest/vvp_tests/begin_keywords_1800_2005.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "begin_keywords_1800_2005.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/begin_keywords_1800_2009.json b/ivtest/vvp_tests/begin_keywords_1800_2009.json new file mode 100644 index 000000000..84460a9db --- /dev/null +++ b/ivtest/vvp_tests/begin_keywords_1800_2009.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "begin_keywords_1800_2009.v", + "iverilog-args" : [ "-g2009" ] +} diff --git a/ivtest/vvp_tests/begin_keywords_1800_2012.json b/ivtest/vvp_tests/begin_keywords_1800_2012.json new file mode 100644 index 000000000..c83b42cf4 --- /dev/null +++ b/ivtest/vvp_tests/begin_keywords_1800_2012.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "begin_keywords_1800_2012.v", + "iverilog-args" : [ "-g2012" ] +} diff --git a/ivtest/vvp_tests/begin_keywords_1800_2017.json b/ivtest/vvp_tests/begin_keywords_1800_2017.json new file mode 100644 index 000000000..0545c5f39 --- /dev/null +++ b/ivtest/vvp_tests/begin_keywords_1800_2017.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "begin_keywords_1800_2017.v", + "iverilog-args" : [ "-g2017" ] +} diff --git a/ivtest/vvp_tests/begin_keywords_1800_2023.json b/ivtest/vvp_tests/begin_keywords_1800_2023.json new file mode 100644 index 000000000..22a3b51e8 --- /dev/null +++ b/ivtest/vvp_tests/begin_keywords_1800_2023.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "begin_keywords_1800_2023.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/begin_keywords_vams_2_3.json b/ivtest/vvp_tests/begin_keywords_vams_2_3.json new file mode 100644 index 000000000..fe44aca3f --- /dev/null +++ b/ivtest/vvp_tests/begin_keywords_vams_2_3.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "begin_keywords_vams_2_3.v", + "iverilog-args" : [ "-g2005-sv", "-gverilog-ams" ] +} diff --git a/ivtest/vvp_tests/br_gh1256b.json b/ivtest/vvp_tests/br_gh1256b.json index c1598a869..ae8ab6e8f 100644 --- a/ivtest/vvp_tests/br_gh1256b.json +++ b/ivtest/vvp_tests/br_gh1256b.json @@ -1,5 +1,5 @@ { "type" : "normal", - "source" : "br_gh1256a.v", + "source" : "br_gh1256b.v", "iverilog-args" : [ "-g2009" ] } diff --git a/ivtest/vvp_tests/br_gh710d.json b/ivtest/vvp_tests/br_gh710d.json new file mode 100644 index 000000000..18d7f106b --- /dev/null +++ b/ivtest/vvp_tests/br_gh710d.json @@ -0,0 +1,7 @@ +{ + "type" : "normal", + "source" : "br_gh710.v", + "gold" : "br_gh710d", + "iverilog-args" : [ "-g2009" ], + "vvp-args-extended" : [ "-fst" ] +} diff --git a/ivtest/vvp_tests/drive_strength4.json b/ivtest/vvp_tests/drive_strength4.json new file mode 100644 index 000000000..73b273742 --- /dev/null +++ b/ivtest/vvp_tests/drive_strength4.json @@ -0,0 +1,4 @@ +{ + "type" : "normal", + "source" : "drive_strength4.v" +} diff --git a/ivtest/vvp_tests/module_port_array_fail1.json b/ivtest/vvp_tests/module_port_array_fail1.json new file mode 100644 index 000000000..a7a343dca --- /dev/null +++ b/ivtest/vvp_tests/module_port_array_fail1.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "module_port_array_fail1.v", + "iverilog-args" : [ "-g2009" ] +} diff --git a/ivtest/vvp_tests/named_event_edge_fail.json b/ivtest/vvp_tests/named_event_edge_fail.json new file mode 100644 index 000000000..f572263f7 --- /dev/null +++ b/ivtest/vvp_tests/named_event_edge_fail.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "named_event_edge_fail.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/named_event_negedge_fail.json b/ivtest/vvp_tests/named_event_negedge_fail.json new file mode 100644 index 000000000..b0afab36a --- /dev/null +++ b/ivtest/vvp_tests/named_event_negedge_fail.json @@ -0,0 +1,4 @@ +{ + "type" : "CE", + "source" : "named_event_negedge_fail.v" +} diff --git a/ivtest/vvp_tests/named_event_posedge_fail.json b/ivtest/vvp_tests/named_event_posedge_fail.json new file mode 100644 index 000000000..2ae4014d7 --- /dev/null +++ b/ivtest/vvp_tests/named_event_posedge_fail.json @@ -0,0 +1,4 @@ +{ + "type" : "CE", + "source" : "named_event_posedge_fail.v" +} diff --git a/ivtest/vvp_tests/sv_ap_uarray_single1.json b/ivtest/vvp_tests/sv_ap_uarray_single1.json new file mode 100644 index 000000000..792665cb9 --- /dev/null +++ b/ivtest/vvp_tests/sv_ap_uarray_single1.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_ap_uarray_single1.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "Array nets are not supported", + "type" : "CE" + } +} diff --git a/ivtest/vvp_tests/sv_ap_uarray_single2.json b/ivtest/vvp_tests/sv_ap_uarray_single2.json new file mode 100644 index 000000000..e372d0a0b --- /dev/null +++ b/ivtest/vvp_tests/sv_ap_uarray_single2.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_ap_uarray_single2.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "Array nets are not supported", + "type" : "CE" + } +} diff --git a/ivtest/vvp_tests/sv_array_assign_single_fail1.json b/ivtest/vvp_tests/sv_array_assign_single_fail1.json new file mode 100644 index 000000000..54c147114 --- /dev/null +++ b/ivtest/vvp_tests/sv_array_assign_single_fail1.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_array_assign_single_fail1.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_array_cassign10.json b/ivtest/vvp_tests/sv_array_cassign10.json new file mode 100644 index 000000000..0c3331289 --- /dev/null +++ b/ivtest/vvp_tests/sv_array_cassign10.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_array_cassign10.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "Array nets are not supported", + "type" : "CE" + } +} diff --git a/ivtest/vvp_tests/sv_array_cassign9.json b/ivtest/vvp_tests/sv_array_cassign9.json new file mode 100644 index 000000000..1b8bd91eb --- /dev/null +++ b/ivtest/vvp_tests/sv_array_cassign9.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_array_cassign9.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "Array nets are not supported", + "type" : "CE" + } +} diff --git a/ivtest/vvp_tests/sv_array_cassign_single.json b/ivtest/vvp_tests/sv_array_cassign_single.json new file mode 100644 index 000000000..23848684d --- /dev/null +++ b/ivtest/vvp_tests/sv_array_cassign_single.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_array_cassign_single.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "Array nets are not supported", + "type" : "CE" + } +} diff --git a/ivtest/vvp_tests/sv_array_cassign_single_fail1.json b/ivtest/vvp_tests/sv_array_cassign_single_fail1.json new file mode 100644 index 000000000..03252cf4e --- /dev/null +++ b/ivtest/vvp_tests/sv_array_cassign_single_fail1.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_array_cassign_single_fail1.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_byte_array_string1.json b/ivtest/vvp_tests/sv_byte_array_string1.json new file mode 100644 index 000000000..a2006f981 --- /dev/null +++ b/ivtest/vvp_tests/sv_byte_array_string1.json @@ -0,0 +1,10 @@ +{ + "type" : "normal", + "source" : "sv_byte_array_string1.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "Array nets are not supported", + "type" : "CE", + "iverilog-args" : [ "-pallowsigned=1" ] + } +} diff --git a/ivtest/vvp_tests/sv_byte_array_string2.json b/ivtest/vvp_tests/sv_byte_array_string2.json new file mode 100644 index 000000000..87bf891eb --- /dev/null +++ b/ivtest/vvp_tests/sv_byte_array_string2.json @@ -0,0 +1,10 @@ +{ + "type" : "normal", + "source" : "sv_byte_array_string2.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "Array nets are not supported", + "type" : "CE", + "iverilog-args" : [ "-pallowsigned=1" ] + } +} diff --git a/ivtest/vvp_tests/sv_byte_array_string3.json b/ivtest/vvp_tests/sv_byte_array_string3.json new file mode 100644 index 000000000..02e0f4f31 --- /dev/null +++ b/ivtest/vvp_tests/sv_byte_array_string3.json @@ -0,0 +1,10 @@ +{ + "type" : "normal", + "source" : "sv_byte_array_string3.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "Array nets are not supported", + "type" : "CE", + "iverilog-args" : [ "-pallowsigned=1" ] + } +} diff --git a/ivtest/vvp_tests/sv_byte_array_string4.json b/ivtest/vvp_tests/sv_byte_array_string4.json new file mode 100644 index 000000000..412e46c7e --- /dev/null +++ b/ivtest/vvp_tests/sv_byte_array_string4.json @@ -0,0 +1,10 @@ +{ + "type" : "normal", + "source" : "sv_byte_array_string4.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "Array nets are not supported", + "type" : "CE", + "iverilog-args" : [ "-pallowsigned=1" ] + } +} diff --git a/ivtest/vvp_tests/sv_byte_array_string_fail1.json b/ivtest/vvp_tests/sv_byte_array_string_fail1.json new file mode 100644 index 000000000..51aaf0658 --- /dev/null +++ b/ivtest/vvp_tests/sv_byte_array_string_fail1.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_byte_array_string_fail1.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_byte_array_string_fail2.json b/ivtest/vvp_tests/sv_byte_array_string_fail2.json new file mode 100644 index 000000000..000b19b4c --- /dev/null +++ b/ivtest/vvp_tests/sv_byte_array_string_fail2.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_byte_array_string_fail2.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_byte_array_string_fail3.json b/ivtest/vvp_tests/sv_byte_array_string_fail3.json new file mode 100644 index 000000000..b9c693937 --- /dev/null +++ b/ivtest/vvp_tests/sv_byte_array_string_fail3.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_byte_array_string_fail3.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_byte_array_string_fail4.json b/ivtest/vvp_tests/sv_byte_array_string_fail4.json new file mode 100644 index 000000000..a4c171738 --- /dev/null +++ b/ivtest/vvp_tests/sv_byte_array_string_fail4.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_byte_array_string_fail4.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_byte_array_string_fail5.json b/ivtest/vvp_tests/sv_byte_array_string_fail5.json new file mode 100644 index 000000000..a6a741748 --- /dev/null +++ b/ivtest/vvp_tests/sv_byte_array_string_fail5.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_byte_array_string_fail5.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_interface_port_array_basic.json b/ivtest/vvp_tests/sv_interface_port_array_basic.json new file mode 100644 index 000000000..795be443a --- /dev/null +++ b/ivtest/vvp_tests/sv_interface_port_array_basic.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_interface_port_array_basic.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "Interfaces are not supported", + "type" : "TE" + } +} diff --git a/ivtest/vvp_tests/sv_interface_port_array_modport_restrict_fail.json b/ivtest/vvp_tests/sv_interface_port_array_modport_restrict_fail.json new file mode 100644 index 000000000..262a5e80a --- /dev/null +++ b/ivtest/vvp_tests/sv_interface_port_array_modport_restrict_fail.json @@ -0,0 +1,6 @@ +{ + "type" : "CE", + "source" : "sv_interface_port_array_modport_restrict_fail.v", + "gold" : "sv_interface_port_array_modport_restrict_fail", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_interface_port_array_size_mismatch_fail.json b/ivtest/vvp_tests/sv_interface_port_array_size_mismatch_fail.json new file mode 100644 index 000000000..2e9c815f8 --- /dev/null +++ b/ivtest/vvp_tests/sv_interface_port_array_size_mismatch_fail.json @@ -0,0 +1,6 @@ +{ + "type" : "CE", + "source" : "sv_interface_port_array_size_mismatch_fail.v", + "gold" : "sv_interface_port_array_size_mismatch_fail", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_interface_port_basic.json b/ivtest/vvp_tests/sv_interface_port_basic.json new file mode 100644 index 000000000..90c5f7477 --- /dev/null +++ b/ivtest/vvp_tests/sv_interface_port_basic.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_interface_port_basic.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "Interfaces are not supported", + "type" : "TE" + } +} diff --git a/ivtest/vvp_tests/sv_interface_port_forwarding.json b/ivtest/vvp_tests/sv_interface_port_forwarding.json new file mode 100644 index 000000000..d9b785c3f --- /dev/null +++ b/ivtest/vvp_tests/sv_interface_port_forwarding.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_interface_port_forwarding.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "Interfaces are not supported", + "type" : "TE" + } +} diff --git a/ivtest/vvp_tests/sv_interface_port_forwarding_restrict_fail.json b/ivtest/vvp_tests/sv_interface_port_forwarding_restrict_fail.json new file mode 100644 index 000000000..96d4040ef --- /dev/null +++ b/ivtest/vvp_tests/sv_interface_port_forwarding_restrict_fail.json @@ -0,0 +1,6 @@ +{ + "type" : "CE", + "source" : "sv_interface_port_forwarding_restrict_fail.v", + "gold" : "sv_interface_port_forwarding_restrict_fail", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_interface_port_indexed_actual.json b/ivtest/vvp_tests/sv_interface_port_indexed_actual.json new file mode 100644 index 000000000..7b6538549 --- /dev/null +++ b/ivtest/vvp_tests/sv_interface_port_indexed_actual.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_interface_port_indexed_actual.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "Interfaces are not supported", + "type" : "TE" + } +} diff --git a/ivtest/vvp_tests/sv_interface_port_indexed_actual_generate.json b/ivtest/vvp_tests/sv_interface_port_indexed_actual_generate.json new file mode 100644 index 000000000..78951ccc0 --- /dev/null +++ b/ivtest/vvp_tests/sv_interface_port_indexed_actual_generate.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_interface_port_indexed_actual_generate.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "Generate and net arrays are not supported", + "type" : "CE" + } +} diff --git a/ivtest/vvp_tests/sv_interface_port_missing_modport_fail.json b/ivtest/vvp_tests/sv_interface_port_missing_modport_fail.json new file mode 100644 index 000000000..86f475edc --- /dev/null +++ b/ivtest/vvp_tests/sv_interface_port_missing_modport_fail.json @@ -0,0 +1,6 @@ +{ + "type" : "CE", + "source" : "sv_interface_port_missing_modport_fail.v", + "gold" : "sv_interface_port_missing_modport_fail", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_interface_port_missing_type_fail.json b/ivtest/vvp_tests/sv_interface_port_missing_type_fail.json new file mode 100644 index 000000000..bc986c918 --- /dev/null +++ b/ivtest/vvp_tests/sv_interface_port_missing_type_fail.json @@ -0,0 +1,6 @@ +{ + "type" : "CE", + "source" : "sv_interface_port_missing_type_fail.v", + "gold" : "sv_interface_port_missing_type_fail", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_interface_port_modport_input_write_fail.json b/ivtest/vvp_tests/sv_interface_port_modport_input_write_fail.json new file mode 100644 index 000000000..401281de9 --- /dev/null +++ b/ivtest/vvp_tests/sv_interface_port_modport_input_write_fail.json @@ -0,0 +1,6 @@ +{ + "type" : "CE", + "source" : "sv_interface_port_modport_input_write_fail.v", + "gold" : "sv_interface_port_modport_input_write_fail", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_interface_port_non_interface_actual_fail.json b/ivtest/vvp_tests/sv_interface_port_non_interface_actual_fail.json new file mode 100644 index 000000000..0fbfdea28 --- /dev/null +++ b/ivtest/vvp_tests/sv_interface_port_non_interface_actual_fail.json @@ -0,0 +1,6 @@ +{ + "type" : "CE", + "source" : "sv_interface_port_non_interface_actual_fail.v", + "gold" : "sv_interface_port_non_interface_actual_fail", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_interface_port_plain_ansi_regression.json b/ivtest/vvp_tests/sv_interface_port_plain_ansi_regression.json new file mode 100644 index 000000000..89a8d8039 --- /dev/null +++ b/ivtest/vvp_tests/sv_interface_port_plain_ansi_regression.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_interface_port_plain_ansi_regression.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_interface_port_positional.json b/ivtest/vvp_tests/sv_interface_port_positional.json new file mode 100644 index 000000000..ec9124164 --- /dev/null +++ b/ivtest/vvp_tests/sv_interface_port_positional.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_interface_port_positional.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "Interfaces are not supported", + "type" : "TE" + } +} diff --git a/ivtest/vvp_tests/sv_interface_port_positional_unconnected_fail.json b/ivtest/vvp_tests/sv_interface_port_positional_unconnected_fail.json new file mode 100644 index 000000000..6403f0a87 --- /dev/null +++ b/ivtest/vvp_tests/sv_interface_port_positional_unconnected_fail.json @@ -0,0 +1,6 @@ +{ + "type" : "CE", + "source" : "sv_interface_port_positional_unconnected_fail.v", + "gold" : "sv_interface_port_positional_unconnected_fail", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_interface_port_typedef_ansi_regression.json b/ivtest/vvp_tests/sv_interface_port_typedef_ansi_regression.json new file mode 100644 index 000000000..ea864c616 --- /dev/null +++ b/ivtest/vvp_tests/sv_interface_port_typedef_ansi_regression.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_interface_port_typedef_ansi_regression.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_interface_port_unlisted_member_fail.json b/ivtest/vvp_tests/sv_interface_port_unlisted_member_fail.json new file mode 100644 index 000000000..880858381 --- /dev/null +++ b/ivtest/vvp_tests/sv_interface_port_unlisted_member_fail.json @@ -0,0 +1,6 @@ +{ + "type" : "CE", + "source" : "sv_interface_port_unlisted_member_fail.v", + "gold" : "sv_interface_port_unlisted_member_fail", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_interface_port_unmodported_basic.json b/ivtest/vvp_tests/sv_interface_port_unmodported_basic.json new file mode 100644 index 000000000..d52a51216 --- /dev/null +++ b/ivtest/vvp_tests/sv_interface_port_unmodported_basic.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_interface_port_unmodported_basic.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "Interfaces are not supported", + "type" : "TE" + } +} diff --git a/ivtest/vvp_tests/sv_interface_port_unmodported_missing_type_fail.json b/ivtest/vvp_tests/sv_interface_port_unmodported_missing_type_fail.json new file mode 100644 index 000000000..e35cde0c3 --- /dev/null +++ b/ivtest/vvp_tests/sv_interface_port_unmodported_missing_type_fail.json @@ -0,0 +1,6 @@ +{ + "type" : "CE", + "source" : "sv_interface_port_unmodported_missing_type_fail.v", + "gold" : "sv_interface_port_unmodported_missing_type_fail", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_interface_port_wildcard.json b/ivtest/vvp_tests/sv_interface_port_wildcard.json new file mode 100644 index 000000000..d6f8863fe --- /dev/null +++ b/ivtest/vvp_tests/sv_interface_port_wildcard.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_interface_port_wildcard.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "Interfaces are not supported", + "type" : "EF" + } +} diff --git a/ivtest/vvp_tests/sv_interface_port_wrong_type_fail.json b/ivtest/vvp_tests/sv_interface_port_wrong_type_fail.json new file mode 100644 index 000000000..6c3f2096c --- /dev/null +++ b/ivtest/vvp_tests/sv_interface_port_wrong_type_fail.json @@ -0,0 +1,6 @@ +{ + "type" : "CE", + "source" : "sv_interface_port_wrong_type_fail.v", + "gold" : "sv_interface_port_wrong_type_fail", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_lval_concat_class_fail1.json b/ivtest/vvp_tests/sv_lval_concat_class_fail1.json new file mode 100644 index 000000000..40b769246 --- /dev/null +++ b/ivtest/vvp_tests/sv_lval_concat_class_fail1.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_lval_concat_class_fail1.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_lval_concat_class_fail2.json b/ivtest/vvp_tests/sv_lval_concat_class_fail2.json new file mode 100644 index 000000000..803e89d8d --- /dev/null +++ b/ivtest/vvp_tests/sv_lval_concat_class_fail2.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_lval_concat_class_fail2.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_lval_concat_class_fail3.json b/ivtest/vvp_tests/sv_lval_concat_class_fail3.json new file mode 100644 index 000000000..610d6872f --- /dev/null +++ b/ivtest/vvp_tests/sv_lval_concat_class_fail3.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_lval_concat_class_fail3.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_lval_concat_class_fail4.json b/ivtest/vvp_tests/sv_lval_concat_class_fail4.json new file mode 100644 index 000000000..612cc605c --- /dev/null +++ b/ivtest/vvp_tests/sv_lval_concat_class_fail4.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_lval_concat_class_fail4.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_lval_concat_darray_fail1.json b/ivtest/vvp_tests/sv_lval_concat_darray_fail1.json new file mode 100644 index 000000000..8442e431f --- /dev/null +++ b/ivtest/vvp_tests/sv_lval_concat_darray_fail1.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_lval_concat_darray_fail1.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_lval_concat_darray_fail2.json b/ivtest/vvp_tests/sv_lval_concat_darray_fail2.json new file mode 100644 index 000000000..93eb8e0ce --- /dev/null +++ b/ivtest/vvp_tests/sv_lval_concat_darray_fail2.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_lval_concat_darray_fail2.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_lval_concat_darray_fail3.json b/ivtest/vvp_tests/sv_lval_concat_darray_fail3.json new file mode 100644 index 000000000..cf0408a32 --- /dev/null +++ b/ivtest/vvp_tests/sv_lval_concat_darray_fail3.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_lval_concat_darray_fail3.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_lval_concat_darray_fail4.json b/ivtest/vvp_tests/sv_lval_concat_darray_fail4.json new file mode 100644 index 000000000..0d6af611d --- /dev/null +++ b/ivtest/vvp_tests/sv_lval_concat_darray_fail4.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_lval_concat_darray_fail4.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_lval_concat_queue_fail1.json b/ivtest/vvp_tests/sv_lval_concat_queue_fail1.json new file mode 100644 index 000000000..94d535fef --- /dev/null +++ b/ivtest/vvp_tests/sv_lval_concat_queue_fail1.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_lval_concat_queue_fail1.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_lval_concat_queue_fail2.json b/ivtest/vvp_tests/sv_lval_concat_queue_fail2.json new file mode 100644 index 000000000..a53dc3713 --- /dev/null +++ b/ivtest/vvp_tests/sv_lval_concat_queue_fail2.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_lval_concat_queue_fail2.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_lval_concat_queue_fail3.json b/ivtest/vvp_tests/sv_lval_concat_queue_fail3.json new file mode 100644 index 000000000..73844e309 --- /dev/null +++ b/ivtest/vvp_tests/sv_lval_concat_queue_fail3.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_lval_concat_queue_fail3.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_lval_concat_queue_fail4.json b/ivtest/vvp_tests/sv_lval_concat_queue_fail4.json new file mode 100644 index 000000000..4f56bc0bc --- /dev/null +++ b/ivtest/vvp_tests/sv_lval_concat_queue_fail4.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_lval_concat_queue_fail4.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_lval_concat_string_fail1.json b/ivtest/vvp_tests/sv_lval_concat_string_fail1.json new file mode 100644 index 000000000..a357deb9d --- /dev/null +++ b/ivtest/vvp_tests/sv_lval_concat_string_fail1.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_lval_concat_string_fail1.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_lval_concat_string_fail2.json b/ivtest/vvp_tests/sv_lval_concat_string_fail2.json new file mode 100644 index 000000000..fe34900ff --- /dev/null +++ b/ivtest/vvp_tests/sv_lval_concat_string_fail2.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_lval_concat_string_fail2.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_lval_concat_string_fail3.json b/ivtest/vvp_tests/sv_lval_concat_string_fail3.json new file mode 100644 index 000000000..9c7409a3d --- /dev/null +++ b/ivtest/vvp_tests/sv_lval_concat_string_fail3.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_lval_concat_string_fail3.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_lval_concat_string_fail4.json b/ivtest/vvp_tests/sv_lval_concat_string_fail4.json new file mode 100644 index 000000000..0cd79d33d --- /dev/null +++ b/ivtest/vvp_tests/sv_lval_concat_string_fail4.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_lval_concat_string_fail4.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_lval_concat_uarray1.json b/ivtest/vvp_tests/sv_lval_concat_uarray1.json new file mode 100644 index 000000000..96d4aced9 --- /dev/null +++ b/ivtest/vvp_tests/sv_lval_concat_uarray1.json @@ -0,0 +1,4 @@ +{ + "type" : "normal", + "source" : "sv_lval_concat_uarray1.v" +} diff --git a/ivtest/vvp_tests/sv_lval_concat_uarray2.json b/ivtest/vvp_tests/sv_lval_concat_uarray2.json new file mode 100644 index 000000000..c678866fb --- /dev/null +++ b/ivtest/vvp_tests/sv_lval_concat_uarray2.json @@ -0,0 +1,8 @@ +{ + "type" : "normal", + "source" : "sv_lval_concat_uarray2.v", + "vlog95" : { + "__comment" : "Array nets are not supported", + "type" : "CE" + } +} diff --git a/ivtest/vvp_tests/sv_lval_concat_uarray_fail1.json b/ivtest/vvp_tests/sv_lval_concat_uarray_fail1.json new file mode 100644 index 000000000..3b668613d --- /dev/null +++ b/ivtest/vvp_tests/sv_lval_concat_uarray_fail1.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_lval_concat_uarray_fail1.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_lval_concat_uarray_fail2.json b/ivtest/vvp_tests/sv_lval_concat_uarray_fail2.json new file mode 100644 index 000000000..b835f8940 --- /dev/null +++ b/ivtest/vvp_tests/sv_lval_concat_uarray_fail2.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_lval_concat_uarray_fail2.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_lval_concat_uarray_fail3.json b/ivtest/vvp_tests/sv_lval_concat_uarray_fail3.json new file mode 100644 index 000000000..8845375aa --- /dev/null +++ b/ivtest/vvp_tests/sv_lval_concat_uarray_fail3.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_lval_concat_uarray_fail3.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_lval_concat_uarray_fail4.json b/ivtest/vvp_tests/sv_lval_concat_uarray_fail4.json new file mode 100644 index 000000000..15e9eb063 --- /dev/null +++ b/ivtest/vvp_tests/sv_lval_concat_uarray_fail4.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_lval_concat_uarray_fail4.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_mixed_assign2.json b/ivtest/vvp_tests/sv_mixed_assign2.json index 207fb7c8c..82c625110 100644 --- a/ivtest/vvp_tests/sv_mixed_assign2.json +++ b/ivtest/vvp_tests/sv_mixed_assign2.json @@ -1,5 +1,5 @@ { "type" : "NI", - "source" : "sv_mixed_assign1.v", + "source" : "sv_mixed_assign2.v", "iverilog-args" : [ "-g2009" ] } diff --git a/ivtest/vvp_tests/sv_mixed_assign_error2.json b/ivtest/vvp_tests/sv_mixed_assign_error2.json index 967b059f5..8bdd1d9fc 100644 --- a/ivtest/vvp_tests/sv_mixed_assign_error2.json +++ b/ivtest/vvp_tests/sv_mixed_assign_error2.json @@ -1,6 +1,6 @@ { "type" : "CE", - "source" : "sv_mixed_assign_error1.v", - "gold" : "sv_mixed_assign_error1", + "source" : "sv_mixed_assign_error2.v", + "gold" : "sv_mixed_assign_error2", "iverilog-args" : [ "-g2009" ] } diff --git a/ivtest/vvp_tests/sv_mixed_assign_error3.json b/ivtest/vvp_tests/sv_mixed_assign_error3.json index 967b059f5..20387f916 100644 --- a/ivtest/vvp_tests/sv_mixed_assign_error3.json +++ b/ivtest/vvp_tests/sv_mixed_assign_error3.json @@ -1,6 +1,6 @@ { "type" : "CE", - "source" : "sv_mixed_assign_error1.v", - "gold" : "sv_mixed_assign_error1", + "source" : "sv_mixed_assign_error3.v", + "gold" : "sv_mixed_assign_error3", "iverilog-args" : [ "-g2009" ] } diff --git a/ivtest/vvp_tests/sv_mixed_assign_error4.json b/ivtest/vvp_tests/sv_mixed_assign_error4.json index 967b059f5..e4b2da1fd 100644 --- a/ivtest/vvp_tests/sv_mixed_assign_error4.json +++ b/ivtest/vvp_tests/sv_mixed_assign_error4.json @@ -1,6 +1,6 @@ { "type" : "CE", - "source" : "sv_mixed_assign_error1.v", - "gold" : "sv_mixed_assign_error1", + "source" : "sv_mixed_assign_error4.v", + "gold" : "sv_mixed_assign_error4", "iverilog-args" : [ "-g2009" ] } diff --git a/ivtest/vvp_tests/sv_net_array_decl_assign.json b/ivtest/vvp_tests/sv_net_array_decl_assign.json new file mode 100644 index 000000000..7e4cdb535 --- /dev/null +++ b/ivtest/vvp_tests/sv_net_array_decl_assign.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_net_array_decl_assign.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "Array nets are not supported", + "type" : "CE" + } +} diff --git a/ivtest/vvp_tests/sv_net_decl_assign.json b/ivtest/vvp_tests/sv_net_decl_assign.json new file mode 100644 index 000000000..ded9a2672 --- /dev/null +++ b/ivtest/vvp_tests/sv_net_decl_assign.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_net_decl_assign.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_package_lifetime.json b/ivtest/vvp_tests/sv_package_lifetime.json new file mode 100644 index 000000000..1c284869e --- /dev/null +++ b/ivtest/vvp_tests/sv_package_lifetime.json @@ -0,0 +1,8 @@ +{ + "type" : "normal", + "source" : "sv_package_lifetime.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "iverilog-args" : [ "-pallowsigned=1" ] + } +} diff --git a/ivtest/vvp_tests/sv_package_lifetime_fail.json b/ivtest/vvp_tests/sv_package_lifetime_fail.json new file mode 100644 index 000000000..8a0e7f1e4 --- /dev/null +++ b/ivtest/vvp_tests/sv_package_lifetime_fail.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_package_lifetime_fail.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_soft_packed_union.json b/ivtest/vvp_tests/sv_soft_packed_union.json new file mode 100644 index 000000000..073a76414 --- /dev/null +++ b/ivtest/vvp_tests/sv_soft_packed_union.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_soft_packed_union.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_soft_packed_union_fail1.json b/ivtest/vvp_tests/sv_soft_packed_union_fail1.json new file mode 100644 index 000000000..bd50b1e04 --- /dev/null +++ b/ivtest/vvp_tests/sv_soft_packed_union_fail1.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_soft_packed_union_fail1.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_super_member_fail.json b/ivtest/vvp_tests/sv_super_member_fail.json new file mode 100644 index 000000000..14a7e7d70 --- /dev/null +++ b/ivtest/vvp_tests/sv_super_member_fail.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_super_member_fail.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_class1.json b/ivtest/vvp_tests/sv_type_param_restrict_class1.json new file mode 100644 index 000000000..333ccba29 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_class1.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_type_param_restrict_class1.v", + "iverilog-args" : [ "-g2023" ], + "vlog95" : { + "__comment" : "Classes are not supported", + "type" : "CE" + } +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_class2.json b/ivtest/vvp_tests/sv_type_param_restrict_class2.json new file mode 100644 index 000000000..f9e01d0f3 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_class2.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_type_param_restrict_class2.v", + "iverilog-args" : [ "-g2023" ], + "vlog95" : { + "__comment" : "Classes are not supported", + "type" : "CE" + } +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_class_fail1.json b/ivtest/vvp_tests/sv_type_param_restrict_class_fail1.json new file mode 100644 index 000000000..37ad86428 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_class_fail1.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_type_param_restrict_class_fail1.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_class_fail2.json b/ivtest/vvp_tests/sv_type_param_restrict_class_fail2.json new file mode 100644 index 000000000..3777c906f --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_class_fail2.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_type_param_restrict_class_fail2.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_enum1.json b/ivtest/vvp_tests/sv_type_param_restrict_enum1.json new file mode 100644 index 000000000..f06dd96db --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_enum1.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_type_param_restrict_enum1.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_enum2.json b/ivtest/vvp_tests/sv_type_param_restrict_enum2.json new file mode 100644 index 000000000..cefdc3f87 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_enum2.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_type_param_restrict_enum2.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_enum_fail1.json b/ivtest/vvp_tests/sv_type_param_restrict_enum_fail1.json new file mode 100644 index 000000000..1f65e7c27 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_enum_fail1.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_type_param_restrict_enum_fail1.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_enum_fail2.json b/ivtest/vvp_tests/sv_type_param_restrict_enum_fail2.json new file mode 100644 index 000000000..419f415d5 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_enum_fail2.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_type_param_restrict_enum_fail2.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_struct1.json b/ivtest/vvp_tests/sv_type_param_restrict_struct1.json new file mode 100644 index 000000000..fc0aa3d09 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_struct1.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_type_param_restrict_struct1.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_struct2.json b/ivtest/vvp_tests/sv_type_param_restrict_struct2.json new file mode 100644 index 000000000..adb31537f --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_struct2.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_type_param_restrict_struct2.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_struct_fail1.json b/ivtest/vvp_tests/sv_type_param_restrict_struct_fail1.json new file mode 100644 index 000000000..f8cd7c732 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_struct_fail1.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_type_param_restrict_struct_fail1.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_struct_fail2.json b/ivtest/vvp_tests/sv_type_param_restrict_struct_fail2.json new file mode 100644 index 000000000..4bc7cae76 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_struct_fail2.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_type_param_restrict_struct_fail2.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_union1.json b/ivtest/vvp_tests/sv_type_param_restrict_union1.json new file mode 100644 index 000000000..642b76ba5 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_union1.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_type_param_restrict_union1.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_union2.json b/ivtest/vvp_tests/sv_type_param_restrict_union2.json new file mode 100644 index 000000000..b804064d0 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_union2.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_type_param_restrict_union2.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_union_fail1.json b/ivtest/vvp_tests/sv_type_param_restrict_union_fail1.json new file mode 100644 index 000000000..bb2ea1054 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_union_fail1.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_type_param_restrict_union_fail1.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_union_fail2.json b/ivtest/vvp_tests/sv_type_param_restrict_union_fail2.json new file mode 100644 index 000000000..49cc68e0b --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_union_fail2.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_type_param_restrict_union_fail2.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/lexor.lex b/lexor.lex index 8f6c87a4b..7c62f92eb 100644 --- a/lexor.lex +++ b/lexor.lex @@ -4,7 +4,7 @@ %{ /* - * Copyright (c) 1998-2025 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -120,6 +120,8 @@ static list keyword_mask_stack; static int comment_enter; static bool in_module = false; static bool in_UDP = false; +static bool in_module_port_list = false; +static bool module_port_list_start = false; bool in_celldefine = false; UCDriveType uc_drive = UCD_NONE; static int ts_state = 0; @@ -139,6 +141,12 @@ void lex_in_package_scope(PPackage*pkg) in_package_scope = pkg; } +void lex_in_module_port_list(bool flag) +{ + in_module_port_list = flag; + module_port_list_start = flag; +} + %} %x CCOMMENT @@ -160,6 +168,7 @@ void lex_in_package_scope(PPackage*pkg) %x REAL_SCALE W [ \t\b\f\r]+ +ID [a-zA-Z_][a-zA-Z0-9$_]* S [afpnumkKMGT] @@ -335,7 +344,7 @@ TU [munpf] "z0" { return K_edge_descriptor; } "z1" { return K_edge_descriptor; } -[a-zA-Z_][a-zA-Z0-9$_]* { +{ID} { int rc = lexor_keyword_code(yytext, yyleng); switch (rc) { case IDENTIFIER: @@ -417,6 +426,13 @@ TU [munpf] } } + /* If this identifier names a previously declared interface, then + return this as an INTERFACE_IDENTIFIER instead. */ + if (rc == IDENTIFIER && gn_system_verilog()) { + if (pform_test_interface_identifier(yylval.text)) + rc = INTERFACE_IDENTIFIER; + } + /* If this identifier names a previously declared type, then return this as a TYPE_IDENTIFIER instead. */ if (rc == IDENTIFIER && gn_system_verilog()) { @@ -427,6 +443,22 @@ TU [munpf] } } + if (rc == IDENTIFIER && gn_system_verilog() && + in_module_port_list && module_port_list_start) { + char save_ch = *yy_c_buf_p; + *yy_c_buf_p = yy_hold_char; + const char*cp = yy_c_buf_p; + while (*cp == ' ' || *cp == '\t' || *cp == '\b' || + *cp == '\f' || *cp == '\r' || *cp == '\n') + cp += 1; + if (*cp == '.' || isalpha(static_cast(*cp)) || + *cp == '_' || *cp == '\\') + rc = INTERFACE_IDENTIFIER; + *yy_c_buf_p = save_ch; + } + + if (in_module_port_list) + module_port_list_start = false; return rc; } @@ -442,6 +474,10 @@ TU [munpf] return PACKAGE_IDENTIFIER; } } + if (gn_system_verilog()) { + if (pform_test_interface_identifier(yylval.text)) + return INTERFACE_IDENTIFIER; + } if (gn_system_verilog()) { if (typedef_t*type = pform_test_type_identifier(yylloc, yylval.text)) { yylval.type_identifier.text = yylval.text; @@ -753,7 +789,9 @@ TU [munpf] |GN_KEYWORDS_1364_2005 |GN_KEYWORDS_1800_2005 |GN_KEYWORDS_1800_2009; - } else if (strcmp(word,"1800-2012") == 0) { + } else if (strcmp(word,"1800-2012") == 0 + || strcmp(word,"1800-2017") == 0 + || strcmp(word,"1800-2023") == 0) { lexor_keyword_mask = GN_KEYWORDS_1364_1995 |GN_KEYWORDS_1364_2001 |GN_KEYWORDS_1364_2001_CONFIG @@ -895,7 +933,16 @@ TU [munpf] `{W} { VLerror(yylloc, "error: Stray tic (`) here. Perhaps you put white " "space between the tic and preprocessor directive?"); } -. { return yytext[0]; } +. { + if (in_module_port_list) { + if (yytext[0] == '(' || yytext[0] == ',') + module_port_list_start = true; + else if (yytext[0] != ')' && yytext[0] != '[' && + yytext[0] != ']' && yytext[0] != ':') + module_port_list_start = false; + } + return yytext[0]; +} /* Final catchall. something got lost or mishandled. */ /* XXX Should we tell the user something about the lexical state? */ diff --git a/m4/_ac_am_config_header_hook.m4 b/m4/_ac_am_config_header_hook.m4 new file mode 100644 index 000000000..b0113a7eb --- /dev/null +++ b/m4/_ac_am_config_header_hook.m4 @@ -0,0 +1,13 @@ +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp file name are based on the header name. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[ +_config_header=$1 +_stamp_name=stamp-`expr //$_config_header : '.*/\([[^./]]*\)\.[[^./]]*$'`-h +echo "timestamp for $_config_header" > `AS_DIRNAME(["$_config_header"])`/[]$_stamp_name +]) #_AC_AM_CONFIG_HEADER_HOOK diff --git a/main.cc b/main.cc index a1f5ef1db..917e006e9 100644 --- a/main.cc +++ b/main.cc @@ -323,6 +323,12 @@ static void process_generation_flag(const char*gen) } else if (strcmp(gen,"2012") == 0) { generation_flag = GN_VER2012; + } else if (strcmp(gen,"2017") == 0) { + generation_flag = GN_VER2017; + + } else if (strcmp(gen,"2023") == 0) { + generation_flag = GN_VER2023; + } else if (strcmp(gen,"icarus-misc") == 0) { gn_icarus_misc_flag = true; @@ -1058,6 +1064,8 @@ int main(int argc, char*argv[]) lexor_keyword_mask = 0; switch (generation_flag) { + case GN_VER2023: + case GN_VER2017: case GN_VER2012: lexor_keyword_mask |= GN_KEYWORDS_1800_2012; // fallthrough @@ -1113,6 +1121,12 @@ int main(int argc, char*argv[]) case GN_VER2012: cout << "IEEE1800-2012"; break; + case GN_VER2017: + cout << "IEEE1800-2017"; + break; + case GN_VER2023: + cout << "IEEE1800-2023"; + break; } if (gn_verilog_ams_flag) diff --git a/net_design.cc b/net_design.cc index ab1002323..0491457b9 100644 --- a/net_design.cc +++ b/net_design.cc @@ -838,6 +838,16 @@ void NetScope::evaluate_type_parameter_(Design *des, param_ref_t cur) data_type_t *ptype = type_expr->get_type(); NetScope *type_scope = cur->second.val_scope; cur->second.ivl_type = ptype->elaborate_type(des, type_scope); + if (!cur->second.ivl_type) + return; + + if (!cur->second.type_restrict.matches(cur->second.ivl_type)) { + cerr << type_expr->get_fileline() << ": error: " + << "Type parameter `" << cur->first << "` expects a `" + << cur->second.type_restrict << "` type, got `" + << *cur->second.ivl_type << "`." << endl; + des->errors++; + } } void NetScope::evaluate_parameter_(Design*des, param_ref_t cur) diff --git a/net_event.cc b/net_event.cc index 2808b7c66..1f5984387 100644 --- a/net_event.cc +++ b/net_event.cc @@ -407,7 +407,6 @@ NetEvWait::~NetEvWait() tmp->next = tmp->next->next; delete tmp; } - delete tgt; } events_.clear(); } diff --git a/net_func.cc b/net_func.cc index 1bd714aa4..755be3ec8 100644 --- a/net_func.cc +++ b/net_func.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2025 Stephen Williams (steve@icarus.com) + * Copyright (c) 2002-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -41,8 +41,7 @@ NetUserFunc::NetUserFunc(NetScope*s, perm_string n, NetScope*d, for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) { pin(idx).set_dir(Link::INPUT); - pin(idx).drive0(IVL_DR_HiZ); - pin(idx).drive1(IVL_DR_HiZ); + pin(idx).drive(drive_strength_t::hiz); } } @@ -103,8 +102,7 @@ NetSysFunc::NetSysFunc(NetScope*s, perm_string n, for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) { pin(idx).set_dir(Link::INPUT); - pin(idx).drive0(IVL_DR_HiZ); - pin(idx).drive1(IVL_DR_HiZ); + pin(idx).drive(drive_strength_t::hiz); } } diff --git a/net_func_eval.cc b/net_func_eval.cc index 19327ea27..c116d0043 100644 --- a/net_func_eval.cc +++ b/net_func_eval.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2025 Stephen Williams (steve@icarus.com) + * Copyright (c) 2012-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -525,7 +525,7 @@ bool NetBlock::evaluate_function(const LineInfo&loc, map&use_context_map = use_local_context_map? local_context_map : context_map; bool flag = true; - NetProc*cur = last_; + const NetProc*cur = last_; do { cur = cur->next_; if (debug_eval_tree) { diff --git a/net_link.cc b/net_link.cc index 039428ae9..df28aaef9 100644 --- a/net_link.cc +++ b/net_link.cc @@ -164,25 +164,26 @@ Link::DIR Link::get_dir() const return dir_; } -void Link::drivers_delays(const NetExpr*rise, const NetExpr*fall, const NetExpr*decay) +void Link::drivers_delays(const delay_exprs_t &delays) { - find_nexus_()->drivers_delays(rise, fall, decay); + find_nexus_()->drivers_delays(delays); } -void Link::drivers_drive(ivl_drive_t drive0__, ivl_drive_t drive1__) +void Link::drivers_drive(const drive_strength_t &drive_i) { - find_nexus_()->drivers_drive(drive0__, drive1__); + find_nexus_()->drivers_drive(drive_i); } -void Link::drive0(ivl_drive_t str) +void Link::drive(const drive_strength_t &drive_i) { - drive0_ = str; + drive0_ = drive_i.drive0; + drive1_ = drive_i.drive1; } -void Link::drive1(ivl_drive_t str) +drive_strength_t Link::drive() const { - drive1_ = str; + return drive_strength_t(drive0_, drive1_); } ivl_drive_t Link::drive0() const @@ -358,7 +359,7 @@ bool Nexus::drivers_present() const return false; } -void Nexus::drivers_delays(const NetExpr*rise, const NetExpr*fall, const NetExpr*decay) +void Nexus::drivers_delays(const delay_exprs_t &delays) { for (Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) { if (cur->get_dir() != Link::OUTPUT) @@ -368,20 +369,17 @@ void Nexus::drivers_delays(const NetExpr*rise, const NetExpr*fall, const NetExpr if (obj == 0) continue; - obj->rise_time(rise); - obj->fall_time(fall); - obj->decay_time(decay); + obj->delay_times(delays); } } -void Nexus::drivers_drive(ivl_drive_t drive0, ivl_drive_t drive1) +void Nexus::drivers_drive(const drive_strength_t &drive) { for (Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) { if (cur->get_dir() != Link::OUTPUT) continue; - cur->drive0(drive0); - cur->drive1(drive1); + cur->drive(drive); } } diff --git a/net_scope.cc b/net_scope.cc index d90b49b82..cd9e923d0 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -239,16 +239,16 @@ void NetScope::add_typedefs(const map*typedefs) typedefs_ = *typedefs; } -NetScope*NetScope::find_typedef_scope(const Design*des, const typedef_t*type) +NetScope*NetScope::find_typedef_scope(const Design*des, const typedef_t*type_i) { - ivl_assert(*this, type); + ivl_assert(*this, type_i); NetScope *cur_scope = this; while (cur_scope) { - auto it = cur_scope->typedefs_.find(type->name); - if (it != cur_scope->typedefs_.end() && it->second == type) + auto it = cur_scope->typedefs_.find(type_i->name); + if (it != cur_scope->typedefs_.end() && it->second == type_i) return cur_scope; - NetScope*import_scope = cur_scope->find_import(des, type->name); + NetScope*import_scope = cur_scope->find_import(des, type_i->name); if (import_scope) cur_scope = import_scope; else if (cur_scope == unit_) @@ -281,6 +281,7 @@ void NetScope::set_parameter(perm_string key, bool is_annotatable, ref.local_flag = param.local_flag; ref.overridable = param.overridable; ref.type_flag = param.type_flag; + ref.type_restrict = param.type_restrict; ref.lexical_pos = param.lexical_pos; ivl_assert(param, !ref.range); ref.range = range_list; @@ -812,6 +813,60 @@ const NetScope* NetScope::child(const hname_t&name) const return cur->second; } +void NetScope::add_interface_port_alias(perm_string formal_name, + NetScope*actual_scope, + const PModport*modport) +{ + ivl_assert(*this, actual_scope); + interface_port_aliases_[formal_name] = interface_port_alias_t(actual_scope, modport); +} + +const NetScope::interface_port_alias_t* +NetScope::find_interface_port_alias(perm_string formal_name) const +{ + map::const_iterator cur; + cur = interface_port_aliases_.find(formal_name); + if (cur == interface_port_aliases_.end()) + return 0; + + return &cur->second; +} + +void NetScope::add_interface_port_alias_element(perm_string formal_name, + long index, + NetScope*actual_scope, + const PModport*modport) +{ + ivl_assert(*this, actual_scope); + interface_port_alias_arrays_[formal_name][index] = + interface_port_alias_t(actual_scope, modport); +} + +const NetScope::interface_port_alias_t* +NetScope::find_interface_port_alias_element(perm_string formal_name, + long index) const +{ + auto arr = interface_port_alias_arrays_.find(formal_name); + if (arr == interface_port_alias_arrays_.end()) + return 0; + + auto cur = arr->second.find(index); + if (cur == arr->second.end()) + return 0; + + return &cur->second; +} + +const map* +NetScope::find_interface_port_alias_array(perm_string formal_name) const +{ + auto cur = interface_port_alias_arrays_.find(formal_name); + if (cur == interface_port_alias_arrays_.end()) + return 0; + + return &cur->second; +} + /* Helper function to see if the given scope is defined in a class and if * so return the class scope. */ const NetScope* NetScope::get_class_scope() const @@ -867,6 +922,10 @@ bool NetScope::symbol_exists(perm_string sym) return true; if (find_event(sym)) return true; + if (find_interface_port_alias(sym)) + return true; + if (find_interface_port_alias_array(sym)) + return true; return false; } diff --git a/netlist.cc b/netlist.cc index 906708bcf..dd7b4c261 100644 --- a/netlist.cc +++ b/netlist.cc @@ -40,6 +40,8 @@ using namespace std; +const drive_strength_t drive_strength_t::hiz(IVL_DR_HiZ, IVL_DR_HiZ); + ostream& operator<< (ostream&o, NetNet::Type t) { switch (t) { @@ -237,7 +239,7 @@ bool NetPins::is_linked(void) const } NetObj::NetObj(NetScope*s, perm_string n, unsigned np) -: NetPins(np), scope_(s), name_(n), delay1_(0), delay2_(0), delay3_(0) +: NetPins(np), scope_(s), name_(n), delays_() { /* Don't ivl_assert(*this, np > 0); @@ -260,6 +262,11 @@ const NetScope* NetObj::scope() const return scope_; } +void NetObj::delay_times(const delay_exprs_t &delays) +{ + delays_ = delays; +} + NetNode::NetNode(NetScope*s, perm_string n, unsigned npins) : NetObj(s, n, npins), node_next_(0), node_prev_(0), design_(0) { diff --git a/netlist.h b/netlist.h index d1eb80764..86bfb9b73 100644 --- a/netlist.h +++ b/netlist.h @@ -79,6 +79,7 @@ class NetEvWait; class PClass; class PExpr; class PFunction; +class PModport; class PPackage; class PTaskFunc; class PWire; @@ -102,6 +103,42 @@ struct functor_t; # define ENUM_UNSIGNED_INT #endif +struct drive_strength_t { + static const drive_strength_t hiz; + + explicit drive_strength_t(ivl_drive_t d0 = IVL_DR_STRONG, + ivl_drive_t d1 = IVL_DR_STRONG) + : drive0(d0), drive1(d1) + { } + + bool has_drive() const + { + return drive0 != IVL_DR_STRONG || drive1 != IVL_DR_STRONG; + } + + ivl_drive_t drive0; + ivl_drive_t drive1; +}; + +struct delay_exprs_t { + explicit delay_exprs_t(const NetExpr *r = nullptr, + const NetExpr *f = nullptr, + const NetExpr *d = nullptr) + : rise(r), fall(f), decay(d) + { } + + bool has_delay() const + { + return rise || fall || decay; + } + + const NetExpr *rise; + const NetExpr *fall; + const NetExpr *decay; +}; + +std::ostream &operator << (std::ostream &o, const drive_strength_t &strength); +std::ostream &operator << (std::ostream &o, const delay_exprs_t &delays); std::ostream& operator << (std::ostream&o, ivl_variable_type_t val); extern void join_island(NetPins*obj); @@ -125,17 +162,17 @@ class Link { DIR get_dir() const; // Set the delay for all the drivers to this nexus. - void drivers_delays(const NetExpr*rise, const NetExpr*fall, const NetExpr*decay); + void drivers_delays(const delay_exprs_t &delays); // A link has a drive strength for 0 and 1 values. The drive0 // strength is for when the link has the value 0, and drive1 // strength is for when the link has a value 1. - void drive0(ivl_drive_t); - void drive1(ivl_drive_t); + void drive(const drive_strength_t &drive_i); + drive_strength_t drive() const; // This sets the drives for all drivers of this link, and not // just the current link. - void drivers_drive(ivl_drive_t d0, ivl_drive_t d1); + void drivers_drive(const drive_strength_t &drive_i); ivl_drive_t drive0() const; ivl_drive_t drive1() const; @@ -268,13 +305,15 @@ class NetObj : public NetPins, public Attrib { perm_string name() const { return name_; } void rename(perm_string n) { name_ = n; } - const NetExpr* rise_time() const { return delay1_; } - const NetExpr* fall_time() const { return delay2_; } - const NetExpr* decay_time() const { return delay3_; } + const NetExpr *rise_time() const { return delays_.rise; } + const NetExpr *fall_time() const { return delays_.fall; } + const NetExpr *decay_time() const { return delays_.decay; } + const delay_exprs_t &delay_times() const + { + return delays_; + } - void rise_time(const NetExpr* d) { delay1_ = d; } - void fall_time(const NetExpr* d) { delay2_ = d; } - void decay_time(const NetExpr* d) { delay3_ = d; } + void delay_times(const delay_exprs_t &delays); void dump_obj_attr(std::ostream&, unsigned) const; @@ -283,9 +322,7 @@ class NetObj : public NetPins, public Attrib { private: NetScope*scope_; perm_string name_; - const NetExpr* delay1_; - const NetExpr* delay2_; - const NetExpr* delay3_; + delay_exprs_t delays_; }; /* @@ -373,8 +410,8 @@ class Nexus { const char* name() const; - void drivers_delays(const NetExpr*rise, const NetExpr*fall, const NetExpr*decay); - void drivers_drive(ivl_drive_t d0, ivl_drive_t d1); + void drivers_delays(const delay_exprs_t &delays); + void drivers_drive(const drive_strength_t &drive); Link*first_nlink(); const Link* first_nlink()const; @@ -970,7 +1007,7 @@ class NetScope : public Definitions, public Attrib { void add_typedefs(const std::map*typedefs); /* Search the scope hierarchy for the scope where 'type' was defined. */ - NetScope*find_typedef_scope(const Design*des, const typedef_t*type); + NetScope*find_typedef_scope(const Design*des, const typedef_t*type_i); /* Parameters exist within a scope, and these methods allow one to manipulate the set. In these cases, the name is the @@ -1043,6 +1080,31 @@ class NetScope : public Definitions, public Attrib { const NetScope* parent() const { return up_; } const NetScope* child(const hname_t&name) const; + struct interface_port_alias_t { + interface_port_alias_t() : actual_scope(nullptr), modport(nullptr) { } + interface_port_alias_t(NetScope*actual, const PModport*mp) + : actual_scope(actual), modport(mp) { } + + NetScope*actual_scope; + const PModport*modport; + }; + + /* Interface-typed module formals are represented as aliases to + concrete interface instance scopes. These are deliberately kept + out of the real child-scope map; only alias-aware lookup paths + should traverse them. */ + void add_interface_port_alias(perm_string formal_name, + NetScope*actual_scope, + const PModport*modport); + const interface_port_alias_t* find_interface_port_alias(perm_string formal_name) const; + void add_interface_port_alias_element(perm_string formal_name, + long index, + NetScope*actual_scope, + const PModport*modport); + const interface_port_alias_t* find_interface_port_alias_element(perm_string formal_name, + long index) const; + const std::map* find_interface_port_alias_array(perm_string formal_name) const; + /* A helper function to find the enclosing class scope. */ const NetScope* get_class_scope() const; @@ -1253,6 +1315,8 @@ class NetScope : public Definitions, public Attrib { bool overridable = false; // Is it a type parameter bool type_flag = false; + // Type restriction for a type parameter + type_restrict_t type_restrict; // The lexical position of the declaration unsigned lexical_pos = 0; // range constraints @@ -1347,6 +1411,8 @@ class NetScope : public Definitions, public Attrib { NetScope*unit_; NetScope*up_; std::map children_; + std::map interface_port_aliases_; + std::map > interface_port_alias_arrays_; unsigned lcounter_; bool need_const_func_, is_const_func_, is_auto_, is_cell_, calls_stask_; diff --git a/netmisc.cc b/netmisc.cc index d2ca275fa..13c466e61 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2025 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -509,8 +509,15 @@ void indices_to_expressions(Design*des, NetScope*scope, NetExpr*word_index = elab_and_eval(des, scope, cur->msb, -1, need_const); - if (word_index == 0) + if (!word_index) { flags.invalid = true; + } else if (word_index->expr_type() == IVL_VT_REAL) { + cerr << cur->msb->get_fileline() << ": error: " + << "Array index expression cannot be a real value." + << endl; + des->errors += 1; + flags.invalid = true; + } // Track if we detect any non-constant expressions // here. This may allow for a special case. @@ -1629,6 +1636,8 @@ NetExpr*collapse_array_indices(Design*des, NetScope*scope, const NetNet*net, static void assign_unpacked_with_bufz_dim(Design *des, NetScope *scope, const LineInfo *loc, NetNet *lval, NetNet *rval, + const drive_strength_t &drive, + const delay_exprs_t &delays, const std::vector &stride, unsigned int dim = 0, unsigned int idx_l = 0, @@ -1671,11 +1680,19 @@ static void assign_unpacked_with_bufz_dim(Design *des, NetScope *scope, driver->set_line(*loc); des->add_node(driver); - connect(lval->pin(idx_l), driver->pin(0)); connect(driver->pin(1), rval->pin(idx_r)); + + if (drive.has_drive()) + driver->pin(0).drive(drive); + + if (delays.has_delay()) + driver->delay_times(delays); + + connect(lval->pin(idx_l), driver->pin(0)); } else { assign_unpacked_with_bufz_dim(des, scope, loc, lval, rval, - stride, dim + 1, idx_l, idx_r); + drive, delays, stride, + dim + 1, idx_l, idx_r); } idx_l += inc_l; @@ -1685,7 +1702,9 @@ static void assign_unpacked_with_bufz_dim(Design *des, NetScope *scope, void assign_unpacked_with_bufz(Design*des, NetScope*scope, const LineInfo*loc, - NetNet*lval, NetNet*rval) + NetNet*lval, NetNet*rval, + const drive_strength_t &drive, + const delay_exprs_t &delays) { ivl_assert(*loc, lval->pin_count()==rval->pin_count()); @@ -1693,7 +1712,8 @@ void assign_unpacked_with_bufz(Design*des, NetScope*scope, vector stride(dims.size()); make_strides(dims, stride); - assign_unpacked_with_bufz_dim(des, scope, loc, lval, rval, stride); + assign_unpacked_with_bufz_dim(des, scope, loc, lval, rval, drive, + delays, stride); } /* diff --git a/netmisc.h b/netmisc.h index be460ad04..ff9edc1ec 100644 --- a/netmisc.h +++ b/netmisc.h @@ -1,7 +1,7 @@ #ifndef IVL_netmisc_H #define IVL_netmisc_H /* - * Copyright (c) 1999-2025 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -50,6 +50,9 @@ struct symbol_search_results { type = 0; eve = 0; decl_after_use = 0; + interface_alias_scope = 0; + interface_alias_target = 0; + interface_alias_modport = 0; } inline bool is_scope() const { @@ -76,6 +79,10 @@ struct symbol_search_results { return "nothing found"; } + inline bool through_interface_alias() const { + return interface_alias_target != 0; + } + // Scope where symbol was located. This is set in all cases, // assuming the search succeeded. NetScope*scope; @@ -93,6 +100,14 @@ struct symbol_search_results { // one is retained. const LineInfo*decl_after_use; + // If lookup traversed an interface-typed formal port alias, these + // fields describe the alias edge. The resolved object remains in the + // normal scope/net/parameter/event fields. + NetScope*interface_alias_scope; + perm_string interface_alias_name; + NetScope*interface_alias_target; + const PModport*interface_alias_modport; + // Store bread crumbs of the search here. The path_tail is the parts // of the original path that were not found, or are after an object // (and so are probably members or methods). @@ -128,6 +143,10 @@ extern bool symbol_search(const LineInfo *li, Design *des, NetScope *scope, const pform_scoped_name_t &path, unsigned lexical_pos, struct symbol_search_results*res); +extern bool check_interface_modport_access(const LineInfo *li, Design *des, + const symbol_search_results &res, + bool is_write); + /* * This function transforms an expression by either zero or sign extending * the high bits until the expression has the desired width. This may mean @@ -473,7 +492,11 @@ extern NetExpr*collapse_array_exprs(Design*des, NetScope*scope, extern void assign_unpacked_with_bufz(Design*des, NetScope*scope, const LineInfo*loc, - NetNet*lval, NetNet*rval); + NetNet*lval, NetNet*rval, + const drive_strength_t &drive = + drive_strength_t(), + const delay_exprs_t &delays = + delay_exprs_t()); extern NetPartSelect* detect_partselect_lval(Link&pin); diff --git a/netstruct.cc b/netstruct.cc index 3c3dc13f7..0c80bd718 100644 --- a/netstruct.cc +++ b/netstruct.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2022 Stephen Williams (steve@icarus.com) + * Copyright (c) 2011-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -26,22 +26,19 @@ using namespace std; -netstruct_t::netstruct_t() -: union_(false), packed_(false), signed_(false) -{ -} - netstruct_t::~netstruct_t() { } -void netstruct_t::union_flag(bool flag) +void netstruct_t::union_flag(bool flag, bool soft) { // This MUST be called before any members are pushed into the // definition. This is because the append relies on this flag // being accurate. ivl_assert(*this, members_.empty()); + ivl_assert(*this, flag || !soft); union_ = flag; + soft_union_ = soft; } void netstruct_t::packed(bool flag) @@ -64,7 +61,7 @@ void netstruct_t::append_member(Design*des, const netstruct_t::member_t&val) des->errors += 1; } } - if (union_ && packed_ && members_.size() > 1) { + if (union_ && packed_ && !soft_union_ && members_.size() > 1) { unsigned long expect_wid = members_.front().net_type->packed_width(); unsigned long got_wid = members_.back().net_type->packed_width(); if (expect_wid != got_wid) { @@ -104,9 +101,20 @@ long netstruct_t::packed_width(void) const // If this is a packed union, then all the members are the // same width, so it is sufficient to return the width of any // single member. - if (union_) + if (union_ && !soft_union_) return members_.front().net_type->packed_width(); + // A soft packed union uses the largest member width. + if (union_ && soft_union_) { + long res = 0; + for (size_t idx = 0 ; idx < members_.size() ; idx += 1) { + long wid = members_[idx].net_type->packed_width(); + if (wid > res) + res = wid; + } + return res; + } + // The width of a packed struct is the sum of member widths. long res = 0; for (size_t idx = 0 ; idx < members_.size() ; idx += 1) diff --git a/netstruct.h b/netstruct.h index 47fe09e30..a0e66fea9 100644 --- a/netstruct.h +++ b/netstruct.h @@ -1,7 +1,7 @@ #ifndef IVL_netstruct_H #define IVL_netstruct_H /* - * Copyright (c) 2011-2025 Stephen Williams (steve@icarus.com) + * Copyright (c) 2011-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -39,14 +39,15 @@ class netstruct_t : public LineInfo, public ivl_type_s { }; public: - netstruct_t(); + netstruct_t() = default; ~netstruct_t() override; // If this is a union (instead of struct) then this flag is // set. We handle union and struct together because they are // so similar. - void union_flag(bool); + void union_flag(bool, bool soft = false); bool union_flag(void) const; + bool soft_union(void) const; void packed(bool flag); bool packed(void) const override; @@ -81,13 +82,15 @@ class netstruct_t : public LineInfo, public ivl_type_s { bool test_equivalence(ivl_type_t that) const override; private: - bool union_; - bool packed_; - bool signed_; + bool union_ = false; + bool soft_union_ = false; + bool packed_ = false; + bool signed_ = false; std::vectormembers_; }; inline bool netstruct_t::union_flag(void) const { return union_; } +inline bool netstruct_t::soft_union(void) const { return soft_union_; } inline bool netstruct_t::packed(void) const { return packed_; } #endif /* IVL_netstruct_H */ diff --git a/parse.y b/parse.y index 4a9274666..667636987 100644 --- a/parse.y +++ b/parse.y @@ -45,6 +45,7 @@ extern void lex_end_table(); static data_type_t* param_data_type = 0; static bool param_is_local = false; static bool param_is_type = false; +static type_restrict_t param_type_restrict; static bool in_gen_region = false; static std::list* specparam_active_range = 0; @@ -100,6 +101,29 @@ static pform_name_t* pform_create_super(void) return res; } +static void check_net_decl_assigns(const struct vlltype&loc, + const std::list*assign_list) +{ + if (gn_system_verilog()) + return; + + bool has_initializer = false; + bool has_no_initializer = false; + + for (const auto*cur : *assign_list) { + if (cur->expr) + has_initializer = true; + else + has_no_initializer = true; + + if (has_initializer && has_no_initializer) { + pform_requires_sv(loc, "Mixing initialized and uninitialized " + "net declaration entries"); + return; + } + } +} + /* The rules sometimes push attributes into a global context where sub-rules may grab them. This makes parser rules a little easier to write in some cases. */ @@ -461,6 +485,32 @@ Module::port_t *module_declare_port(const YYLTYPE&loc, char *id, return port; } +Module::port_t *module_declare_interface_port(const YYLTYPE&loc, char *type, + char *modport, char *id, + std::list *udims, + std::list *attributes) +{ + pform_requires_sv(loc, "Interface port declaration"); + + Module::port_t *port = pform_module_interface_port_reference( + loc, lex_strings.make(type), + modport ? lex_strings.make(modport) : perm_string(), + lex_strings.make(id), udims); + + delete[] type; + if (modport) + delete[] modport; + delete[] id; + + pform_module_define_interface_port(loc, port, attributes); + + port_declaration_context.port_type = NetNet::NOT_A_PORT; + port_declaration_context.port_net_type = NetNet::NONE; + port_declaration_context.data_type = nullptr; + + return port; +} + %} %union { @@ -486,8 +536,6 @@ Module::port_t *module_declare_port(const YYLTYPE&loc, char *id, ivl_discipline_t discipline; - hname_t*hier; - std::list*strings; struct str_pair_t drive; @@ -540,7 +588,6 @@ Module::port_t *module_declare_port(const YYLTYPE&loc, char *id, struct_type_t*struct_type; data_type_t*data_type; - class_type_t*class_type; real_type_t::type_t real_type; property_qualifier_t property_qualifier; PPackage*package; @@ -570,17 +617,15 @@ Module::port_t *module_declare_port(const YYLTYPE&loc, char *id, verireal* realtime; PSpecPath* specpath; - std::list *dimensions; - PTimingCheck::event_t* timing_check_event; PTimingCheck::optional_args_t* spec_optional_args; LexicalScope::lifetime_t lifetime; - enum typedef_t::basic_type typedef_basic_type; + enum type_restrict_t::type_t type_restrict; }; -%token IDENTIFIER SYSTEM_IDENTIFIER STRING TIME_LITERAL +%token IDENTIFIER INTERFACE_IDENTIFIER SYSTEM_IDENTIFIER STRING TIME_LITERAL %token TYPE_IDENTIFIER %token PACKAGE_IDENTIFIER %token DISCIPLINE_IDENTIFIER @@ -685,7 +730,7 @@ Module::port_t *module_declare_port(const YYLTYPE&loc, char *id, %type from_exclude block_item_decls_opt %type number pos_neg_number %type signing unsigned_signed_opt signed_unsigned_opt -%type import_export +%type import_export union_soft_opt %type K_genvar_opt K_static_opt K_virtual_opt K_const_opt %type udp_reg_opt edge_operator %type drive_strength drive_strength_opt dr_strength0 dr_strength1 @@ -698,9 +743,6 @@ Module::port_t *module_declare_port(const YYLTYPE&loc, char *id, %type udp_port_decl udp_port_decls %type udp_initial udp_init_opt -%type net_variable -%type net_variable_list - %type event_variable label_opt class_declaration_endlabel_opt %type block_identifier_opt %type identifier_name @@ -709,9 +751,6 @@ Module::port_t *module_declare_port(const YYLTYPE&loc, char *id, %type loop_variables %type list_of_port_identifiers list_of_variable_port_identifiers -%type net_decl_assigns -%type net_decl_assign - %type port port_opt port_reference port_reference_list %type port_declaration %type list_of_ports module_port_list_opt list_of_port_declarations module_attribute_foreign @@ -758,7 +797,7 @@ Module::port_t *module_declare_port(const YYLTYPE&loc, char *id, %type assignment_pattern expression expression_opt expr_mintypmax %type expr_primary_or_typename expr_primary call_chain_expr %type class_new dynamic_array_new -%type var_decl_initializer_opt initializer_opt +%type net_decl_initializer_opt var_decl_initializer_opt initializer_opt %type inc_or_dec_expression inside_expression lpvalue %type branch_probe_expression streaming_concatenation %type delay_value delay_value_simple @@ -766,8 +805,8 @@ Module::port_t *module_declare_port(const YYLTYPE&loc, char *id, %type expression_list_with_nuls expression_list_proper %type cont_assign cont_assign_list -%type variable_decl_assignment -%type list_of_variable_decl_assignments +%type net_decl_assign variable_decl_assignment +%type net_decl_assigns list_of_variable_decl_assignments %type data_type data_type_opt data_type_or_implicit data_type_or_implicit_or_void %type data_type_or_implicit_no_opt @@ -837,7 +876,7 @@ Module::port_t *module_declare_port(const YYLTYPE&loc, char *id, %type compressed_operator -%type typedef_basic_type +%type forward_type forward_type_without_enum %token K_TAND %nonassoc K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ @@ -1283,22 +1322,24 @@ constraint_set /* IEEE1800-2005 A.1.9 */ ; data_declaration /* IEEE1800-2005: A.2.1.3 */ - : attribute_list_opt K_const_opt data_type list_of_variable_decl_assignments ';' - { data_type_t *data_type = $3; - if (!data_type) { - data_type = new vector_type_t(IVL_VT_LOGIC, false, 0); - FILE_NAME(data_type, @3); - } - pform_makewire(@3, 0, str_strength, $4, NetNet::IMPLICIT_REG, data_type, - $1, $2); - } - | attribute_list_opt K_const_opt K_var data_type_or_implicit list_of_variable_decl_assignments ';' + : attribute_list_opt K_const_opt variable_lifetime_opt data_type list_of_variable_decl_assignments ';' { data_type_t *data_type = $4; + if (!data_type) { + data_type = new vector_type_t(IVL_VT_LOGIC, false, 0); + FILE_NAME(data_type, @4); + } + pform_makewire(@4, 0, str_strength, $5, NetNet::IMPLICIT_REG, data_type, + $1, $2); + var_lifetime = LexicalScope::INHERITED; + } + | attribute_list_opt K_const_opt K_var variable_lifetime_opt data_type_or_implicit list_of_variable_decl_assignments ';' + { data_type_t *data_type = $5; if (!data_type) { data_type = new vector_type_t(IVL_VT_LOGIC, false, 0); FILE_NAME(data_type, @3); } - pform_make_var(@3, $5, data_type, $1, $2); + pform_make_var(@3, $6, data_type, $1, $2); + var_lifetime = LexicalScope::INHERITED; } | attribute_list_opt K_event event_variable_list ';' { if ($3) pform_make_events(@2, $3); @@ -1333,7 +1374,7 @@ packed_array_data_type /* IEEE1800-2005: A.2.2.1 */ : enum_data_type { $$ = $1; } | struct_data_type - { if (!$1->packed_flag) { + { if (!$1->packed_flag && !($1->union_flag && $1->soft_flag)) { yyerror(@1, "sorry: Unpacked structs not supported."); } $$ = $1; @@ -2705,10 +2746,16 @@ variable_dimension /* IEEE1800-2005: A.2.5 */ variable_lifetime_opt : lifetime - { if (pform_requires_sv(@1, "Overriding default variable lifetime") && - $1 != pform_peek_scope()->default_lifetime) { - yyerror(@1, "sorry: Overriding the default variable lifetime " - "is not yet supported."); + { LexicalScope*scope = pform_peek_scope(); + if (dynamic_cast(scope)) { + if ($1 == LexicalScope::AUTOMATIC) { + yyerror(@1, "error: automatic lifetime is not allowed for " + "variables declared in packages."); + } + } else if (pform_requires_sv(@1, "Overriding default variable lifetime") && + $1 != scope->default_lifetime) { + yyerror(@1, "sorry: Overriding the default variable " + "lifetime is not yet supported."); } var_lifetime = $1; } @@ -2853,11 +2900,16 @@ block_item_decls_opt * `typedef enum ` can either be the start of a enum forward * declaration or a enum type declaration with a type identifier as its base * type. And this abmiguity can not be resolved if we reduce the K_enum to - * typedef_basic_type. */ -typedef_basic_type - : K_struct { $$ = typedef_t::STRUCT; } - | K_union { $$ = typedef_t::UNION; } - | K_class { $$ = typedef_t::CLASS; } + * forward_type_without_enum. */ +forward_type_without_enum + : K_struct { $$ = type_restrict_t::STRUCT; } + | K_union { $$ = type_restrict_t::UNION; } + | K_class { $$ = type_restrict_t::CLASS; } + ; + +forward_type + : K_enum { $$ = type_restrict_t::ENUM; } + | forward_type_without_enum ; /* Type declarations are parsed here. The rule actions call pform @@ -2873,17 +2925,17 @@ type_declaration | K_typedef identifier_name ';' { perm_string name = lex_strings.make($2); - pform_forward_typedef(@2, name, typedef_t::ANY); + pform_forward_typedef(@2, name, type_restrict_t(type_restrict_t::ANY)); delete[]$2; } - | K_typedef typedef_basic_type identifier_name ';' + | K_typedef forward_type_without_enum identifier_name ';' { perm_string name = lex_strings.make($3); - pform_forward_typedef(@3, name, $2); + pform_forward_typedef(@3, name, type_restrict_t($2)); delete[]$3; } | K_typedef K_enum identifier_name ';' { perm_string name = lex_strings.make($3); - pform_forward_typedef(@3, name, typedef_t::ENUM); + pform_forward_typedef(@3, name, type_restrict_t(type_restrict_t::ENUM)); delete[]$3; } | K_typedef error ';' @@ -2984,6 +3036,13 @@ packed_signing /* IEEE 1800-2012 A.2.2.1 */ } ; +union_soft_opt + : K_soft + { $$ = true; } + | + { $$ = false; } + ; + struct_data_type /* IEEE 1800-2012 A.2.2.1 */ : K_struct packed_signing '{' struct_union_member_list '}' { struct_type_t*tmp = new struct_type_t; @@ -2991,16 +3050,20 @@ struct_data_type /* IEEE 1800-2012 A.2.2.1 */ tmp->packed_flag = $2.packed_flag; tmp->signed_flag = $2.signed_flag; tmp->union_flag = false; - tmp->members .reset($4); + tmp->soft_flag = false; + tmp->members.reset($4); $$ = tmp; } - | K_union packed_signing '{' struct_union_member_list '}' - { struct_type_t*tmp = new struct_type_t; + | K_union union_soft_opt packed_signing '{' struct_union_member_list '}' + { if ($2 && generation_flag < GN_VER2023) + yyerror(@1, "error: Soft packed unions require SystemVerilog 2023 or later."); + struct_type_t*tmp = new struct_type_t; FILE_NAME(tmp, @1); - tmp->packed_flag = $2.packed_flag; - tmp->signed_flag = $2.signed_flag; + tmp->packed_flag = $3.packed_flag; + tmp->signed_flag = $3.signed_flag; tmp->union_flag = true; - tmp->members .reset($4); + tmp->soft_flag = $2; + tmp->members.reset($5); $$ = tmp; } | K_struct packed_signing '{' error '}' @@ -3011,16 +3074,20 @@ struct_data_type /* IEEE 1800-2012 A.2.2.1 */ tmp->packed_flag = $2.packed_flag; tmp->signed_flag = $2.signed_flag; tmp->union_flag = false; + tmp->soft_flag = false; $$ = tmp; } - | K_union packed_signing '{' error '}' - { yyerror(@3, "error: Errors in union member list."); + | K_union union_soft_opt packed_signing '{' error '}' + { if ($2 && generation_flag < GN_VER2023) + yyerror(@1, "error: Soft packed unions require SystemVerilog 2023 or later."); + yyerror(@4, "error: Errors in union member list."); yyerrok; struct_type_t*tmp = new struct_type_t; FILE_NAME(tmp, @1); - tmp->packed_flag = $2.packed_flag; - tmp->signed_flag = $2.signed_flag; + tmp->packed_flag = $3.packed_flag; + tmp->signed_flag = $3.signed_flag; tmp->union_flag = true; + tmp->soft_flag = $2; $$ = tmp; } ; @@ -4634,10 +4701,20 @@ list_of_port_declarations { std::vector *ports = $1; Module::port_t* port; - port = module_declare_port(@4, $4, port_declaration_context.port_type, - port_declaration_context.port_net_type, - port_declaration_context.data_type, - $5, $6, $3); + if (port_declaration_context.port_type == NetNet::NOT_A_PORT) { + yyerror(@4, "error: Incomplete interface port declaration."); + delete[]$4; + delete $5; + delete $6; + delete $3; + port = 0; + } else { + port = module_declare_port(@4, $4, + port_declaration_context.port_type, + port_declaration_context.port_net_type, + port_declaration_context.data_type, + $5, $6, $3); + } ports->push_back(port); $$ = ports; } @@ -4653,6 +4730,12 @@ port_declaration : attribute_list_opt port_direction net_type_or_var_opt data_type_or_implicit IDENTIFIER dimensions_opt initializer_opt { $$ = module_declare_port(@5, $5, $2, $3, $4, $6, $7, $1); } + | attribute_list_opt INTERFACE_IDENTIFIER '.' IDENTIFIER IDENTIFIER dimensions_opt + { $$ = module_declare_interface_port(@5, $2, $4, $5, $6, $1); + } + | attribute_list_opt INTERFACE_IDENTIFIER IDENTIFIER dimensions_opt + { $$ = module_declare_interface_port(@3, $2, 0, $3, $4, $1); + } | attribute_list_opt net_type_or_var data_type_or_implicit IDENTIFIER dimensions_opt initializer_opt { pform_requires_sv(@4, "Partial ANSI port declaration"); $$ = module_declare_port(@4, $4, port_declaration_context.port_type, @@ -4770,9 +4853,11 @@ module port_declaration_context_init(); } module_package_import_list_opt module_parameter_port_list_opt + { lex_in_module_port_list(true); } module_port_list_opt + { lex_in_module_port_list(false); } module_attribute_foreign ';' - { pform_module_set_ports($8); } + { pform_module_set_ports($9); } timeunits_declaration_opt { pform_set_scope_timescale(@2); } module_item_list_opt @@ -4795,16 +4880,16 @@ module } // Check that program/endprogram and module/endmodule // keywords match. - if ($2 != $15) { + if ($2 != $17) { switch ($2) { case K_module: - yyerror(@15, "error: module not closed by endmodule."); + yyerror(@17, "error: module not closed by endmodule."); break; case K_program: - yyerror(@15, "error: program not closed by endprogram."); + yyerror(@17, "error: program not closed by endprogram."); break; case K_interface: - yyerror(@15, "error: interface not closed by endinterface."); + yyerror(@17, "error: interface not closed by endinterface."); break; default: break; @@ -4820,13 +4905,13 @@ module // module. switch ($2) { case K_module: - check_end_label(@17, "module", $4, $17); + check_end_label(@19, "module", $4, $19); break; case K_program: - check_end_label(@17, "program", $4, $17); + check_end_label(@19, "program", $4, $19); break; case K_interface: - check_end_label(@17, "interface", $4, $17); + check_end_label(@19, "interface", $4, $19); break; default: break; @@ -4901,7 +4986,16 @@ module_parameter_port_list_opt ; type_param - : K_type { param_is_type = true; } + : K_type + { param_is_type = true; + param_type_restrict = {}; + } + | K_type forward_type + { if (generation_flag < GN_VER2023) + yyerror(@1, "error: Restricted type parameters require SystemVerilog 2023 or later."); + param_is_type = true; + param_type_restrict = type_restrict_t($2); + } ; module_parameter @@ -4917,6 +5011,7 @@ module_parameter_port_list { param_data_type = $1; param_is_local = false; param_is_type = false; + param_type_restrict = {}; } parameter_assign { pform_requires_sv(@3, "Omitting initial `parameter` in parameter port " @@ -4932,6 +5027,7 @@ module_parameter_port_list "data type in parameter port list"); param_data_type = $3; param_is_type = false; + param_type_restrict = {}; } } parameter_assign @@ -4943,70 +5039,30 @@ module_item /* Modules can contain further sub-module definitions. */ : module - | attribute_list_opt net_type data_type_or_implicit delay3_opt net_variable_list ';' - - { data_type_t*data_type = $3; - pform_check_net_data_type(@2, $2, $3); - if (data_type == 0) { - data_type = new vector_type_t(IVL_VT_LOGIC, false, 0); - FILE_NAME(data_type, @2); - } - pform_set_data_type(@2, data_type, $5, $2, $1); - if ($4 != 0) { - yyerror(@2, "sorry: Net delays not supported."); - delete $4; - } - delete $1; - } - - | attribute_list_opt K_wreal delay3 net_variable_list ';' - { real_type_t*tmpt = new real_type_t(real_type_t::REAL); - pform_set_data_type(@2, tmpt, $4, NetNet::WIRE, $1); - if ($3 != 0) { - yyerror(@3, "sorry: Net delays not supported."); - delete $3; - } - delete $1; - } - - | attribute_list_opt K_wreal net_variable_list ';' - { real_type_t*tmpt = new real_type_t(real_type_t::REAL); - pform_set_data_type(@2, tmpt, $3, NetNet::WIRE, $1); - delete $1; - } - /* Very similar to the rule above, but this takes a list of net_decl_assigns, which are = assignment declarations. */ - | attribute_list_opt net_type data_type_or_implicit delay3_opt net_decl_assigns ';' - { data_type_t*data_type = $3; - pform_check_net_data_type(@2, $2, $3); + | attribute_list_opt net_type drive_strength_opt data_type_or_implicit delay3_opt net_decl_assigns ';' + { data_type_t*data_type = $4; + pform_check_net_data_type(@2, $2, $4); + check_net_decl_assigns(@6, $6); if (data_type == 0) { data_type = new vector_type_t(IVL_VT_LOGIC, false, 0); FILE_NAME(data_type, @2); } - pform_makewire(@2, $4, str_strength, $5, $2, data_type, $1); + pform_makewire(@2, $5, $3, $6, $2, data_type, $1); delete $1; } - /* This form doesn't have the range, but does have strengths. This - gives strength to the assignment drivers. */ - - | attribute_list_opt net_type data_type_or_implicit drive_strength net_decl_assigns ';' - { data_type_t*data_type = $3; - pform_check_net_data_type(@2, $2, $3); - if (data_type == 0) { - data_type = new vector_type_t(IVL_VT_LOGIC, false, 0); - FILE_NAME(data_type, @2); - } - pform_makewire(@2, 0, $4, $5, $2, data_type, $1); - delete $1; - } - - | attribute_list_opt K_wreal net_decl_assigns ';' + | attribute_list_opt K_wreal delay3_opt net_decl_assigns ';' { real_type_t*data_type = new real_type_t(real_type_t::REAL); - pform_makewire(@2, 0, str_strength, $3, NetNet::WIRE, data_type, $1); + check_net_decl_assigns(@4, $4); + if ($3) { + yyerror(@2, "error: wreal net does not support delay."); + delete $3; + } + pform_makewire(@2, 0, str_strength, $4, NetNet::WIRE, data_type, $1); delete $1; } @@ -5196,6 +5252,13 @@ module_item delete[]$2; } + | attribute_list_opt + INTERFACE_IDENTIFIER parameter_value_opt gate_instance_list ';' + { perm_string tmp1 = lex_strings.make($2); + pform_make_modgates(@2, tmp1, $3, $4, $1); + delete[]$2; + } + | attribute_list_opt IDENTIFIER parameter_value_opt error ';' { yyerror(@2, "error: Invalid module instantiation"); @@ -5203,6 +5266,13 @@ module_item if ($1) delete $1; } + | attribute_list_opt + INTERFACE_IDENTIFIER parameter_value_opt error ';' + { yyerror(@2, "error: Invalid module instantiation"); + delete[]$2; + if ($1) delete $1; + } + /* Continuous assignment can have an optional drive strength, then an optional delay3 that applies to all the assignments in the cont_assign_list. */ @@ -5496,10 +5566,21 @@ generate_block Note that the continuous assignment statement is generated as a side effect, and all I pass up is the name of the l-value. */ +net_decl_initializer_opt + : '=' expression { $$ = $2; } + | { $$ = 0; } + ; + net_decl_assign - : IDENTIFIER '=' expression + : IDENTIFIER dimensions_opt net_decl_initializer_opt { decl_assignment_t*tmp = new decl_assignment_t; tmp->name = { lex_strings.make($1), @1.lexical_pos }; + if ($2) { + tmp->index = *$2; + if ($3) + pform_requires_sv(@$, "Assignment of net array during declaration"); + delete $2; + } tmp->expr.reset($3); delete[]$1; $$ = tmp; @@ -5561,6 +5642,7 @@ param_type : data_type_or_implicit { param_is_type = false; param_data_type = $1; + param_type_restrict = {}; } | type_param @@ -5595,7 +5677,8 @@ parameter_assign_list parameter_assign : IDENTIFIER dimensions_opt initializer_opt parameter_value_ranges_opt { pform_set_parameter(@1, lex_strings.make($1), param_is_local, - param_is_type, param_data_type, $2, $3, $4); + param_is_type, param_type_restrict, + param_data_type, $2, $3, $4); delete[]$1; } ; @@ -5970,26 +6053,6 @@ dimensions } ; -net_variable - : IDENTIFIER dimensions_opt - { pform_ident_t name = { lex_strings.make($1), @1.lexical_pos }; - $$ = pform_makewire(@1, name, NetNet::IMPLICIT, $2); - delete [] $1; - } - ; - -net_variable_list - : net_variable - { std::vector *tmp = new std::vector; - tmp->push_back($1); - $$ = tmp; - } - | net_variable_list ',' net_variable - { $1->push_back($3); - $$ = $1; - } - ; - event_variable : IDENTIFIER dimensions_opt { if ($2) { diff --git a/parse_misc.h b/parse_misc.h index 23547e85c..62adbe9e6 100644 --- a/parse_misc.h +++ b/parse_misc.h @@ -1,7 +1,7 @@ #ifndef IVL_parse_misc_H #define IVL_parse_misc_H /* - * Copyright (c) 1998-2024 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -83,6 +83,13 @@ extern UCDriveType uc_drive; */ extern void lex_in_package_scope(PPackage*pkg); +/* + * The parser signals when the lexor is scanning a module/interface/program + * port list so that ambiguous SystemVerilog interface formals can be + * tokenized without depending on declaration order. + */ +extern void lex_in_module_port_list(bool flag); + /* * Test if this identifier is a type identifier in the current * context. The pform code needs to help the lexor here because the @@ -92,6 +99,11 @@ extern void lex_in_package_scope(PPackage*pkg); extern typedef_t* pform_test_type_identifier(const YYLTYPE&loc, const char*txt); extern typedef_t* pform_test_type_identifier(PPackage*pkg, const char*txt); +/* + * Test if this identifier is a previously declared interface name. + */ +extern bool pform_test_interface_identifier(const char*txt); + /* * Test if this identifier is a package name. The pform needs to help * the lexor here because the parser detects packages and saves them. diff --git a/pform.cc b/pform.cc index 277312b05..954ff7963 100644 --- a/pform.cc +++ b/pform.cc @@ -49,6 +49,10 @@ using namespace std; +static void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, + std::vector *wires, + list*attr, bool is_const = false); + /* * The "// synthesis translate_on/off" meta-comments cause this flag * to be turned off or on. The pform_make_behavior and similar @@ -841,7 +845,7 @@ static typedef_t *pform_get_typedef(const struct vlltype&loc, perm_string name) } void pform_forward_typedef(const struct vlltype&loc, perm_string name, - enum typedef_t::basic_type basic_type) + type_restrict_t basic_type) { typedef_t *td = pform_get_typedef(loc, name); @@ -926,6 +930,14 @@ typedef_t* pform_test_type_identifier(const struct vlltype&loc, const char*txt) return 0; } +bool pform_test_interface_identifier(const char*txt) +{ + perm_string name = lex_strings.make(txt); + map::const_iterator cur = pform_modules.find(name); + + return cur != pform_modules.end() && cur->second->is_interface; +} + PECallFunction* pform_make_call_function(const struct vlltype&loc, const pform_name_t&name, const list &parms) @@ -1404,6 +1416,35 @@ Module::port_t* pform_module_port_reference(const struct vlltype&loc, return ptmp; } +Module::port_t* pform_module_interface_port_reference( + const struct vlltype&loc, + perm_string interface_type, + perm_string modport_name, + perm_string name, + list*udims) +{ + Module::port_t*ptmp = new Module::port_t; + + ptmp->port_kind = Module::port_t::P_INTERFACE; + ptmp->name = name; + ptmp->interface_type = interface_type; + ptmp->modport_name = modport_name; + ptmp->interface_unpacked_dimensions = udims; + ptmp->lexical_pos = loc.lexical_pos; + + return ptmp; +} + +void pform_module_define_interface_port(const struct vlltype&loc, + const Module::port_t*port, + list*attr) +{ + ivl_assert(loc, port); + ivl_assert(loc, port->is_interface_port()); + + delete attr; +} + void pform_module_set_ports(vector*ports) { assert(! pform_cur_module.empty()); @@ -2237,8 +2278,7 @@ static void pform_makegate(PGBuiltin::Type type, // pform_bind_attributes function to keep the attr object. pform_bind_attributes(cur->attributes, attr, true); - cur->strength0(str.str0); - cur->strength1(str.str1); + cur->strength(drive_strength_t(str.str0, str.str1)); cur->set_line(info); if (pform_cur_generate) { @@ -2460,8 +2500,7 @@ static PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval, else cur = new PGAssign(wires, del); - cur->strength0(str.str0); - cur->strength1(str.str1); + cur->strength(drive_strength_t(str.str0, str.str1)); if (pform_cur_generate) pform_cur_generate->add_gate(cur); @@ -2690,22 +2729,24 @@ void pform_makewire(const struct vlltype&li, wires->push_back(wire); } - pform_set_data_type(li, data_type, wires, type, attr, is_const); + pform_set_data_type(li, data_type, wires, attr, is_const); while (! assign_list->empty()) { decl_assignment_t*first = assign_list->front(); assign_list->pop_front(); - if (PExpr*expr = first->expr.release()) { - if (type == NetNet::REG || type == NetNet::IMPLICIT_REG) { - pform_make_var_init(li, first->name, expr); - } else { - PEIdent*lval = new PEIdent(first->name.first, + if (PExpr*expr = first->expr.release()) { + if (type == NetNet::REG || type == NetNet::IMPLICIT_REG) { + pform_make_var_init(li, first->name, expr); + } else { + PEIdent*lval = new PEIdent(first->name.first, first->name.second); - FILE_NAME(lval, li); - PGAssign*ass = pform_make_pgassign(lval, expr, delay, str); - FILE_NAME(ass, li); - } - } + FILE_NAME(lval, li); + PGAssign*ass = pform_make_pgassign(lval, expr, delay, str); + FILE_NAME(ass, li); + } + } else if (delay) { + VLerror(li, "sorry: net delays not supported."); + } delete first; } } @@ -2929,6 +2970,7 @@ static void pform_set_type_parameter(const struct vlltype&loc, perm_string name, void pform_set_parameter(const struct vlltype&loc, perm_string name, bool is_local, bool is_type, + type_restrict_t type_restrict, data_type_t*data_type, const list*udims, PExpr*expr, LexicalScope::range_t*value_range) { @@ -3001,6 +3043,7 @@ void pform_set_parameter(const struct vlltype&loc, parm->local_flag = is_local; parm->overridable = overridable; parm->type_flag = is_type; + parm->type_restrict = type_restrict; parm->lexical_pos = loc.lexical_pos; scope->parameters[name] = parm; @@ -3251,9 +3294,9 @@ void pform_set_port_type(const struct vlltype&li, * This function detects the derived class for the given type and * dispatches the type to the proper subtype function. */ -void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, - std::vector *wires, NetNet::Type net_type, - list*attr, bool is_const) +static void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, + std::vector *wires, + list*attr, bool is_const) { if (data_type == 0) { VLerror(li, "internal error: data_type==0."); @@ -3268,11 +3311,6 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, pform_set_net_range(wire, vec_type); - // If these fail there is a bug somewhere else. pform_set_data_type() - // is only ever called on a fresh wire that already exists. - bool rc = wire->set_wire_type(net_type); - ivl_assert(li, rc); - wire->set_data_type(data_type); wire->set_const(is_const); diff --git a/pform.h b/pform.h index 12d0e5704..598eb3988 100644 --- a/pform.h +++ b/pform.h @@ -167,6 +167,15 @@ extern void pform_module_define_port(const struct vlltype&li, extern Module::port_t* pform_module_port_reference(const struct vlltype&loc, perm_string name); +extern Module::port_t* pform_module_interface_port_reference( + const struct vlltype&loc, + perm_string interface_type, + perm_string modport_name, + perm_string name, + std::list*udims = 0); +extern void pform_module_define_interface_port(const struct vlltype&loc, + const Module::port_t*port, + std::list*attr); extern void pform_endmodule(const char*, bool inside_celldefine, Module::UCDriveType uc_drive_def); @@ -314,7 +323,7 @@ extern void pform_set_typedef(const struct vlltype&loc, perm_string name, data_type_t*data_type, std::list*unp_ranges = nullptr); extern void pform_forward_typedef(const struct vlltype&loc, perm_string name, - enum typedef_t::basic_type basic_type); + type_restrict_t basic_type); extern void pform_set_type_referenced(const struct vlltype&loc, const char*name); @@ -379,13 +388,6 @@ extern void pform_set_port_type(const struct vlltype&li, data_type_t*dt, std::list*attr); -extern void pform_set_data_type(const struct vlltype&li, - data_type_t *data_type, - std::vector *wires, - NetNet::Type net_type, - std::list*attr, - bool is_const = false); - extern void pform_set_string_type(const struct vlltype&li, const string_type_t*string_type, std::list*names, NetNet::Type net_type, std::list*attr); extern void pform_set_class_type(const struct vlltype&li, class_type_t*class_type, std::list*names, NetNet::Type net_type, std::list*addr); @@ -407,6 +409,7 @@ extern LexicalScope::range_t* pform_parameter_value_range(bool exclude_flag, extern void pform_set_parameter(const struct vlltype&loc, perm_string name, bool is_local, bool is_type, + type_restrict_t type_restrict, data_type_t*data_type, const std::list*udims, PExpr*expr, LexicalScope::range_t*value_range); extern void pform_set_specparam(const struct vlltype&loc, diff --git a/pform_dump.cc b/pform_dump.cc index 313d94cf5..ddc76867a 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2025 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -747,7 +747,7 @@ void PGate::dump(ostream&out, unsigned ind) const void PGAssign::dump(ostream&out, unsigned ind) const { out << setw(ind) << ""; - out << "assign (" << strength0() << "0 " << strength1() << "1) "; + out << "assign (" << strength() << ") "; dump_delays(out); out << " " << *pin(0) << " = " << *pin(1) << ";" << endl; } @@ -793,7 +793,7 @@ void PGBuiltin::dump(ostream&out, unsigned ind) const out << "builtin gate "; } - out << "(" << strength0() << "0 " << strength1() << "1) "; + out << "(" << strength() << ") "; dump_delays(out); out << " " << get_name(); dump_ranges(out); diff --git a/pform_types.cc b/pform_types.cc index f69c5d908..f9af4f1fe 100644 --- a/pform_types.cc +++ b/pform_types.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2019 Stephen Williams (steve@icarus.com) + * Copyright (c) 2007-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -19,6 +19,8 @@ # include "pform_types.h" +# include "netclass.h" +# include "netenum.h" data_type_t::~data_type_t() { @@ -55,34 +57,59 @@ bool typedef_t::set_data_type(data_type_t *t) return true; } -bool typedef_t::set_basic_type(enum basic_type bt) +bool typedef_t::set_basic_type(type_restrict_t type) { - if (bt == ANY) + return basic_type.merge(type); +} + +bool type_restrict_t::merge(type_restrict_t other) +{ + if (other.type == ANY) return true; - if (basic_type != ANY && bt != basic_type) + if (this->type != ANY && other.type != this->type) return false; - basic_type = bt; + this->type = other.type; return true; } -std::ostream& operator<< (std::ostream&out, enum typedef_t::basic_type bt) +bool type_restrict_t::matches(ivl_type_t ivl_type) const { - switch (bt) { - case typedef_t::ANY: + switch (this->type) { + case ENUM: + return dynamic_cast(ivl_type); + case STRUCT: { + const netstruct_t *struct_type = dynamic_cast(ivl_type); + return struct_type && !struct_type->union_flag(); + } + case UNION: { + const netstruct_t *struct_type = dynamic_cast(ivl_type); + return struct_type && struct_type->union_flag(); + } + case CLASS: + return dynamic_cast(ivl_type); + default: + return true; + } +} + +std::ostream& operator<< (std::ostream&out, const type_restrict_t& type) +{ + switch (type.type) { + case type_restrict_t::ANY: out << "any"; break; - case typedef_t::ENUM: + case type_restrict_t::ENUM: out << "enum"; break; - case typedef_t::STRUCT: + case type_restrict_t::STRUCT: out << "struct"; break; - case typedef_t::UNION: + case type_restrict_t::UNION: out << "union"; break; - case typedef_t::CLASS: + case type_restrict_t::CLASS: out << "class"; break; } diff --git a/pform_types.h b/pform_types.h index 452c3e583..e16273cf6 100644 --- a/pform_types.h +++ b/pform_types.h @@ -49,6 +49,24 @@ class netclass_t; class netenum_t; typedef named named_pexpr_t; +struct type_restrict_t { + enum type_t { + ANY, + ENUM, + STRUCT, + UNION, + CLASS + }; + + type_restrict_t() = default; + explicit type_restrict_t(type_t kind) : type(kind) { } + + bool merge(type_restrict_t other); + bool matches(ivl_type_t type) const; + + enum type_t type = ANY; +}; + /* * The pform_ident_t holds the identifier name and its lexical position * (the lexical_pos supplied by the scanner). @@ -180,26 +198,18 @@ class data_type_t : public PNamedItem { }; struct typedef_t : public PNamedItem { - explicit typedef_t(perm_string n) : basic_type(ANY), name(n) { }; + explicit typedef_t(perm_string n) : name(n) { }; ivl_type_t elaborate_type(Design*des, NetScope*scope); - enum basic_type { - ANY, - ENUM, - STRUCT, - UNION, - CLASS - }; - bool set_data_type(data_type_t *t); const data_type_t *get_data_type() const { return data_type.get(); } - bool set_basic_type(basic_type bt); - enum basic_type get_basic_type() const { return basic_type; } + bool set_basic_type(type_restrict_t type); + type_restrict_t get_basic_type() const { return basic_type; } protected: - enum basic_type basic_type; + type_restrict_t basic_type; std::unique_ptr data_type; public: perm_string name; @@ -259,6 +269,7 @@ struct struct_type_t : public data_type_t { bool packed_flag; bool union_flag; + bool soft_flag; bool signed_flag; std::unique_ptr< std::list > members; }; @@ -497,6 +508,6 @@ extern std::ostream& operator<< (std::ostream&out, const pform_name_t&); extern std::ostream& operator<< (std::ostream&out, const pform_scoped_name_t&); extern std::ostream& operator<< (std::ostream&out, const name_component_t&that); extern std::ostream& operator<< (std::ostream&out, const index_component_t&that); -extern std::ostream& operator<< (std::ostream&out, enum typedef_t::basic_type bt); +extern std::ostream& operator<< (std::ostream&out, const type_restrict_t& type); #endif /* IVL_pform_types_H */ diff --git a/scripts/CREATE_BRANCH.sh b/scripts/CREATE_BRANCH.sh index e35546072..440ff0800 100644 --- a/scripts/CREATE_BRANCH.sh +++ b/scripts/CREATE_BRANCH.sh @@ -5,10 +5,10 @@ # # 1. It creates a new branch with the proper name. # -# 2. It then updates the version_base.h to match this version. It likely +# 2. It then updates the configure.ac to match this version. It likely # already does, but it is incorrectly marked as devel instead of stable. # -# 3. It updates the default suffix in aclocal.m4 to match the branch. +# 3. It updates the default suffix in m4/ax_enable_suffix.m4 to match the branch. # # Now manually push the new branch to the master repository. # @@ -27,7 +27,8 @@ case $1 in esac major=$1 - +minor=0 +extra="stable" branch="v${major}-branch" branch_exists=`git ls-remote --heads origin $branch` @@ -39,16 +40,17 @@ fi echo "Creating branch $branch" git checkout -b $branch -echo "Updating version_base.h..." -sed -i -E "s/(define\s+VERSION_MAJOR\s+).*/\1$major/" version_base.h -sed -i -E "s/(define\s+VERSION_MINOR\s+).*/\10/" version_base.h -sed -i -E "s/(define\s+VERSION_EXTRA\s+).*/\1\" \(stable\)\"/" version_base.h +file=configure.ac +echo "Updating $file..." +sed -i -E "s/(m4_define\(\[VER_MAJOR\],[[:space:]]*\[)[^]]*(\]\))/\1$major\2/" $file +sed -i -E "s/(m4_define\(\[VER_MINOR\],[[:space:]]*\[)[^]]*(\]\))/\1$minor\2/" $file +sed -i -E "s/(m4_define\(\[VER_EXTRA\],[[:space:]]*\[)[^]]*(\]\))/\1$extra\2/" $file -echo "Updating aclocal.m4..." -sed -i -E "s/(install_suffix='-)dev/\1$major/" aclocal.m4 +echo "Updating m4/ax_enable_suffix.m4..." +sed -i -E "s/(install_suffix='-)dev/\1$major/" m4/ax_enable_suffix.m4 echo "Adding updated files to the new branch..." -git add version_base.h aclocal.m4 +git add configure.ac m4/ax_enable_suffix.m4 git commit -m "Creating new branch $branch" echo "Done" diff --git a/scripts/CREATE_RELEASE.sh b/scripts/CREATE_RELEASE.sh index 9bff3b652..9da7dad02 100644 --- a/scripts/CREATE_RELEASE.sh +++ b/scripts/CREATE_RELEASE.sh @@ -4,10 +4,10 @@ # based on the first and second argument passed to the script, which should # be the desired major and minor numbers for the release. Before creating the # tag, autoconf.sh will be run to create the configure and lexor_keyword.cc -# files, the version_base.h and verilog.spec files will be updated to reflect -# the new release ID and a release_tag.h file will be created in the top level -# directory to provide the VERSION_TAG macro. After creating the tag, the -# configure, lexor_keywords.cc, and release_tag.h files will be deleted. +# files, the verilog.spec file will be updated to reflect the new release ID +# and a release_tag.h file will be created in the top level directory to +# provide the VERSION_TAG macro. After creating the tag, the configure, +# lexor_keywords.cc, and release_tag.h files will be deleted. # # The complete steps to publish a release are: # @@ -44,6 +44,13 @@ if [ -n "$tag_exists" ] ; then exit 1 fi +extra="stable" +file=configure.ac +echo "Updating $file..." +sed -i -E "s/(m4_define\(\[VER_MAJOR\],[[:space:]]*\[)[^]]*(\]\))/\1$major\2/" $file +sed -i -E "s/(m4_define\(\[VER_MINOR\],[[:space:]]*\[)[^]]*(\]\))/\1$minor\2/" $file +sed -i -E "s/(m4_define\(\[VER_EXTRA\],[[:space:]]*\[)[^]]*(\]\))/\1$extra\2/" $file + echo "Executing autoconf.sh..." sh autoconf.sh if [ $? -ne 0 ] ; then @@ -51,11 +58,6 @@ if [ $? -ne 0 ] ; then exit 1 fi -echo "Updating version_base.h..." -sed -i -E "s/(define\s+VERSION_MAJOR\s+).*/\1$major/" version_base.h -sed -i -E "s/(define\s+VERSION_MINOR\s+).*/\1$minor/" version_base.h -sed -i -E "s/(define\s+VERSION_EXTRA\s+).*/\1\" \(stable\)\"/" version_base.h - echo "Updating verilog.spec..." sed -i -E "s/(define\s+major\s+).*/\1$major/" verilog.spec sed -i -E "s/(define\s+minor\s+).*/\1$minor/" verilog.spec @@ -66,7 +68,7 @@ echo "#define VERSION_TAG \"$tag\"" > release_tag.h echo "Adding files and creating the tag..." git add -f configure lexor_keyword.cc vhdlpp/lexor_keyword.cc -git add version_base.h verilog.spec release_tag.h +git add configure.ac verilog.spec release_tag.h git commit -m "Creating release $tag" git tag -a -m "Release $major.$minor" $tag diff --git a/scripts/CREATE_VERSION.sh b/scripts/CREATE_VERSION.sh index 450f21370..8cecaba62 100644 --- a/scripts/CREATE_VERSION.sh +++ b/scripts/CREATE_VERSION.sh @@ -1,6 +1,6 @@ #!/bin/sh -# This script manually creates a version.h file. +# This script manually creates a version_tag.h file. # # It is used when creating a MinGW executable from a Cygwin # hosted git repository. It assumes that git is available. diff --git a/symbol_search.cc b/symbol_search.cc index 61a28d4ec..863c9717e 100644 --- a/symbol_search.cc +++ b/symbol_search.cc @@ -25,6 +25,7 @@ # include "compiler.h" # include "PPackage.h" # include "PWire.h" +# include "PModport.h" # include "ivl_assert.h" using namespace std; @@ -75,6 +76,25 @@ bool symbol_search(const LineInfo*li, Design*des, NetScope*scope, if (! flag) return false; + if (res->net && res->path_tail.empty() && !res->path_head.empty()) { + name_component_t prefix_tail = res->path_head.back(); + if (prefix_tail.index.empty() && + res->scope->child_byname(prefix_tail.name)) { + bool eval_flag = false; + hname_t path_item = eval_path_component(des, start_scope, + prefix_tail, eval_flag); + if (eval_flag) { + cerr << li->get_fileline() << ": XXXXX: Errors evaluating scope index" << endl; + } else if (NetScope*chld = res->scope->child(path_item)) { + if (chld->is_interface()) { + res->scope = chld; + res->net = 0; + res->type = 0; + } + } + } + } + // The prefix is found to be something besides a scope. Put the // tail into the path_tail of the result, and return success. The // caller needs to deal with that tail bit. Note that the @@ -153,6 +173,15 @@ bool symbol_search(const LineInfo*li, Design*des, NetScope*scope, if (path_tail.name == "#") { if (NetNet *net = scope->find_signal(perm_string::literal(THIS_TOKEN))) { const netclass_t *class_type = dynamic_cast(net->net_type()); + ivl_assert(*li, class_type); + if (!class_type->get_super()) { + cerr << li->get_fileline() << ": error: " + << "Class " << class_type->get_name() + << " uses `super` without a base class." + << endl; + des->errors += 1; + return false; + } path.push_back(path_tail); res->scope = scope; res->net = net; @@ -292,6 +321,52 @@ bool symbol_search(const LineInfo*li, Design*des, NetScope*scope, } } + if (path_tail.index.empty()) { + if (const NetScope::interface_port_alias_t*alias = + scope->find_interface_port_alias(path_tail.name)) { + path.push_back(path_tail); + res->scope = alias->actual_scope; + res->path_head = path; + res->interface_alias_scope = scope; + res->interface_alias_name = path_tail.name; + res->interface_alias_target = alias->actual_scope; + res->interface_alias_modport = alias->modport; + + if (debug_scopes || debug_elaborate) { + cerr << li->get_fileline() << ": symbol_search: " + << "Interface alias " << path_tail.name + << " -> " << scope_path(alias->actual_scope) << endl; + } + + return true; + } + } else if (scope->find_interface_port_alias_array(path_tail.name)) { + bool flag = false; + hname_t path_item = eval_path_component(des, start_scope, path_tail, flag); + if (!flag && path_item.has_numbers() == 1) { + if (const NetScope::interface_port_alias_t*alias = + scope->find_interface_port_alias_element(path_tail.name, + path_item.peek_number(0))) { + path.push_back(path_tail); + res->scope = alias->actual_scope; + res->path_head = path; + res->interface_alias_scope = scope; + res->interface_alias_name = path_tail.name; + res->interface_alias_target = alias->actual_scope; + res->interface_alias_modport = alias->modport; + + if (debug_scopes || debug_elaborate) { + cerr << li->get_fileline() << ": symbol_search: " + << "Interface alias " << path_tail.name + << "[" << path_item.peek_number(0) << "]" + << " -> " << scope_path(alias->actual_scope) << endl; + } + + return true; + } + } + } + // Don't scan up if we are searching within a prefixed scope. if (prefix_scope) break; @@ -387,3 +462,34 @@ bool symbol_search(const LineInfo *li, Design *des, NetScope *scope, return symbol_search(li, des, search_scope, path.name, lexical_pos, res, search_scope, prefix_scope); } + +bool check_interface_modport_access(const LineInfo *li, Design *des, + const symbol_search_results &res, + bool is_write) +{ + if (!res.through_interface_alias() || !res.interface_alias_modport || !res.net) + return true; + + const PModport *modport = res.interface_alias_modport; + perm_string member = res.net->name(); + map::const_iterator cur = + modport->simple_ports.find(member); + + if (cur == modport->simple_ports.end()) { + cerr << li->get_fileline() << ": error: Interface member `" + << member << "' is not listed in modport `" + << modport->name() << "'." << endl; + des->errors += 1; + return false; + } + + if (is_write && cur->second.first == NetNet::PINPUT) { + cerr << li->get_fileline() << ": error: Cannot assign to input " + "modport member `" << member << "' through interface port `" + << res.interface_alias_name << "'." << endl; + des->errors += 1; + return false; + } + + return true; +} diff --git a/synth2.cc b/synth2.cc index f44f87f76..b5f92a7d5 100644 --- a/synth2.cc +++ b/synth2.cc @@ -360,7 +360,7 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, return false; } - NetNet*lsig = lval_->sig(); + const NetNet*lsig = lval_->sig(); if (!lsig) { cerr << get_fileline() << ": error: " "NetAssignBase::synth_async on unsupported lval "; diff --git a/t-dll.cc b/t-dll.cc index 6a99ec8d6..1d130dbca 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -401,13 +401,13 @@ static void scope_add_switch(ivl_scope_t scope, ivl_switch_t net) scope->switches.push_back(net); } -ivl_parameter_t dll_target::scope_find_param(ivl_scope_t scope, +ivl_parameter_t dll_target::scope_find_param(ivl_scope_t scope_i, const char*name) { unsigned idx = 0; - while (idx < scope->param.size()) { - if (strcmp(name, scope->param[idx].basename) == 0) - return &scope->param[idx]; + while (idx < scope_i->param.size()) { + if (strcmp(name, scope_i->param[idx].basename) == 0) + return &scope_i->param[idx]; idx += 1; } diff --git a/t-dll.h b/t-dll.h index 4dc074247..44d5c3724 100644 --- a/t-dll.h +++ b/t-dll.h @@ -162,7 +162,7 @@ struct dll_target : public target_t, public expr_scan_t { static ivl_scope_t find_scope(ivl_design_s &des, const NetScope*cur); static ivl_signal_t find_signal(ivl_design_s &des, const NetNet*net); - static ivl_parameter_t scope_find_param(ivl_scope_t scope, + static ivl_parameter_t scope_find_param(ivl_scope_t scope_i, const char*name); void add_root(const NetScope *s); diff --git a/tgt-fpga/Makefile.in b/tgt-fpga/Makefile.in index 0fa9c6738..776541ad3 100644 --- a/tgt-fpga/Makefile.in +++ b/tgt-fpga/Makefile.in @@ -23,8 +23,9 @@ suffix = @install_suffix@ prefix = @prefix@ exec_prefix = @exec_prefix@ srcdir = @srcdir@ -mandir = @mandir@ -datarootdir = @datarootdir@ +datarootdir = @datarootdir +man1dir = @mandir@/man1 +docdir = @docdir@ VPATH = $(srcdir) @@ -94,13 +95,15 @@ iverilog-fpga.ps: $(srcdir)/iverilog-fpga.man iverilog-fpga.pdf: iverilog-fpga.ps ps2pdf iverilog-fpga.ps iverilog-fpga.pdf -ifeq (@WIN32@,yes) -INSTALL_DOC = installpdf installman -INSTALL_DOCDIR = $(mandir)/man1 +INSTALL_DOC = +ifneq ($(MAN),none) +INSTALL_DOC += installman +ifneq ($(PS2PDF),none) +ifeq (@MINGW32@,yes) +INSTALL_DOC += installpdf all: iverilog-fpga.pdf -else -INSTALL_DOC = installman -INSTALL_DOCDIR = $(mandir)/man1 +endif +endif endif install: all installdirs installfiles @@ -111,10 +114,10 @@ F = ./fpga.tgt \ $(INSTALL_DOC) installman: $(srcdir)/iverilog-fpga.man installdirs - $(INSTALL_DATA) $(srcdir)/iverilog-fpga.man "$(DESTDIR)$(mandir)/man1/iverilog-fpga$(suffix).1" + $(INSTALL_DATA) $(srcdir)/iverilog-fpga.man "$(DESTDIR)$(man1dir)/iverilog-fpga$(suffix).1" installpdf: iverilog-fpga.pdf installdirs - $(INSTALL_DATA) iverilog-fpga.pdf "$(DESTDIR)$(prefix)/iverilog-fpga$(suffix).pdf" + $(INSTALL_DATA) iverilog-fpga.pdf "$(DESTDIR)$(docdir)/iverilog-fpga$(suffix).pdf" installfiles: $(F) | installdirs $(INSTALL_PROGRAM) ./fpga.tgt "$(DESTDIR)$(libdir)/ivl$(suffix)/fpga.tgt" @@ -126,7 +129,7 @@ installdirs: $(srcdir)/../mkinstalldirs uninstall: rm -f "$(DESTDIR)$(libdir)/ivl$(suffix)/fpga.tgt" - rm -f "$(DESTDIR)$(prefix)/iverilog-fpga$(suffix).pdf" "$(DESTDIR)$(mandir)/man1/iverilog-fpga$(suffix).1" + rm -f "$(DESTDIR)$(docdir)/iverilog-fpga$(suffix).pdf" "$(DESTDIR)$(man1dir)/iverilog-fpga$(suffix).1" rm -f "$(DESTDIR)$(libdir)/ivl$(suffix)/fpga-s.conf" rm -f "$(DESTDIR)$(libdir)/ivl$(suffix)/fpga.conf" diff --git a/tgt-fpga/device.h b/tgt-fpga/device.h index 03cb08b1b..0c001215d 100644 --- a/tgt-fpga/device.h +++ b/tgt-fpga/device.h @@ -1,7 +1,7 @@ #ifndef IVL_device_H #define IVL_device_H /* - * Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -72,6 +72,6 @@ struct device_s { * This function is used if the user specifies the architecture * explicitly, with the -parch=name flag. */ -extern device_t device_from_arch(const char*arch); +extern device_t device_from_arch(const char*arch_i); #endif /* IVL_device_H */ diff --git a/tgt-fpga/tables.c b/tgt-fpga/tables.c index 1aa44f16f..73fa608c8 100644 --- a/tgt-fpga/tables.c +++ b/tgt-fpga/tables.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -40,14 +40,14 @@ const struct device_table_s { { 0, 0 } }; -device_t device_from_arch(const char*arch) +device_t device_from_arch(const char*arch_i) { unsigned idx; - assert(arch); + assert(arch_i); for (idx = 0 ; device_table[idx].name ; idx += 1) { - if (strcmp(arch, device_table[idx].name) == 0) + if (strcmp(arch_i, device_table[idx].name) == 0) return device_table[idx].driver; } diff --git a/tgt-fpga/xilinx.c b/tgt-fpga/xilinx.c index eb1ad7738..233d58bd1 100644 --- a/tgt-fpga/xilinx.c +++ b/tgt-fpga/xilinx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2014 Stephen Williams (steve at icarus.com) + * Copyright (c) 2003-2026 Stephen Williams (steve at icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -26,80 +26,80 @@ # include # include "ivl_alloc.h" -edif_cell_t xilinx_cell_buf(edif_xlibrary_t xlib) +edif_cell_t xilinx_cell_buf(edif_xlibrary_t xlib_i) { static edif_cell_t cell = 0; if (cell) return cell; - cell = edif_xcell_create(xlib, "BUF", 2); + cell = edif_xcell_create(xlib_i, "BUF", 2); edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT); edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT); return cell; } -edif_cell_t xilinx_cell_bufe(edif_xlibrary_t xlib) +edif_cell_t xilinx_cell_bufe(edif_xlibrary_t xlib_i) { static edif_cell_t cell = 0; if (cell) return cell; - cell = edif_xcell_create(xlib, "BUFE", 3); + cell = edif_xcell_create(xlib_i, "BUFE", 3); edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT); edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT); edif_cell_portconfig(cell, BUF_T, "E", IVL_SIP_INPUT); return cell; } -edif_cell_t xilinx_cell_bufg(edif_xlibrary_t xlib) +edif_cell_t xilinx_cell_bufg(edif_xlibrary_t xlib_i) { static edif_cell_t cell = 0; if (cell) return cell; - cell = edif_xcell_create(xlib, "BUFG", 2); + cell = edif_xcell_create(xlib_i, "BUFG", 2); edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT); edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT); return cell; } -edif_cell_t xilinx_cell_buft(edif_xlibrary_t xlib) +edif_cell_t xilinx_cell_buft(edif_xlibrary_t xlib_i) { static edif_cell_t cell = 0; if (cell) return cell; - cell = edif_xcell_create(xlib, "BUFT", 3); + cell = edif_xcell_create(xlib_i, "BUFT", 3); edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT); edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT); edif_cell_portconfig(cell, BUF_T, "T", IVL_SIP_INPUT); return cell; } -edif_cell_t xilinx_cell_ibuf(edif_xlibrary_t xlib) +edif_cell_t xilinx_cell_ibuf(edif_xlibrary_t xlib_i) { static edif_cell_t cell = 0; if (cell) return cell; - cell = edif_xcell_create(xlib, "IBUF", 2); + cell = edif_xcell_create(xlib_i, "IBUF", 2); edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT); edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT); return cell; } -edif_cell_t xilinx_cell_inv(edif_xlibrary_t xlib) +edif_cell_t xilinx_cell_inv(edif_xlibrary_t xlib_i) { static edif_cell_t cell = 0; if (cell) return cell; - cell = edif_xcell_create(xlib, "INV", 2); + cell = edif_xcell_create(xlib_i, "INV", 2); edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT); edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT); return cell; } -edif_cell_t xilinx_cell_muxf5(edif_xlibrary_t xlib) +edif_cell_t xilinx_cell_muxf5(edif_xlibrary_t xlib_i) { static edif_cell_t cell = 0; if (cell) return cell; - cell = edif_xcell_create(xlib, "MUXF5", 4); + cell = edif_xcell_create(xlib_i, "MUXF5", 4); edif_cell_portconfig(cell, MUXF_O, "O", IVL_SIP_OUTPUT); edif_cell_portconfig(cell, MUXF_I0, "I0", IVL_SIP_INPUT); edif_cell_portconfig(cell, MUXF_I1, "I1", IVL_SIP_INPUT); @@ -107,12 +107,12 @@ edif_cell_t xilinx_cell_muxf5(edif_xlibrary_t xlib) return cell; } -edif_cell_t xilinx_cell_muxf6(edif_xlibrary_t xlib) +edif_cell_t xilinx_cell_muxf6(edif_xlibrary_t xlib_i) { static edif_cell_t cell = 0; if (cell) return cell; - cell = edif_xcell_create(xlib, "MUXF6", 4); + cell = edif_xcell_create(xlib_i, "MUXF6", 4); edif_cell_portconfig(cell, MUXF_O, "O", IVL_SIP_OUTPUT); edif_cell_portconfig(cell, MUXF_I0, "I0", IVL_SIP_INPUT); edif_cell_portconfig(cell, MUXF_I1, "I1", IVL_SIP_INPUT); @@ -120,36 +120,36 @@ edif_cell_t xilinx_cell_muxf6(edif_xlibrary_t xlib) return cell; } -edif_cell_t xilinx_cell_obuf(edif_xlibrary_t xlib) +edif_cell_t xilinx_cell_obuf(edif_xlibrary_t xlib_i) { static edif_cell_t cell = 0; if (cell) return cell; - cell = edif_xcell_create(xlib, "OBUF", 2); + cell = edif_xcell_create(xlib_i, "OBUF", 2); edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT); edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT); return cell; } -edif_cell_t xilinx_cell_lut2(edif_xlibrary_t xlib) +edif_cell_t xilinx_cell_lut2(edif_xlibrary_t xlib_i) { static edif_cell_t cell = 0; if (cell != 0) return cell; - cell = edif_xcell_create(xlib, "LUT2", 3); + cell = edif_xcell_create(xlib_i, "LUT2", 3); edif_cell_portconfig(cell, LUT_O, "O", IVL_SIP_OUTPUT); edif_cell_portconfig(cell, LUT_I0, "I0", IVL_SIP_INPUT); edif_cell_portconfig(cell, LUT_I1, "I1", IVL_SIP_INPUT); return cell; } -edif_cell_t xilinx_cell_lut3(edif_xlibrary_t xlib) +edif_cell_t xilinx_cell_lut3(edif_xlibrary_t xlib_i) { static edif_cell_t cell = 0; if (cell != 0) return cell; - cell = edif_xcell_create(xlib, "LUT3", 4); + cell = edif_xcell_create(xlib_i, "LUT3", 4); edif_cell_portconfig(cell, LUT_O, "O", IVL_SIP_OUTPUT); edif_cell_portconfig(cell, LUT_I0, "I0", IVL_SIP_INPUT); edif_cell_portconfig(cell, LUT_I1, "I1", IVL_SIP_INPUT); @@ -157,12 +157,12 @@ edif_cell_t xilinx_cell_lut3(edif_xlibrary_t xlib) return cell; } -edif_cell_t xilinx_cell_lut4(edif_xlibrary_t xlib) +edif_cell_t xilinx_cell_lut4(edif_xlibrary_t xlib_i) { static edif_cell_t cell = 0; if (cell != 0) return cell; - cell = edif_xcell_create(xlib, "LUT4", 5); + cell = edif_xcell_create(xlib_i, "LUT4", 5); edif_cell_portconfig(cell, LUT_O, "O", IVL_SIP_OUTPUT); edif_cell_portconfig(cell, LUT_I0, "I0", IVL_SIP_INPUT); edif_cell_portconfig(cell, LUT_I1, "I1", IVL_SIP_INPUT); @@ -172,12 +172,12 @@ edif_cell_t xilinx_cell_lut4(edif_xlibrary_t xlib) } -edif_cell_t xilinx_cell_fdce(edif_xlibrary_t xlib) +edif_cell_t xilinx_cell_fdce(edif_xlibrary_t xlib_i) { static edif_cell_t cell = 0; if (cell != 0) return cell; - cell = edif_xcell_create(xlib, "FDCE", 5); + cell = edif_xcell_create(xlib_i, "FDCE", 5); edif_cell_portconfig(cell, FDCE_Q, "Q", IVL_SIP_OUTPUT); edif_cell_portconfig(cell, FDCE_D, "D", IVL_SIP_INPUT); edif_cell_portconfig(cell, FDCE_C, "C", IVL_SIP_INPUT); @@ -186,12 +186,12 @@ edif_cell_t xilinx_cell_fdce(edif_xlibrary_t xlib) return cell; } -edif_cell_t xilinx_cell_fdcpe(edif_xlibrary_t xlib) +edif_cell_t xilinx_cell_fdcpe(edif_xlibrary_t xlib_i) { static edif_cell_t cell = 0; if (cell != 0) return cell; - cell = edif_xcell_create(xlib, "FDCPE", 6); + cell = edif_xcell_create(xlib_i, "FDCPE", 6); edif_cell_portconfig(cell, FDCE_Q, "Q", IVL_SIP_OUTPUT); edif_cell_portconfig(cell, FDCE_D, "D", IVL_SIP_INPUT); edif_cell_portconfig(cell, FDCE_C, "C", IVL_SIP_INPUT); @@ -201,12 +201,12 @@ edif_cell_t xilinx_cell_fdcpe(edif_xlibrary_t xlib) return cell; } -edif_cell_t xilinx_cell_fdre(edif_xlibrary_t xlib) +edif_cell_t xilinx_cell_fdre(edif_xlibrary_t xlib_i) { static edif_cell_t cell = 0; if (cell != 0) return cell; - cell = edif_xcell_create(xlib, "FDRE", 5); + cell = edif_xcell_create(xlib_i, "FDRE", 5); edif_cell_portconfig(cell, FDCE_Q, "Q", IVL_SIP_OUTPUT); edif_cell_portconfig(cell, FDCE_D, "D", IVL_SIP_INPUT); edif_cell_portconfig(cell, FDCE_C, "C", IVL_SIP_INPUT); @@ -216,24 +216,24 @@ edif_cell_t xilinx_cell_fdre(edif_xlibrary_t xlib) } -edif_cell_t xilinx_cell_mult_and(edif_xlibrary_t xlib) +edif_cell_t xilinx_cell_mult_and(edif_xlibrary_t xlib_i) { static edif_cell_t cell = 0; if (cell != 0) return cell; - cell = edif_xcell_create(xlib, "MULT_AND", 3); + cell = edif_xcell_create(xlib_i, "MULT_AND", 3); edif_cell_portconfig(cell, MULT_AND_LO, "LO", IVL_SIP_OUTPUT); edif_cell_portconfig(cell, MULT_AND_I0, "I0", IVL_SIP_INPUT); edif_cell_portconfig(cell, MULT_AND_I1, "I1", IVL_SIP_INPUT); return cell; } -edif_cell_t xilinx_cell_muxcy(edif_xlibrary_t xlib) +edif_cell_t xilinx_cell_muxcy(edif_xlibrary_t xlib_i) { static edif_cell_t cell = 0; if (cell != 0) return cell; - cell = edif_xcell_create(xlib, "MUXCY", 4); + cell = edif_xcell_create(xlib_i, "MUXCY", 4); edif_cell_portconfig(cell, MUXCY_O, "O", IVL_SIP_OUTPUT); edif_cell_portconfig(cell, MUXCY_DI, "DI", IVL_SIP_INPUT); edif_cell_portconfig(cell, MUXCY_CI, "CI", IVL_SIP_INPUT); @@ -241,12 +241,12 @@ edif_cell_t xilinx_cell_muxcy(edif_xlibrary_t xlib) return cell; } -edif_cell_t xilinx_cell_muxcy_l(edif_xlibrary_t xlib) +edif_cell_t xilinx_cell_muxcy_l(edif_xlibrary_t xlib_i) { static edif_cell_t cell = 0; if (cell != 0) return cell; - cell = edif_xcell_create(xlib, "MUXCY_L", 4); + cell = edif_xcell_create(xlib_i, "MUXCY_L", 4); edif_cell_portconfig(cell, MUXCY_O, "LO", IVL_SIP_OUTPUT); edif_cell_portconfig(cell, MUXCY_DI, "DI", IVL_SIP_INPUT); edif_cell_portconfig(cell, MUXCY_CI, "CI", IVL_SIP_INPUT); @@ -254,12 +254,12 @@ edif_cell_t xilinx_cell_muxcy_l(edif_xlibrary_t xlib) return cell; } -edif_cell_t xilinx_cell_xorcy(edif_xlibrary_t xlib) +edif_cell_t xilinx_cell_xorcy(edif_xlibrary_t xlib_i) { static edif_cell_t cell = 0; if (cell != 0) return cell; - cell = edif_xcell_create(xlib, "XORCY", 3); + cell = edif_xcell_create(xlib_i, "XORCY", 3); edif_cell_portconfig(cell, XORCY_O, "O", IVL_SIP_OUTPUT); edif_cell_portconfig(cell, XORCY_CI, "CI", IVL_SIP_INPUT); edif_cell_portconfig(cell, XORCY_LI, "LI", IVL_SIP_INPUT); diff --git a/tgt-fpga/xilinx.h b/tgt-fpga/xilinx.h index b3b0ae7ac..70f241614 100644 --- a/tgt-fpga/xilinx.h +++ b/tgt-fpga/xilinx.h @@ -1,7 +1,7 @@ #ifndef IVL_xilinx_H #define IVL_xilinx_H /* - * Copyright (c) 2003-2014 Stephen Williams (steve at icarus.com) + * Copyright (c) 2003-2026 Stephen Williams (steve at icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -34,13 +34,13 @@ /* Buffer types of devices have the BUF_O and BUF_I pin assignments. The BUF, INV, and certain specialized devices fit in this category. */ -extern edif_cell_t xilinx_cell_buf (edif_xlibrary_t xlib); -extern edif_cell_t xilinx_cell_bufe(edif_xlibrary_t xlib); -extern edif_cell_t xilinx_cell_bufg(edif_xlibrary_t xlib); -extern edif_cell_t xilinx_cell_buft(edif_xlibrary_t xlib); -extern edif_cell_t xilinx_cell_inv (edif_xlibrary_t xlib); -extern edif_cell_t xilinx_cell_ibuf(edif_xlibrary_t xlib); -extern edif_cell_t xilinx_cell_obuf(edif_xlibrary_t xlib); +extern edif_cell_t xilinx_cell_buf (edif_xlibrary_t xlib_i); +extern edif_cell_t xilinx_cell_bufe(edif_xlibrary_t xlib_i); +extern edif_cell_t xilinx_cell_bufg(edif_xlibrary_t xlib_i); +extern edif_cell_t xilinx_cell_buft(edif_xlibrary_t xlib_i); +extern edif_cell_t xilinx_cell_inv (edif_xlibrary_t xlib_i); +extern edif_cell_t xilinx_cell_ibuf(edif_xlibrary_t xlib_i); +extern edif_cell_t xilinx_cell_obuf(edif_xlibrary_t xlib_i); #define BUF_O 0 #define BUF_I 1 /* Only bufe and buft buffers have this input. */ @@ -52,9 +52,9 @@ extern edif_cell_t xilinx_cell_obuf(edif_xlibrary_t xlib); 2, 3 or 4 inputs. All forms have a single bit output. Also, the real behavior of the device will need to be specified by an INIT parameter string. */ -extern edif_cell_t xilinx_cell_lut2(edif_xlibrary_t xlib); -extern edif_cell_t xilinx_cell_lut3(edif_xlibrary_t xlib); -extern edif_cell_t xilinx_cell_lut4(edif_xlibrary_t xlib); +extern edif_cell_t xilinx_cell_lut2(edif_xlibrary_t xlib_i); +extern edif_cell_t xilinx_cell_lut3(edif_xlibrary_t xlib_i); +extern edif_cell_t xilinx_cell_lut4(edif_xlibrary_t xlib_i); #define LUT_O 0 #define LUT_I0 1 #define LUT_I1 2 @@ -67,9 +67,9 @@ extern edif_cell_t xilinx_cell_lut4(edif_xlibrary_t xlib); /* * These are flip-flops of various sort, but similar pinouts. */ -extern edif_cell_t xilinx_cell_fdce(edif_xlibrary_t xlib); -extern edif_cell_t xilinx_cell_fdcpe(edif_xlibrary_t xlib); -extern edif_cell_t xilinx_cell_fdre(edif_xlibrary_t xlib); +extern edif_cell_t xilinx_cell_fdce(edif_xlibrary_t xlib_i); +extern edif_cell_t xilinx_cell_fdcpe(edif_xlibrary_t xlib_i); +extern edif_cell_t xilinx_cell_fdre(edif_xlibrary_t xlib_i); #define FDCE_Q 0 #define FDCE_C 1 #define FDCE_D 2 @@ -80,28 +80,28 @@ extern edif_cell_t xilinx_cell_fdre(edif_xlibrary_t xlib); /* === Virtex/Virtex2 Carry Chain Logic === */ -extern edif_cell_t xilinx_cell_mult_and(edif_xlibrary_t xlib); +extern edif_cell_t xilinx_cell_mult_and(edif_xlibrary_t xlib_i); #define MULT_AND_LO 0 #define MULT_AND_I0 1 #define MULT_AND_I1 2 -extern edif_cell_t xilinx_cell_muxcy(edif_xlibrary_t xlib); -extern edif_cell_t xilinx_cell_muxcy_l(edif_xlibrary_t xlib); +extern edif_cell_t xilinx_cell_muxcy(edif_xlibrary_t xlib_i); +extern edif_cell_t xilinx_cell_muxcy_l(edif_xlibrary_t xlib_i); #define MUXCY_O 0 #define MUXCY_DI 1 #define MUXCY_CI 2 #define MUXCY_S 3 -extern edif_cell_t xilinx_cell_xorcy(edif_xlibrary_t xlib); +extern edif_cell_t xilinx_cell_xorcy(edif_xlibrary_t xlib_i); #define XORCY_O 0 #define XORCY_CI 1 #define XORCY_LI 2 /* === Virtex/Virtex2 MUX devices */ -extern edif_cell_t xilinx_cell_muxf5(edif_xlibrary_t xlib); -extern edif_cell_t xilinx_cell_muxf6(edif_xlibrary_t xlib); -extern edif_cell_t xilinx_cell_muxf7(edif_xlibrary_t xlib); -extern edif_cell_t xilinx_cell_muxf8(edif_xlibrary_t xlib); +extern edif_cell_t xilinx_cell_muxf5(edif_xlibrary_t xlib_i); +extern edif_cell_t xilinx_cell_muxf6(edif_xlibrary_t xlib_i); +extern edif_cell_t xilinx_cell_muxf7(edif_xlibrary_t xlib_i); +extern edif_cell_t xilinx_cell_muxf8(edif_xlibrary_t xlib_i); #define MUXF_O 0 #define MUXF_I0 1 #define MUXF_I1 2 diff --git a/tgt-pcb/cppcheck.sup b/tgt-pcb/cppcheck.sup index 789847374..0599400b1 100644 --- a/tgt-pcb/cppcheck.sup +++ b/tgt-pcb/cppcheck.sup @@ -10,9 +10,12 @@ unusedFunction:pcb.cc:84 // Errors/limitations in the generated yacc and lex files duplicateBreak:fp.lex constParameterPointer:fp.cc +invalidPrintfArgType_sint:fp.cc knownConditionTrueFalse:fp.cc +unsignedPositive:fp.cc constVariablePointer:fp_lex.cc cstyleCast:fp_lex.cc +duplicateBreak:fp_lex.cc nullPointer:fp_lex.cc redundantInitialization:fp_lex.cc unusedFunction:fp_lex.cc diff --git a/tgt-vhdl/vhdl_syntax.cc b/tgt-vhdl/vhdl_syntax.cc index d62daefa5..763a31e07 100644 --- a/tgt-vhdl/vhdl_syntax.cc +++ b/tgt-vhdl/vhdl_syntax.cc @@ -286,9 +286,9 @@ void stmt_container::find_vars(vhdl_var_set_t& read, (*it)->find_vars(read, write); } -void stmt_container::emit(std::ostream &of, int level, bool newline) const +void stmt_container::emit(std::ostream &of, int level, bool trailing_newln) const { - emit_children(of, stmts_, level, "", newline); + emit_children(of, stmts_, level, "", trailing_newln); } vhdl_comp_inst::vhdl_comp_inst(const char *inst_name, const char *comp_name) diff --git a/tgt-vhdl/vhdl_syntax.hh b/tgt-vhdl/vhdl_syntax.hh index e74d564af..66b2e8903 100644 --- a/tgt-vhdl/vhdl_syntax.hh +++ b/tgt-vhdl/vhdl_syntax.hh @@ -360,7 +360,7 @@ public: void add_stmt(vhdl_seq_stmt *stmt); void move_stmts_from(stmt_container *other); - void emit(std::ostream &of, int level, bool newline=true) const; + void emit(std::ostream &of, int level, bool trailing_newln=true) const; bool empty() const { return stmts_.empty(); } void find_vars(vhdl_var_set_t& read, vhdl_var_set_t& write); diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index a29129fb3..0b5b40ea0 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2021 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -671,7 +671,7 @@ static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope) switch (ivl_statement_type(net)) { case IVL_ST_CASE: - fprintf(vvp_out, " %%cmp/u;\n"); + fprintf(vvp_out, " %%cmp/e;\n"); fprintf(vvp_out, " %%jmp/1 T_%u.%u, 6;\n", thread_count, local_base+idx); break; diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 467ae6d8a..5600e1abd 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2025 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -912,7 +912,7 @@ static void draw_equiv_impl_in_scope(ivl_net_logic_t lptr) unsigned ninp; const char *lval; const char *rval; - const char*ltype = "?"; + const char *ltype; assert(width_of_nexus(ivl_logic_pin(lptr, 0)) == 1); diff --git a/version.c b/version.c deleted file mode 100644 index 64e4178c2..000000000 --- a/version.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2009-2015 Stephen Williams (steve@icarus.com) - * - * This source code is free software; you can redistribute it - * and/or modify it in source code form under the terms of the GNU - * General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -# include "version_base.h" -# include "version_tag.h" -# include -# include - -static void run_string(const char*txt) -{ - const char*cp = txt; - while (*cp) { - if (cp[0] == '%' && cp[1] != 0) { - switch (cp[1]) { - case 'M': - fprintf(stdout, "%d", VERSION_MAJOR); - break; - case 'n': - fprintf(stdout, "%d", VERSION_MINOR); - break; - case 'E': - fprintf(stdout, "%s", VERSION_EXTRA); - break; - case 'T': - fprintf(stdout, "%s", VERSION_TAG); - break; - case '%': - putc('%', stdout); - break; - default: - break; - } - cp += 2; - - } else if (cp[0] == '\\' && cp[1] != 0) { - switch (cp[1]) { - case 'n': - putc('\n', stdout); - break; - default: - putc(cp[1], stdout); - break; - } - cp += 2; - - } else { - putc(cp[0], stdout); - cp += 1; - } - } -} - -int main(int argc, char*argv[]) -{ - int idx; - - if (argc == 1) { - printf("%s\n", VERSION); - return 0; - } - - run_string(argv[1]); - for (idx = 2 ; idx < argc ; idx += 1) { - printf(" "); - run_string(argv[idx]); - } - - return 0; -} diff --git a/version_base.h b/version_base.h.in similarity index 52% rename from version_base.h rename to version_base.h.in index 46b0e93eb..750e8c02e 100644 --- a/version_base.h +++ b/version_base.h.in @@ -1,16 +1,17 @@ #ifndef VERSION /* - * Edit this definition in version_base.in to define the base version - * number for the compiled result. + * This file is generated from version_base.h.in by the build system + * + * WARNING! All changes made in this file will be lost when recompiling! */ -# define VERSION_MAJOR 14 -# define VERSION_MINOR 0 +#define VERSION_MAJOR @VERSION_MAJOR@ +#define VERSION_MINOR @VERSION_MINOR@ /* * This will be appended to the version. Use this to mark development * versions and the like. */ -# define VERSION_EXTRA " (devel)" +# define VERSION_EXTRA "@VERSION_EXTRA@" # define VERSION_STRINGIFY(x) #x # define VERSION_STR(a,b,extra) VERSION_STRINGIFY(a.b) extra diff --git a/vhdlpp/architec_emit.cc b/vhdlpp/architec_emit.cc index 900dfe8c0..012c8684c 100644 --- a/vhdlpp/architec_emit.cc +++ b/vhdlpp/architec_emit.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2021 Stephen Williams (steve@icarus.com) + * Copyright (c) 2011-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -203,7 +203,7 @@ int CondSignalAssignment::emit(ostream&out, Entity*ent, Architecture*arc) int ComponentInstantiation::emit(ostream&out, Entity*ent, Architecture*arc) { - const char*comma = ""; + const char*comma; int errors = 0; arc->set_cur_component(this); diff --git a/vhdlpp/cppcheck.sup b/vhdlpp/cppcheck.sup index 5613c1c10..53b54a207 100644 --- a/vhdlpp/cppcheck.sup +++ b/vhdlpp/cppcheck.sup @@ -24,6 +24,7 @@ useStlAlgorithm // Errors/limitations in the generated yacc and lex files cstyleCast:lexor.cc constVariablePointer:lexor.cc +duplicateBreak:lexor.cc redundantInitialization:lexor.cc unusedFunction:lexor.cc unusedStructMember:lexor.cc @@ -32,7 +33,9 @@ duplicateBreak:lexor.lex redundantInitialization:lexor.lex uselessAssignmentPtrArg:lexor.lex constParameterPointer:parse.cc +invalidPrintfArgType_sint:parse.cc knownConditionTrueFalse:parse.cc +unsignedPositive:parse.cc // Unused functions unusedFunction:LineInfo.h diff --git a/vhdlpp/library.cc b/vhdlpp/library.cc index b59bc7990..b72a7d896 100644 --- a/vhdlpp/library.cc +++ b/vhdlpp/library.cc @@ -78,7 +78,6 @@ void library_add_directory(const char*directory) SubprogramHeader*library_match_subprogram(perm_string name, const list*params) { - SubprogramHeader*subp; map::const_iterator lib_it; for(lib_it = libraries.begin(); lib_it != libraries.end(); ++lib_it) { @@ -86,6 +85,7 @@ SubprogramHeader*library_match_subprogram(perm_string name, const list::const_iterator pack_it; for(pack_it = lib.packages.begin(); pack_it != lib.packages.end(); ++pack_it) { + SubprogramHeader*subp; if((subp = pack_it->second->match_subprogram(name, params))) return subp; } diff --git a/vpi/cppcheck.sup b/vpi/cppcheck.sup index 30a59239e..c69de0859 100644 --- a/vpi/cppcheck.sup +++ b/vpi/cppcheck.sup @@ -63,7 +63,6 @@ constParameterPointer:fstapi.c constVariablePointer:fstapi.c duplicateConditionalAssign:fstapi.c knownConditionTrueFalse:fstapi.c -memleak:fstapi.c missingInclude:fst_win_unistd.h:50 nullPointer:fstapi.c shiftTooManyBits:fstapi.c @@ -75,85 +74,85 @@ uselessAssignmentPtrArg:fstapi.c variableScope:fstapi.c // These functions are not used by Icarus // fstReaderClrFacProcessMask() -unusedFunction:fstapi.c:3513 +unusedFunction:fstapi.c:3514 // fstReaderClrFacProcessMaskAll() -unusedFunction:fstapi.c:3533 +unusedFunction:fstapi.c:3534 // fstReaderGetAliasCount() -unusedFunction:fstapi.c:3578 +unusedFunction:fstapi.c:3579 // fstReaderGetCurrentFlatScope() -unusedFunction:fstapi.c:3392 +unusedFunction:fstapi.c:3393 // fstReaderGetCurrentScopeLen() -unusedFunction:fstapi.c:3465 +unusedFunction:fstapi.c:3466 // fstReaderGetCurrentScopeUserInfo() -unusedFunction:fstapi.c:3401 +unusedFunction:fstapi.c:3402 // fstReaderGetDateString() -unusedFunction:fstapi.c:3598 +unusedFunction:fstapi.c:3599 // fstReaderGetDoubleEndianMatchState() -unusedFunction:fstapi.c:3588 +unusedFunction:fstapi.c:3589 // fstReaderGetDumpActivityChangeTime() -unusedFunction:fstapi.c:3618 +unusedFunction:fstapi.c:3619 // fstReaderGetDumpActivityChangeValue() -unusedFunction:fstapi.c:3627 +unusedFunction:fstapi.c:3628 // fstReaderGetEndTime() -unusedFunction:fstapi.c:3553 +unusedFunction:fstapi.c:3554 // fstReaderGetFacProcessMask() -unusedFunction:fstapi.c:3486 +unusedFunction:fstapi.c:3487 // fstReaderGetFileType() -unusedFunction:fstapi.c:3603 +unusedFunction:fstapi.c:3604 // fstReaderGetFseekFailed() -unusedFunction:fstapi.c:3474 +unusedFunction:fstapi.c:3475 // fstReaderGetMaxHandle() -unusedFunction:fstapi.c:3573 +unusedFunction:fstapi.c:3574 // fstReaderGetMemoryUsedByWriter() -unusedFunction:fstapi.c:3558 +unusedFunction:fstapi.c:3559 // fstReaderGetNumberDumpActivityChanges() -unusedFunction:fstapi.c:3613 +unusedFunction:fstapi.c:3614 // fstReaderGetScopeCount() -unusedFunction:fstapi.c:3563 +unusedFunction:fstapi.c:3564 // fstReaderGetStartTime() -unusedFunction:fstapi.c:3548 +unusedFunction:fstapi.c:3549 // fstReaderGetTimescale() -unusedFunction:fstapi.c:3543 +unusedFunction:fstapi.c:3544 // fstReaderGetTimezero() -unusedFunction:fstapi.c:3608 +unusedFunction:fstapi.c:3609 // fstReaderGetValueChangeSectionCount() -unusedFunction:fstapi.c:3583 +unusedFunction:fstapi.c:3584 // fstReaderGetValueFromHandleAtTime() -unusedFunction:fstapi.c:5952 +unusedFunction:fstapi.c:5953 // fstReaderGetVarCount() -unusedFunction:fstapi.c:3568 +unusedFunction:fstapi.c:3569 // fstReaderGetVersionString() -unusedFunction:fstapi.c:3593 +unusedFunction:fstapi.c:3594 // fstReaderIterBlocks() -unusedFunction:fstapi.c:4832 +unusedFunction:fstapi.c:4833 // fstReaderIterBlocksSetNativeDoublesOnCallback() -unusedFunction:fstapi.c:3659 +unusedFunction:fstapi.c:3660 // fstReaderIterateHier() -unusedFunction:fstapi.c:3872 +unusedFunction:fstapi.c:3873 // fstReaderIterateHierRewind() -unusedFunction:fstapi.c:3856 +unusedFunction:fstapi.c:3857 // fstReaderOpen() -unusedFunction:fstapi.c:4728 +unusedFunction:fstapi.c:4729 // fstReaderOpenForUtilitiesOnly() -unusedFunction:fstapi.c:4721 +unusedFunction:fstapi.c:4722 // fstReaderPushScope() -unusedFunction:fstapi.c:3435 +unusedFunction:fstapi.c:3436 // fstReaderResetScope() -unusedFunction:fstapi.c:3427 +unusedFunction:fstapi.c:3428 // fstReaderSetFacProcessMask() -unusedFunction:fstapi.c:3500 +unusedFunction:fstapi.c:3501 // fstReaderSetFacProcessMaskAll() -unusedFunction:fstapi.c:3526 +unusedFunction:fstapi.c:3527 // fstReaderSetLimitTimeRange() -unusedFunction:fstapi.c:3636 +unusedFunction:fstapi.c:3637 // fstReaderSetUnlimitedTimeRange() -unusedFunction:fstapi.c:3645 +unusedFunction:fstapi.c:3646 // fstReaderSetVcdExtensions() -unusedFunction:fstapi.c:3652 +unusedFunction:fstapi.c:3653 // fstUtilityExtractEnumTableFromString() -unusedFunction:fstapi.c:6930 +unusedFunction:fstapi.c:6931 // fstUtilityFreeEnumTable() -unusedFunction:fstapi.c:6995 +unusedFunction:fstapi.c:6996 // fstWriterCreateEnumTable() unusedFunction:fstapi.c:2715 // fstWriterCreateVar2() @@ -281,6 +280,8 @@ unusedFunction:fastlz.c:418 // lz4.c from GTKWave bitwiseOnBoolean:lz4.c constVariablePointer:lz4.c +invalidPrintfArgType_sint:lz4.c +invalidPrintfArgType_uint:lz4.c staticFunction:lz4.c syntaxError:lz4.c unusedStructMember:lz4.c @@ -360,6 +361,8 @@ variableScope:sys_random.c:47 variableScope:sys_random.c:70 variableScope:sys_random.c:93 variableScope:sys_random.c:148 +// Also a comparison warning. +compareValueOutOfTypeRangeError:sys_random.c:195 // Issues in Lex/Yacc files allocaCalled:sdf_parse.c diff --git a/vpi/sys_display.c b/vpi/sys_display.c index 155ec3169..6522d20ea 100644 --- a/vpi/sys_display.c +++ b/vpi/sys_display.c @@ -838,7 +838,7 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus, vpi_printf("WARNING: %s:%d: incompatible value for %s%s.\n", info->filename, info->lineno, info->name, fmtb); } else { - PLI_INT32 veclen, word, elem, bits, byte; + PLI_INT32 veclen, word, elem, byte; char *cp; veclen = (vpi_get(vpiSize, info->items[*idx])+31)/32; @@ -849,7 +849,7 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus, for (word = 0; word < veclen; word += 1) { /* Write the aval followed by the bval in endian order. */ for (elem = 0; elem < 2; elem += 1) { - bits = *(&value.value.vector[word].aval+elem); + PLI_INT32 bits = *(&value.value.vector[word].aval+elem); #ifdef WORDS_BIGENDIAN for (byte = 3; byte >= 0; byte -= 1) { #else diff --git a/vvp/Makefile.in b/vvp/Makefile.in index 0ae99b13b..9b7f0013f 100644 --- a/vvp/Makefile.in +++ b/vvp/Makefile.in @@ -23,16 +23,19 @@ prefix = @prefix@ exec_prefix = @exec_prefix@ srcdir = @srcdir@ datarootdir = @datarootdir@ +abs_builddir = @abs_builddir@ VPATH = $(srcdir) bindir = @bindir@ libdir = @libdir@ -mandir = @mandir@ +man1dir = @mandir@/man1 +docdir = @docdir@ +pkgconfigdir = @libdir@/pkgconfig + # This is actually the directory where we install our own header files. # It is a little different from the generic includedir. -includedir = @includedir@/iverilog$(suffix) -pdfdir = @docdir@ +ivl_includedir = @includedir@/iverilog$(suffix) # For a cross compile these defines will need to be set accordingly. HOSTCC = @CC@ @@ -58,66 +61,139 @@ INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/.. endif CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ -DICARUS_VPI_CONST=const -CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@ -CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@ -LDFLAGS = @rdynamic@ @LDFLAGS@ -LIBS = @LIBS@ @EXTRALIBS@ +CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@ @PICFLAG@ +CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@ @PICFLAG@ +LDFLAGS = @rdynamic@ @LDFLAGS@ @PICFLAG@ +LIBS = @LIBS@ @EXTRALIBS@ @DLLIB@ -ifeq (@WIN32@,yes) +LIBVVP_VERSION = @LIBVVP_VERSION@ +LIBVVP_SOVERSION = @LIBVVP_SOVERSION@ +LIBBASENAME=vvp$(suffix) +LDFLAGS_SHARED = @rdynamic@ @shared@ @LDFLAGS@ + +ifeq (@MINGW32@,yes) SLDIR=$(bindir) SLEXT=dll +IMPEXT=dll.a +LIBPREFIX=lib +LIBNAME=$(LIBPREFIX)$(LIBBASENAME) +LIBSONAME=$(LIBNAME).$(SLEXT).$(LIBVVP_SOVERSION) +LIBREALNAME=$(LIBNAME).$(SLEXT).$(LIBVVP_VERSION) +LIBLINKNAME=$(LIBNAME).$(SLEXT) +LIBTARGET=$(LIBNAME)-$(LIBVVP_SOVERSION).$(SLEXT) +LIBBUILD=$(LIBTARGET) +LIBLINKFLAGS=-Wl,--out-implib,$(LIBNAME).$(IMPEXT) -Wl,--no-undefined +LIBPOSTBUILD=@true +LIBINSTALL=$(LIBTARGET) +LIBDEVELINSTALL=$(LIBNAME).$(IMPEXT) +else ifeq (@WIN32@,yes) +SLDIR=$(bindir) +SLEXT=dll +IMPEXT=lib +LIBPREFIX= +LIBNAME=$(LIBPREFIX)$(LIBBASENAME) +LIBSONAME=$(LIBNAME).$(SLEXT).$(LIBVVP_SOVERSION) +LIBREALNAME=$(LIBNAME).$(SLEXT).$(LIBVVP_VERSION) +LIBLINKNAME=$(LIBNAME).$(SLEXT) +LIBTARGET=$(LIBLINKNAME) +LIBBUILD=$(LIBLINKNAME) +LIBLINKFLAGS= +LIBPOSTBUILD=@true +LIBINSTALL=$(LIBTARGET) +LIBDEVELINSTALL= +else ifneq (,$(findstring darwin,@host_os@)) +SLDIR=$(libdir) +SLEXT=dylib +LIBPREFIX=lib +LIBNAME=$(LIBPREFIX)$(LIBBASENAME) +LIBSONAME=$(LIBNAME).$(LIBVVP_SOVERSION).$(SLEXT) +LIBREALNAME=$(LIBNAME).$(LIBVVP_VERSION).$(SLEXT) +LIBLINKNAME=$(LIBNAME).$(SLEXT) +LIBTARGET=$(LIBREALNAME) +LIBBUILD=$(LIBTARGET) +LDFLAGS_SHARED=-dynamiclib +LIBLINKFLAGS= \ + -Wl,-install_name,$(libdir)/$(LIBSONAME) \ + -Wl,-compatibility_version,$(LIBVVP_SOVERSION) \ + -Wl,-current_version,$(LIBVVP_VERSION) +LIBPOSTBUILD= \ + ln -sf $(LIBREALNAME) $(LIBSONAME) && \ + ln -sf $(LIBSONAME) $(LIBLINKNAME) +LIBINSTALL=$(LIBTARGET) +LIBDEVELINSTALL= else SLDIR=$(libdir) SLEXT=so +LIBPREFIX=lib +LIBNAME=$(LIBPREFIX)$(LIBBASENAME) +LIBSONAME=$(LIBNAME).$(SLEXT).$(LIBVVP_SOVERSION) +LIBREALNAME=$(LIBNAME).$(SLEXT).$(LIBVVP_VERSION) +LIBLINKNAME=$(LIBNAME).$(SLEXT) +LIBTARGET=$(LIBREALNAME) +LIBBUILD=$(LIBLINKNAME) +LIBLINKFLAGS=-Wl,-soname,$(LIBSONAME) +LIBPOSTBUILD=ln -sf $(LIBREALNAME) $(LIBSONAME) && ln -sf $(LIBSONAME) $(LIBLINKNAME) +LIBINSTALL=$(LIBTARGET) +LIBDEVELINSTALL= endif -dllib=@DLLIB@ - MDIR1 = -DMODULE_DIR1='"$(libdir)/ivl$(suffix)"' -VPI = vpi_modules.o vpi_bit.o vpi_callback.o vpi_cobject.o vpi_const.o vpi_darray.o \ - vpi_event.o vpi_iter.o vpi_mcd.o \ - vpi_priv.o vpi_scope.o vpi_real.o vpi_signal.o vpi_string.o vpi_tasks.o vpi_time.o \ - vpi_vthr_vector.o vpip_bin.o vpip_hex.o vpip_oct.o \ - vpip_to_dec.o vpip_format.o vvp_vpi.o +CORE_OBJ = lib_main.o \ + parse.o parse_misc.o lexor.o arith.o array_common.o array.o bufif.o compile.o \ + concat.o dff.o class_type.o enum_type.o extend.o file_line.o latch.o npmos.o part.o \ + permaheap.o reduce.o resolv.o \ + sfunc.o stop.o \ + substitute.o \ + symbols.o ufunc.o codes.o vthread.o schedule.o \ + statistics.o tables.o udp.o vvp_island.o vvp_net.o vvp_net_sig.o \ + vvp_object.o vvp_cobject.o vvp_darray.o event.o logic.o delay.o \ + words.o island_tran.o -O = lib_main.o \ - parse.o parse_misc.o lexor.o arith.o array_common.o array.o bufif.o compile.o \ - concat.o dff.o class_type.o enum_type.o extend.o file_line.o latch.o npmos.o part.o \ - permaheap.o reduce.o resolv.o \ - sfunc.o stop.o \ - substitute.o \ - symbols.o ufunc.o codes.o vthread.o schedule.o \ - statistics.o tables.o udp.o vvp_island.o vvp_net.o vvp_net_sig.o \ - vvp_object.o vvp_cobject.o vvp_darray.o event.o logic.o delay.o \ - words.o island_tran.o $(VPI) +VPI_OBJ = vpi_modules.o vpi_bit.o vpi_callback.o vpi_cobject.o vpi_const.o vpi_darray.o \ + vpi_event.o vpi_iter.o vpi_mcd.o \ + vpi_priv.o vpi_scope.o vpi_real.o vpi_signal.o vpi_string.o vpi_tasks.o vpi_time.o \ + vpi_vthr_vector.o vpip_bin.o vpip_hex.o vpip_oct.o \ + vpip_to_dec.o vpip_format.o vvp_vpi.o + +LIB_OBJ = $(CORE_OBJ) $(VPI_OBJ) +LIB_CLEAN = $(LIBNAME)*.$(SLEXT)* libvvp.pc + +VVP_OBJ = main.o +VVP_CLEAN = vvp@EXEEXT@ +ifeq (@WIN32@,yes) +# To support cocotb, we export the VPI functions directly. This allows +# cocotb to build VPI modules without using our vpi_user.h and libvpi.a. +# The .def file controls what is exported. +VVP_OBJ += $(srcdir)/vvp.def +endif +ifeq (@LIBVVP@,yes) +VVP_LDFLAGS = -lvvp$(suffix) +VVP_DEPS = $(LIBBUILD) +else +VVP_OBJ += $(LIB_OBJ) +endif +ifneq (@install_suffix@,) +VVP_POSTBUILD = ln -sf vvp@EXEEXT@ vvp$(suffix)@EXEEXT@ +VVP_CLEAN += vvp$(suffix)@EXEEXT@ +endif all: dep vvp@EXEEXT@ vvp.man +# ENV_VVP sets LD_LIBRARY_PATH by default to run vvp from the build tree check: all -ifeq (@WIN32@,yes) -ifeq (@install_suffix@,) - ./vvp -M../vpi $(srcdir)/examples/hello.vvp | grep 'Hello, World.' -else - # On Windows if we have a suffix we must run the vvp test with - # a suffix since it was built/linked that way. - ln vvp.exe vvp$(suffix).exe - ./vvp$(suffix) -M../vpi $(srcdir)/examples/hello.vvp | grep 'Hello, World.' - rm -f vvp$(suffix).exe -endif -else - $(ENV_VVP) ./vvp -M../vpi $(srcdir)/examples/hello.vvp | grep 'Hello, World.' -endif + $(ENV_VVP) ./vvp$(suffix)@EXEEXT@ -M../vpi $(srcdir)/examples/hello.vvp | grep 'Hello, World.' clean: - rm -f *.o *~ parse.cc parse.h lexor.cc tables.cc libvvp$(suffix).$(SLEXT) - rm -rf dep vvp@EXEEXT@ parse.output vvp.man vvp.ps vvp.pdf vvp.exp + rm -f *.o *~ parse.cc parse.h lexor.cc tables.cc $(LIB_CLEAN) + rm -f $(VVP_CLEAN) parse.output vvp.man vvp.ps vvp.pdf vvp.exp + rm -rf dep distclean: clean rm -f Makefile config.log rm -f stamp-config-h config.h -cppcheck: $(O:.o=.cc) draw_tt.c +cppcheck: $(LIB_OBJ:.o=.cc) draw_tt.c cppcheck --enable=all --std=c99 --std=c++11 -f \ --check-level=exhaustive \ --suppressions-list=$(srcdir)/../cppcheck-global.sup \ @@ -136,30 +212,15 @@ dep: mkdir dep ifeq (@LIBVVP@,yes) - -CPPFLAGS+= -fpic - -# To avoid setting LD_LIBRARY_PATH when running vvp from the build tree, -# add option -Wl,-rpath=`pwd` to the CXX command below. - -vvp@EXEEXT@: main.o $(srcdir)/vvp.def libvvp$(suffix).$(SLEXT) - $(CXX) $(LDFLAGS) -o vvp@EXEEXT@ main.o -L. $(LDFLAGS) -lvvp$(suffix) $(LIBS) - -libvvp$(suffix).$(SLEXT): $O - $(CXX) -shared $(LDFLAGS) -o libvvp$(suffix).$(SLEXT) $O $(LIBS) $(dllib) -else -ifeq (@WIN32@,yes) -# To support cocotb, we export the VPI functions directly. This allows -# cocotb to build VPI modules without using our vpi_user.h and libvpi.a. -# The .def file controls what is exported. -vvp@EXEEXT@: main.o $O $(srcdir)/vvp.def - $(CXX) $(LDFLAGS) -o vvp@EXEEXT@ $(LDFLAGS) $(srcdir)/vvp.def main.o $O $(dllib) $(LIBS) -else -vvp@EXEEXT@: $O main.o - $(CXX) $(LDFLAGS) -o vvp@EXEEXT@ main.o $O $(LIBS) $(dllib) -endif +$(LIBBUILD): $(LIB_OBJ) + $(CXX) $(LDFLAGS_SHARED) $(LIBLINKFLAGS) -o $(LIBTARGET) $^ $(LIBS) + $(LIBPOSTBUILD) endif +vvp@EXEEXT@: $(VVP_OBJ) $(VVP_DEPS) + $(CXX) $(LDFLAGS) -o $@ $(VVP_OBJ) -L. $(VVP_LDFLAGS) $(LIBS) + $(VVP_POSTBUILD) + %.o: %.cc config.h | dep $(CXX) $(CPPFLAGS) -DIVL_SUFFIX='"$(suffix)"' $(MDIR1) $(MDIR2) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o mv $*.d dep/$*.d @@ -186,9 +247,8 @@ parse%cc parse%h: $(srcdir)/parse%y lexor.cc: $(srcdir)/lexor.lex $(LEX) -s -o$@ $< -vvp.man: $(srcdir)/vvp.man.in ../version.exe - ../version.exe `head -1 $<`'\n' > $@ - tail -n +2 $< >> $@ +vvp.man: $(srcdir)/vvp.man.in ../config.status + cd ..; ./config.status --file=vvp/$@ vvp.ps: vvp.man $(MAN) -t ./$< > $@ @@ -196,25 +256,15 @@ vvp.ps: vvp.man vvp.pdf: vvp.ps $(PS2PDF) $< $@ +INSTALL_DOC = +ifneq ($(MAN),none) +INSTALL_DOC += installman +ifneq ($(PS2PDF),none) ifeq (@MINGW32@,yes) -ifeq ($(MAN),none) -INSTALL_DOC = installman -INSTALL_PDFDIR = $(prefix) -else -ifeq ($(PS2PDF),none) -INSTALL_DOC = installman -INSTALL_PDFDIR = $(prefix) -else -INSTALL_DOC = installpdf installman -INSTALL_PDFDIR = $(pdfdir) +INSTALL_DOC += installpdf all: vvp.pdf endif endif -INSTALL_DOCDIR = $(mandir)/man1 -else -INSTALL_DOC = installman -INSTALL_DOCDIR = $(mandir)/man1 -INSTALL_PDFDIR = $(prefix) endif stamp-config-h: $(srcdir)/config.h.in ../config.status @@ -222,36 +272,60 @@ stamp-config-h: $(srcdir)/config.h.in ../config.status cd ..; ./config.status --header=vvp/config.h config.h: stamp-config-h -install: all installdirs installfiles +install: all installdirs installfiles installpkgconfig F = ./vvp@EXEEXT@ $(srcdir)/libvvp.h $(INSTALL_DOC) installman: vvp.man installdirs - $(INSTALL_DATA) vvp.man "$(DESTDIR)$(mandir)/man1/vvp$(suffix).1" + $(INSTALL_DATA) vvp.man "$(DESTDIR)$(man1dir)/vvp$(suffix).1" installpdf: vvp.pdf installdirs - $(INSTALL_DATA) vvp.pdf "$(DESTDIR)$(pdfdir)/vvp$(suffix).pdf" + $(INSTALL_DATA) vvp.pdf "$(DESTDIR)$(docdir)/vvp$(suffix).pdf" installfiles: $(F) | installdirs $(INSTALL_PROGRAM) ./vvp@EXEEXT@ "$(DESTDIR)$(bindir)/vvp$(suffix)@EXEEXT@" ifeq (@LIBVVP@,yes) - $(INSTALL_PROGRAM) ./libvvp$(suffix).$(SLEXT) "$(DESTDIR)$(SLDIR)/libvvp$(suffix).$(SLEXT)" - $(INSTALL_DATA) $(srcdir)/libvvp.h "$(DESTDIR)$(includedir)/libvvp.h" + $(INSTALL_PROGRAM) ./$(LIBINSTALL) "$(DESTDIR)$(SLDIR)/$(LIBINSTALL)" +ifeq (@WIN32@,yes) +ifneq ($(LIBDEVELINSTALL),) + $(INSTALL_PROGRAM) ./$(LIBDEVELINSTALL) "$(DESTDIR)$(libdir)/$(LIBDEVELINSTALL)" +endif +else + # Install real library + ln -sf $(LIBREALNAME) "$(DESTDIR)$(SLDIR)/$(LIBSONAME)" + ln -sf $(LIBSONAME) "$(DESTDIR)$(SLDIR)/$(LIBLINKNAME)" +endif + $(INSTALL_DATA) $(srcdir)/libvvp.h "$(DESTDIR)$(ivl_includedir)/libvvp.h" endif installdirs: $(srcdir)/../mkinstalldirs $(srcdir)/../mkinstalldirs "$(DESTDIR)$(bindir)" \ + "$(DESTDIR)$(ivl_includedir)" \ "$(DESTDIR)$(libdir)" \ - "$(DESTDIR)$(INSTALL_DOCDIR)" \ - "$(DESTDIR)$(INSTALL_PDFDIR)" + "$(DESTDIR)$(docdir)" \ + "$(DESTDIR)$(man1dir)" +installpkgconfig: + $(INSTALL) -d "$(DESTDIR)$(pkgconfigdir)" + $(INSTALL_DATA) libvvp.pc "$(DESTDIR)$(pkgconfigdir)/libvvp$(suffix).pc" uninstall: $(UNINSTALL32) rm -f "$(DESTDIR)$(bindir)/vvp$(suffix)@EXEEXT@" - rm -f "$(DESTDIR)$(mandir)/man1/vvp$(suffix).1" "$(DESTDIR)$(pdfdir)/vvp$(suffix).pdf" + rm -f "$(DESTDIR)$(man1dir)/vvp$(suffix).1" \ + "$(DESTDIR)$(docdir)/vvp$(suffix).pdf" ifeq (@LIBVVP@,yes) - rm -f "$(DESTDIR)$(SLDIR)/libvvp$(suffix).$(SLEXT)" - rm -f "$(DESTDIR)$(includedir)/libvvp.h" + rm -f "$(DESTDIR)$(SLDIR)/$(LIBINSTALL)" +ifeq (@WIN32@,yes) +ifneq ($(LIBDEVELINSTALL),) + rm -f "$(DESTDIR)$(libdir)/$(LIBDEVELINSTALL)" +endif +else + rm -f "$(DESTDIR)$(SLDIR)/$(LIBLINKNAME)" + rm -f "$(DESTDIR)$(SLDIR)/$(LIBSONAME)" + rm -f "$(DESTDIR)$(SLDIR)/$(LIBREALNAME)" +endif + rm -f "$(DESTDIR)$(pkgconfigdir)/libvvp$(suffix).pc" + rm -f "$(DESTDIR)$(ivl_includedir)/libvvp.h" endif --include $(patsubst %.o, dep/%.d, $O) +-include $(patsubst %.o, dep/%.d, $LIB_OBJ) diff --git a/vvp/compile.cc b/vvp/compile.cc index 2831efe40..a71e1fca3 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -1642,7 +1642,7 @@ struct __vpiModPath* compile_modpath(char*label, unsigned width, } static struct __vpiModPathSrc*make_modpath_src(struct __vpiModPath*path, - char edge, + char edge_c, const struct symb_s&src, struct numbv_s&vals, bool ifnone) @@ -1660,12 +1660,12 @@ static struct __vpiModPathSrc*make_modpath_src(struct __vpiModPath*path, vvp_fun_modpath_src*obj = 0; int vpi_edge = vpiNoEdge; - if (edge == 0) { + if (edge_c == 0) { obj = new vvp_fun_modpath_src(use_delay); } else { bool posedge, negedge; - switch (edge) { + switch (edge_c) { case '+': vpi_edge = vpiPosedge; posedge = true; @@ -1685,8 +1685,8 @@ static struct __vpiModPathSrc*make_modpath_src(struct __vpiModPath*path, default: posedge = false; negedge = false; - fprintf(stderr, "Unknown edge identifier %c(%d).\n", edge, - edge); + fprintf(stderr, "Unknown edge identifier %c(%d).\n", edge_c, + edge_c); assert(0); } obj = new vvp_fun_modpath_edge(use_delay, posedge, negedge); @@ -1705,19 +1705,19 @@ static struct __vpiModPathSrc*make_modpath_src(struct __vpiModPath*path, return srcobj; } -void compile_modpath_src(struct __vpiModPath*dst, char edge, +void compile_modpath_src(struct __vpiModPath*dst, char edge_c, const struct symb_s&src, struct numbv_s&vals, const struct symb_s&condit_src, const struct symb_s&path_term_in) { struct __vpiModPathSrc*obj = - make_modpath_src(dst, edge, src, vals, false); + make_modpath_src(dst, edge_c, src, vals, false); input_connect(obj->net, 1, condit_src.text); compile_vpi_lookup(&obj->path_term_in.expr, path_term_in.text); } -void compile_modpath_src(struct __vpiModPath*dst, char edge, +void compile_modpath_src(struct __vpiModPath*dst, char edge_c, const struct symb_s&src, struct numbv_s&vals, int condit_src, @@ -1726,7 +1726,7 @@ void compile_modpath_src(struct __vpiModPath*dst, char edge, { assert(condit_src == 0); struct __vpiModPathSrc*obj = - make_modpath_src(dst, edge, src, vals, ifnone); + make_modpath_src(dst, edge_c, src, vals, ifnone); compile_vpi_lookup(&obj->path_term_in.expr, path_term_in.text); } diff --git a/vvp/compile.h b/vvp/compile.h index 6abc26439..cd1ca87b8 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -242,13 +242,13 @@ extern __vpiModPath* compile_modpath(char*label, struct symb_s drv, struct symb_s dest); extern void compile_modpath_src(__vpiModPath*dst, - char edge, + char edge_c, const struct symb_s&src, struct numbv_s&vals, const struct symb_s&condit_src, const struct symb_s&path_term_in); extern void compile_modpath_src(__vpiModPath*dst, - char edge, + char edge_c, const struct symb_s&src, struct numbv_s&vals, int condit_src, /* match with '0' */ diff --git a/vvp/cppcheck.sup b/vvp/cppcheck.sup index 39319c661..128d0ab86 100644 --- a/vvp/cppcheck.sup +++ b/vvp/cppcheck.sup @@ -37,8 +37,8 @@ useInitializationList:delay.cc:513 constParameterPointer:vpi_priv.cc:1458 // Operator new/delete are static so cannot override -duplInheritedMember:vvp_net.h:1476 -duplInheritedMember:vvp_net.h:1477 +duplInheritedMember:vvp_net.h:1481 +duplInheritedMember:vvp_net.h:1482 duplInheritedMember:vvp_net_sig.h:187 duplInheritedMember:vvp_net_sig.h:188 duplInheritedMember:vvp_net_sig.h:253 @@ -154,10 +154,10 @@ redundantAssignment:vpi_modules.cc:117 invalidScanfArgType_int:compile.cc:597 invalidScanfArgType_int:compile.cc:603 invalidScanfArgType_int:compile.cc:609 -invalidScanfArgType_int:vthread.cc:4545 -invalidScanfArgType_int:vthread.cc:4548 -invalidScanfArgType_int:vthread.cc:4551 -invalidScanfArgType_int:vthread.cc:4554 +invalidScanfArgType_int:vthread.cc:4541 +invalidScanfArgType_int:vthread.cc:4544 +invalidScanfArgType_int:vthread.cc:4547 +invalidScanfArgType_int:vthread.cc:4550 // The new() operator is always used to allocate space for this class and // pool is defined there. @@ -227,14 +227,15 @@ unusedFunction:vvp_net.cc:1752 // as_string() unusedFunction:vvp_net.cc:1855 // fully_featured_resolv_() -unusedFunction:vvp_net.cc:3581 +unusedFunction:vvp_net.cc:3704 // words() -unusedFunction:vvp_net.h:595 +unusedFunction:vvp_net.h:600 // force_vec8() unusedFunction:vvp_net_sig.cc:128 // Unused functions from the lexor duplicateBreak:lexor.lex +duplicateBreak:lexor.cc unusedStructMember:lexor.lex constVariablePointer:lexor.cc cstyleCast:lexor.cc diff --git a/vvp/delay.cc b/vvp/delay.cc index 49954b13d..af5224580 100644 --- a/vvp/delay.cc +++ b/vvp/delay.cc @@ -626,7 +626,7 @@ void vvp_fun_modpath::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit, typedef list::const_iterator iter_t; iter_t cur = candidate_list.begin(); - vvp_fun_modpath_src*src = *cur; + const vvp_fun_modpath_src*src = *cur; for (unsigned idx = 0 ; idx < 12 ; idx += 1) { out_at[idx] = src->wake_time_ + src->delay_[idx]; diff --git a/vvp/libvvp.pc.in b/vvp/libvvp.pc.in new file mode 100644 index 000000000..2e93b2233 --- /dev/null +++ b/vvp/libvvp.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libvvp@install_suffix@ +Version: @VERSION_MAJOR@.@VERSION_MINOR@ +Description: Icarus Verilog VVP runtime library +Libs: -L${libdir} -lvvp@install_suffix@ +Cflags: -I${includedir}/iverilog@install_suffix@ diff --git a/vvp/logic.cc b/vvp/logic.cc index 458cc6cb6..06285c41f 100644 --- a/vvp/logic.cc +++ b/vvp/logic.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2020 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -94,21 +94,11 @@ void vvp_fun_and::run_run() vvp_vector4_t result (input_[0]); - for (unsigned idx = 0 ; idx < result.size() ; idx += 1) { - vvp_bit4_t bitbit = result.value(idx); - for (unsigned pdx = 1 ; pdx < 4 ; pdx += 1) { - if (input_[pdx].size() < idx) { - bitbit = BIT4_X; - break; - } + for (unsigned pdx = 1 ; pdx < 4 ; pdx += 1) + result &= input_[pdx]; - bitbit = bitbit & input_[pdx].value(idx); - } - - if (invert_) - bitbit = ~bitbit; - result.set_bit(idx, bitbit); - } + if (invert_) + result.invert(); ptr->send_vec4(result, 0); } @@ -535,21 +525,11 @@ void vvp_fun_or::run_run() vvp_vector4_t result (input_[0]); - for (unsigned idx = 0 ; idx < result.size() ; idx += 1) { - vvp_bit4_t bitbit = result.value(idx); - for (unsigned pdx = 1 ; pdx < 4 ; pdx += 1) { - if (input_[pdx].size() < idx) { - bitbit = BIT4_X; - break; - } + for (unsigned pdx = 1 ; pdx < 4 ; pdx += 1) + result |= input_[pdx]; - bitbit = bitbit | input_[pdx].value(idx); - } - - if (invert_) - bitbit = ~bitbit; - result.set_bit(idx, bitbit); - } + if (invert_) + result.invert(); ptr->send_vec4(result, 0); } @@ -571,21 +551,11 @@ void vvp_fun_xor::run_run() vvp_vector4_t result (input_[0]); - for (unsigned idx = 0 ; idx < result.size() ; idx += 1) { - vvp_bit4_t bitbit = result.value(idx); - for (unsigned pdx = 1 ; pdx < 4 ; pdx += 1) { - if (input_[pdx].size() < idx) { - bitbit = BIT4_X; - break; - } + for (unsigned pdx = 1 ; pdx < 4 ; pdx += 1) + result ^= input_[pdx]; - bitbit = bitbit ^ input_[pdx].value(idx); - } - - if (invert_) - bitbit = ~bitbit; - result.set_bit(idx, bitbit); - } + if (invert_) + result.invert(); ptr->send_vec4(result, 0); } diff --git a/vvp/reduce.cc b/vvp/reduce.cc index 37afc1ea5..39362e5fb 100644 --- a/vvp/reduce.cc +++ b/vvp/reduce.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2025 Stephen Williams (steve@icarus.com) + * Copyright (c) 2005-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -97,12 +97,7 @@ vvp_reduce_and::~vvp_reduce_and() vvp_bit4_t vvp_reduce_and::calculate_result() const { - vvp_bit4_t res = BIT4_1; - - for (unsigned idx = 0 ; idx < bits_.size() ; idx += 1) - res = res & bits_.value(idx); - - return res; + return bits_.reduce_and(); } class vvp_reduce_or : public vvp_reduce_base { @@ -123,12 +118,7 @@ vvp_reduce_or::~vvp_reduce_or() vvp_bit4_t vvp_reduce_or::calculate_result() const { - vvp_bit4_t res = BIT4_0; - - for (unsigned idx = 0 ; idx < bits_.size() ; idx += 1) - res = res | bits_.value(idx); - - return res; + return bits_.reduce_or(); } class vvp_reduce_xor : public vvp_reduce_base { @@ -149,12 +139,7 @@ vvp_reduce_xor::~vvp_reduce_xor() vvp_bit4_t vvp_reduce_xor::calculate_result() const { - vvp_bit4_t res = BIT4_0; - - for (unsigned idx = 0 ; idx < bits_.size() ; idx += 1) - res = res ^ bits_.value(idx); - - return res; + return bits_.reduce_xor(); } class vvp_reduce_nand : public vvp_reduce_base { @@ -175,12 +160,7 @@ vvp_reduce_nand::~vvp_reduce_nand() vvp_bit4_t vvp_reduce_nand::calculate_result() const { - vvp_bit4_t res = BIT4_1; - - for (unsigned idx = 0 ; idx < bits_.size() ; idx += 1) - res = res & bits_.value(idx); - - return ~res; + return ~bits_.reduce_and(); } class vvp_reduce_nor : public vvp_reduce_base { @@ -201,12 +181,7 @@ vvp_reduce_nor::~vvp_reduce_nor() vvp_bit4_t vvp_reduce_nor::calculate_result() const { - vvp_bit4_t res = BIT4_0; - - for (unsigned idx = 0 ; idx < bits_.size() ; idx += 1) - res = res | bits_.value(idx); - - return ~res; + return ~bits_.reduce_or(); } class vvp_reduce_xnor : public vvp_reduce_base { @@ -227,12 +202,7 @@ vvp_reduce_xnor::~vvp_reduce_xnor() vvp_bit4_t vvp_reduce_xnor::calculate_result() const { - vvp_bit4_t res = BIT4_0; - - for (unsigned idx = 0 ; idx < bits_.size() ; idx += 1) - res = res ^ bits_.value(idx); - - return ~res; + return ~bits_.reduce_xor(); } static void make_reduce(char*label, vvp_net_fun_t*red, const struct symb_s&arg) diff --git a/vvp/vpip_to_dec.cc b/vvp/vpip_to_dec.cc index 5bb686d62..96c928c7e 100644 --- a/vvp/vpip_to_dec.cc +++ b/vvp/vpip_to_dec.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2025 Stephen Williams + * Copyright (c) 2008-2026 Stephen Williams * Copyright (c) 2002 Larry Doolittle (larry@doolittle.boa.org) * * This source code is free software; you can redistribute it @@ -58,6 +58,11 @@ #define B_ISX(x) ((x) == 2) #define B_ISZ(x) ((x) == 3) +/* Jump through some hoops so we don't have to malloc/free valv + * on every call, and implement an optional malloc-less version. */ +static unsigned long *valv=NULL; +static unsigned int vlen_alloc=0; + /* The program works by building a base BASE representation of the number * in the valv array. BBITS bits of the number can be put in at a time. * Previous values of each valv element are always less than BASE, the @@ -68,7 +73,7 @@ * less than or equal to 2^BBITS. BBITS and BASE are configured above * to depend on the "unsigned long" length of the host, for efficiency. */ -static inline void shift_in(unsigned long *valv, unsigned int vlen, unsigned long val) +static inline void shift_in(unsigned int vlen, unsigned long val) { unsigned int i; /* printf("shift in %u\n",val); */ @@ -103,11 +108,6 @@ static inline int write_digits(unsigned long v, char **buf, return zero_suppress; } -/* Jump through some hoops so we don't have to malloc/free valv - * on every call, and implement an optional malloc-less version. */ -static unsigned long *valv=NULL; -static unsigned int vlen_alloc=0; - #ifdef CHECK_WITH_VALGRIND void dec_str_delete(void) { @@ -179,7 +179,7 @@ unsigned vpip_vec4_to_dec_str(const vvp_vector4_t&vec4, if ((mbits-idx-1)%BBITS==0) { /* make negative 2's complement, not 1's complement */ if (comp && idx==mbits-1) ++val; - shift_in(valv,vlen,val); + shift_in(vlen,val); val=0; } else { val=val+val; diff --git a/vvp/vthread.cc b/vvp/vthread.cc index a85f2c226..d3dac23ac 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -4780,13 +4780,9 @@ bool of_NAND(vthread_t thr, vvp_code_t) vvp_vector4_t valr = thr->pop_vec4(); vvp_vector4_t&vall = thr->peek_vec4(); assert(vall.size() == valr.size()); - unsigned wid = vall.size(); - for (unsigned idx = 0 ; idx < wid ; idx += 1) { - vvp_bit4_t lb = vall.value(idx); - vvp_bit4_t rb = valr.value(idx); - vall.set_bit(idx, ~(lb&rb)); - } + vall &= valr; + vall.invert(); return true; } @@ -4869,24 +4865,8 @@ bool of_NOOP(vthread_t, vvp_code_t) */ bool of_NORR(vthread_t thr, vvp_code_t) { - vvp_vector4_t val = thr->pop_vec4(); - - vvp_bit4_t lb = BIT4_1; - - for (unsigned idx = 0 ; idx < val.size() ; idx += 1) { - - vvp_bit4_t rb = val.value(idx); - if (rb == BIT4_1) { - lb = BIT4_0; - break; - } - - if (rb != BIT4_0) - lb = BIT4_X; - } - - vvp_vector4_t res (1, lb); - thr->push_vec4(res); + vvp_vector4_t&val = thr->peek_vec4(); + val = vvp_vector4_t(1, ~val.reduce_or()); return true; } @@ -4906,23 +4886,8 @@ bool of_NULL(vthread_t thr, vvp_code_t) */ bool of_ANDR(vthread_t thr, vvp_code_t) { - vvp_vector4_t val = thr->pop_vec4(); - - vvp_bit4_t lb = BIT4_1; - - for (unsigned idx = 0 ; idx < val.size() ; idx += 1) { - vvp_bit4_t rb = val.value(idx); - if (rb == BIT4_0) { - lb = BIT4_0; - break; - } - - if (rb != 1) - lb = BIT4_X; - } - - vvp_vector4_t res (1, lb); - thr->push_vec4(res); + vvp_vector4_t&val = thr->peek_vec4(); + val = vvp_vector4_t(1, val.reduce_and()); return true; } @@ -4932,23 +4897,8 @@ bool of_ANDR(vthread_t thr, vvp_code_t) */ bool of_NANDR(vthread_t thr, vvp_code_t) { - vvp_vector4_t val = thr->pop_vec4(); - - vvp_bit4_t lb = BIT4_0; - for (unsigned idx = 0 ; idx < val.size() ; idx += 1) { - - vvp_bit4_t rb = val.value(idx); - if (rb == BIT4_0) { - lb = BIT4_1; - break; - } - - if (rb != BIT4_1) - lb = BIT4_X; - } - - vvp_vector4_t res (1, lb); - thr->push_vec4(res); + vvp_vector4_t&val = thr->peek_vec4(); + val = vvp_vector4_t(1, ~val.reduce_and()); return true; } @@ -4958,22 +4908,9 @@ bool of_NANDR(vthread_t thr, vvp_code_t) */ bool of_ORR(vthread_t thr, vvp_code_t) { - vvp_vector4_t val = thr->pop_vec4(); + vvp_vector4_t&val = thr->peek_vec4(); + val = vvp_vector4_t(1, val.reduce_or()); - vvp_bit4_t lb = BIT4_0; - for (unsigned idx = 0 ; idx < val.size() ; idx += 1) { - vvp_bit4_t rb = val.value(idx); - if (rb == BIT4_1) { - lb = BIT4_1; - break; - } - - if (rb != BIT4_0) - lb = BIT4_X; - } - - vvp_vector4_t res (1, lb); - thr->push_vec4(res); return true; } @@ -4982,22 +4919,9 @@ bool of_ORR(vthread_t thr, vvp_code_t) */ bool of_XORR(vthread_t thr, vvp_code_t) { - vvp_vector4_t val = thr->pop_vec4(); + vvp_vector4_t&val = thr->peek_vec4(); + val = vvp_vector4_t(1, val.reduce_xor()); - vvp_bit4_t lb = BIT4_0; - for (unsigned idx = 0 ; idx < val.size() ; idx += 1) { - - vvp_bit4_t rb = val.value(idx); - if (rb == BIT4_1) - lb = ~lb; - else if (rb != BIT4_0) { - lb = BIT4_X; - break; - } - } - - vvp_vector4_t res (1, lb); - thr->push_vec4(res); return true; } @@ -5006,22 +4930,9 @@ bool of_XORR(vthread_t thr, vvp_code_t) */ bool of_XNORR(vthread_t thr, vvp_code_t) { - vvp_vector4_t val = thr->pop_vec4(); + vvp_vector4_t&val = thr->peek_vec4(); + val = vvp_vector4_t(1, ~val.reduce_xor()); - vvp_bit4_t lb = BIT4_1; - for (unsigned idx = 0 ; idx < val.size() ; idx += 1) { - - vvp_bit4_t rb = val.value(idx); - if (rb == BIT4_1) - lb = ~lb; - else if (rb != BIT4_0) { - lb = BIT4_X; - break; - } - } - - vvp_vector4_t res (1, lb); - thr->push_vec4(res); return true; } @@ -5044,13 +4955,9 @@ bool of_NOR(vthread_t thr, vvp_code_t) vvp_vector4_t valr = thr->pop_vec4(); vvp_vector4_t&vall = thr->peek_vec4(); assert(vall.size() == valr.size()); - unsigned wid = vall.size(); - for (unsigned idx = 0 ; idx < wid ; idx += 1) { - vvp_bit4_t lb = vall.value(idx); - vvp_bit4_t rb = valr.value(idx); - vall.set_bit(idx, ~(lb|rb)); - } + vall |= valr; + vall.invert(); return true; } @@ -7789,7 +7696,7 @@ bool of_STORE_STRA(vthread_t thr, vvp_code_t cp) bool of_STORE_VEC4(vthread_t thr, vvp_code_t cp) { vvp_net_ptr_t ptr(cp->net, 0); - vvp_signal_value*sig = dynamic_cast (cp->net->fil); + const vvp_signal_value*sig = dynamic_cast (cp->net->fil); unsigned off_index = cp->bit_idx[0]; unsigned int wid = cp->bit_idx[1]; @@ -8121,14 +8028,9 @@ bool of_XNOR(vthread_t thr, vvp_code_t) vvp_vector4_t valr = thr->pop_vec4(); vvp_vector4_t&vall = thr->peek_vec4(); assert(vall.size() == valr.size()); - unsigned wid = vall.size(); - for (unsigned idx = 0 ; idx < wid ; idx += 1) { - - vvp_bit4_t lb = vall.value(idx); - vvp_bit4_t rb = valr.value(idx); - vall.set_bit(idx, ~(lb ^ rb)); - } + vall ^= valr; + vall.invert(); return true; } @@ -8141,14 +8043,8 @@ bool of_XOR(vthread_t thr, vvp_code_t) vvp_vector4_t valr = thr->pop_vec4(); vvp_vector4_t&vall = thr->peek_vec4(); assert(vall.size() == valr.size()); - unsigned wid = vall.size(); - for (unsigned idx = 0 ; idx < wid ; idx += 1) { - - vvp_bit4_t lb = vall.value(idx); - vvp_bit4_t rb = valr.value(idx); - vall.set_bit(idx, lb ^ rb); - } + vall ^= valr; return true; } diff --git a/vvp/vvp.man.in b/vvp/vvp.man.in index c7d64d9b4..8da9ef816 100644 --- a/vvp/vvp.man.in +++ b/vvp/vvp.man.in @@ -1,4 +1,4 @@ -.TH vvp 1 "Jan 13th, 2026" "" "Version %M.%n %E" +.TH vvp 1 "Jan 13th, 2026" "" "Version @VERSION@" .SH NAME vvp - Icarus Verilog vvp runtime engine diff --git a/vvp/vvp_island.h b/vvp/vvp_island.h index 9841f6bbe..68c31373e 100644 --- a/vvp/vvp_island.h +++ b/vvp/vvp_island.h @@ -218,7 +218,7 @@ struct vvp_island_branch { static inline vvp_branch_ptr_t next(vvp_branch_ptr_t cur) { - vvp_island_branch*ptr = cur.ptr(); + const vvp_island_branch*ptr = cur.ptr(); unsigned ab = cur.port(); return ptr->link[ab]; } diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index ee1e123a1..30efa58cc 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -1905,6 +1905,105 @@ void vvp_vector4_t::invert() } } +#define BIT_MASK(n) ((n) ? ((~0UL) >> (BITS_PER_WORD - (n))) : ~0UL) + +vvp_bit4_t vvp_vector4_t::reduce_or() const +{ + unsigned long mask = BIT_MASK(size_ % BITS_PER_WORD); + vvp_bit4_t res = BIT4_0; + + if (size_ <= BITS_PER_WORD) { + if ((abits_val_ & ~bbits_val_ & mask) != 0UL) + return BIT4_1; + if ((bbits_val_ & mask) != 0UL) + return BIT4_X; + } else { + unsigned words = (size_ + BITS_PER_WORD - 1) / BITS_PER_WORD; + unsigned idx; + for (idx = 0; idx < words - 1; idx += 1) { + if ((abits_ptr_[idx] & ~bbits_ptr_[idx]) != 0UL) + return BIT4_1; + if (bbits_ptr_[idx] != 0UL) + res = BIT4_X; + } + if ((abits_ptr_[idx] & ~bbits_ptr_[idx] & mask) != 0UL) + return BIT4_1; + if ((bbits_ptr_[idx] & mask) != 0UL) + res = BIT4_X; + } + + return res; +} + +vvp_bit4_t vvp_vector4_t::reduce_and() const +{ + unsigned long mask = BIT_MASK(size_ % BITS_PER_WORD); + vvp_bit4_t res = BIT4_1; + + if (size_ <= BITS_PER_WORD) { + if ((abits_val_ | bbits_val_ | ~mask) != ~0UL) + return BIT4_0; + if ((bbits_val_ & mask) != 0UL) + return BIT4_X; + } else { + unsigned words = (size_ + BITS_PER_WORD - 1) / BITS_PER_WORD; + unsigned idx; + for (idx = 0; idx < words - 1; idx += 1) { + if ((abits_ptr_[idx] | bbits_ptr_[idx]) != ~0UL) + return BIT4_0; + if (bbits_ptr_[idx] != 0UL) + res = BIT4_X; + } + if ((abits_ptr_[idx] | bbits_ptr_[idx] | ~mask) != ~0UL) + return BIT4_0; + if ((bbits_ptr_[idx] & mask) != 0UL) + res = BIT4_X; + } + + return res; +} + +static unsigned long parity(unsigned long val) +{ +#if defined(__GNUC__) + // The compiler builtin can use target-specific CPU instructions. + return __builtin_parityl(val); +#else +#if ULONG_MAX > 0xffffffffUL + val ^= val >> 32; +#endif + val ^= val >> 16; + val ^= val >> 8; + val ^= val >> 4; + + return (0x6996 >> (val & 0xf)) & 1; +#endif +} + +vvp_bit4_t vvp_vector4_t::reduce_xor() const +{ + unsigned long mask = BIT_MASK(size_ % BITS_PER_WORD); + + if (size_ <= BITS_PER_WORD) { + if ((bbits_val_ & mask) != 0UL) + return BIT4_X; + return parity(abits_val_ & mask) ? BIT4_1 : BIT4_0; + } else { + unsigned words = (size_ + BITS_PER_WORD - 1) / BITS_PER_WORD; + unsigned long val_a = 0UL; + unsigned idx; + for (idx = 0; idx < words - 1; idx += 1) { + if (bbits_ptr_[idx] != 0UL) + return BIT4_X; + val_a ^= abits_ptr_[idx]; + } + if ((bbits_ptr_[idx] & mask) != 0UL) + return BIT4_X; + val_a ^= abits_ptr_[idx] & mask; + return parity(val_a) ? BIT4_1 : BIT4_0; + } +} + vvp_vector4_t& vvp_vector4_t::operator &= (const vvp_vector4_t&that) { // The truth table is: @@ -1964,6 +2063,30 @@ vvp_vector4_t& vvp_vector4_t::operator |= (const vvp_vector4_t&that) return *this; } +vvp_vector4_t& vvp_vector4_t::operator ^= (const vvp_vector4_t&that) +{ + // The truth table is: + // 00 01 11 10 + // 00 00 01 11 11 + // 01 01 00 11 11 + // 11 11 11 11 11 + // 10 11 11 11 11 + if (size_ <= BITS_PER_WORD) { + unsigned long bval = bbits_val_ | that.bbits_val_; + bbits_val_ = bval; + abits_val_ = (abits_val_ ^ that.abits_val_) | bval; + } else { + unsigned words = (size_ + BITS_PER_WORD - 1) / BITS_PER_WORD; + for (unsigned idx = 0; idx < words ; idx += 1) { + unsigned long bval = bbits_ptr_[idx] | that.bbits_ptr_[idx]; + bbits_ptr_[idx] = bval; + abits_ptr_[idx] = (abits_ptr_[idx] ^ that.abits_ptr_[idx]) | bval; + } + } + + return *this; +} + /* * Add an integer to the vvp_vector4_t in place, bit by bit so that * there is no size limitations. diff --git a/vvp/vvp_net.h b/vvp/vvp_net.h index 5d0e77e2f..f6beeb095 100644 --- a/vvp/vvp_net.h +++ b/vvp/vvp_net.h @@ -323,8 +323,13 @@ class vvp_vector4_t { void invert(); vvp_vector4_t& operator &= (const vvp_vector4_t&that); vvp_vector4_t& operator |= (const vvp_vector4_t&that); + vvp_vector4_t& operator ^= (const vvp_vector4_t&that); vvp_vector4_t& operator += (int64_t); + vvp_bit4_t reduce_or() const; + vvp_bit4_t reduce_and() const; + vvp_bit4_t reduce_xor() const; + private: // Number of vvp_bit4_t bits that can be shoved into a word. enum { BITS_PER_WORD = 8*sizeof(unsigned long) };