Merge branch 'master' into master
This commit is contained in:
commit
8cf4507fcb
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
sphinx==8.1.3
|
||||
shibuya==2026.1.9
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
158
Makefile.in
158
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
|
||||
|
|
|
|||
62
Module.cc
62
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 <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
list<Module::named_expr_t> 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<perm_string,Module*>::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<perm_string,PModport*>::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<PEIdent*>& Module::get_port(unsigned idx) const
|
|||
ivl_assert(*this, idx < ports.size());
|
||||
static const vector<PEIdent*> 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);
|
||||
|
|
|
|||
32
Module.h
32
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<PEIdent*> 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<pform_range_t>*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<PEIdent*>& 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 */
|
||||
|
|
|
|||
44
PDelays.cc
44
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<NetEConst*>(rise);
|
||||
const NetEConst *c_fall = dynamic_cast<NetEConst*>(fall);
|
||||
const NetEConst *c_rise = dynamic_cast<const NetEConst*>(rise);
|
||||
const NetEConst *c_fall = dynamic_cast<const NetEConst*>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
8
PExpr.h
8
PExpr.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef IVL_PExpr_H
|
||||
#define IVL_PExpr_H
|
||||
/*
|
||||
* 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
|
||||
|
|
@ -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<netrange_t> &dims,
|
||||
unsigned int cur_dim) const;
|
||||
private:
|
||||
char*text_;
|
||||
};
|
||||
|
|
|
|||
41
PGate.cc
41
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<PExpr*>*pins)
|
|||
}
|
||||
|
||||
PGate::PGate(perm_string name, list<PExpr*>*pins, const list<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_delays(del);
|
||||
str0_ = IVL_DR_STRONG;
|
||||
str1_ = IVL_DR_STRONG;
|
||||
}
|
||||
|
||||
PGate::PGate(perm_string name, list<PExpr*>*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<PExpr*>*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<pform_range_t>*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
|
||||
|
|
|
|||
30
PGate.h
30
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<perm_string,PExpr*> attributes;
|
||||
|
||||
|
|
@ -109,7 +106,7 @@ class PGate : public PNamedItem {
|
|||
|
||||
std::list<pform_range_t>*ranges_;
|
||||
|
||||
ivl_drive_t str0_, str1_;
|
||||
drive_strength_t strength_;
|
||||
|
||||
void set_pins_(std::list<PExpr*>*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<PExpr*>&pins,
|
||||
const std::vector<bool>&pins_fromwc) const;
|
||||
bool match_module_ports_(Design*des, const Module*mod,
|
||||
NetScope*scope,
|
||||
std::vector<PExpr*>&pins,
|
||||
std::vector<bool>&pins_fromwc,
|
||||
std::vector<bool>&pins_is_explicitly_not_connected) const;
|
||||
// Not currently used.
|
||||
#if 0
|
||||
bool elaborate_sig_udp_(Design*des, NetScope*scope, PUdp*udp) const;
|
||||
|
|
|
|||
4
PScope.h
4
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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
|
|
|
|||
|
|
@ -4,4 +4,4 @@ nullPointerOutOfMemory:cadpli.c:53
|
|||
nullPointerOutOfMemory:cadpli.c:54
|
||||
|
||||
// Unused function
|
||||
unusedFunction:ivl_dlfcn.h:73
|
||||
unusedFunction:ivl_dlfcn.h:87
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
|||
84
configure.ac
84
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
|
||||
|
|
|
|||
59
cppcheck.sup
59
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:<stdout>
|
||||
cstyleCast:<stdout>
|
||||
duplicateBreak:<stdout>
|
||||
nullPointer:<stdout>
|
||||
redundantInitialization:<stdout>
|
||||
syntaxError:<stdout>
|
||||
|
|
|
|||
4
cprop.cc
4
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)
|
||||
|
|
|
|||
107
design_dump.cc
107
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_ <<endl;
|
||||
|
|
@ -854,10 +856,8 @@ void NetSubstitute::dump_node(ostream&fd, unsigned ind) const
|
|||
{
|
||||
fd << setw(ind) << "" << "NetSubstitute: "
|
||||
<< name();
|
||||
if (rise_time())
|
||||
fd << " #(" << *rise_time()
|
||||
<< "," << *fall_time()
|
||||
<< "," << *decay_time() << ")";
|
||||
if (delay_times().has_delay())
|
||||
fd << " #(" << delay_times() << ")";
|
||||
else
|
||||
fd << " #(.,.,.)";
|
||||
fd << " width=" << wid_ << " base=" << off_ <<endl;
|
||||
|
|
@ -877,10 +877,8 @@ void NetReplicate::dump_node(ostream&o, unsigned ind) const
|
|||
void NetSignExtend::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NetSignExtend: " << name();
|
||||
if (rise_time())
|
||||
o << " #(" << *rise_time()
|
||||
<< "," << *fall_time()
|
||||
<< "," << *decay_time() << ")";
|
||||
if (delay_times().has_delay())
|
||||
o << " #(" << delay_times() << ")";
|
||||
else
|
||||
o << " #(.,.,.)";
|
||||
o << " output width=" << width_ << endl;
|
||||
|
|
@ -914,8 +912,7 @@ void NetUReduce::dump_node(ostream&o, unsigned ind) const
|
|||
o << "xnor";
|
||||
break;
|
||||
}
|
||||
o << " #(" << rise_time()
|
||||
<< "," << fall_time() << "," << decay_time() << ") " << name()
|
||||
o << " #(" << delay_times() << ") " << name()
|
||||
<< " scope=" << scope_path(scope())
|
||||
<< endl;
|
||||
|
||||
|
|
@ -935,10 +932,8 @@ void NetUserFunc::dump_node(ostream&o, unsigned ind) const
|
|||
{
|
||||
o << setw(ind) << "" << "USER FUNC: "
|
||||
<< scope_path(def_);
|
||||
if (rise_time())
|
||||
o << " #(" <<*rise_time()
|
||||
<<","<<*fall_time()
|
||||
<< "," <<*decay_time() << ")";
|
||||
if (delay_times().has_delay())
|
||||
o << " #(" << delay_times() << ")";
|
||||
o << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
|
|
@ -986,14 +981,7 @@ void NetTran::dump_node(ostream&o, unsigned ind) const
|
|||
<< " part=" << part_width()
|
||||
<< " offset=" << part_offset();
|
||||
}
|
||||
o << " delay=(";
|
||||
if (rise_time())
|
||||
o << *rise_time() << "," << *fall_time() << ","
|
||||
<< *decay_time();
|
||||
else
|
||||
o << "0,0,0";
|
||||
|
||||
o << ")" << endl;
|
||||
o << " delay=(" << delay_times() << ")" << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
|
@ -1001,8 +989,7 @@ void NetTran::dump_node(ostream&o, unsigned ind) const
|
|||
void NetUDP::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "UDP (" << udp_name() << "): ";
|
||||
o << " #(" << rise_time() << "," << fall_time() << "," << decay_time() <<
|
||||
") " << name() << endl;
|
||||
o << " #(" << delay_times() << ") " << name() << endl;
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
|
|
|
|||
|
|
@ -31,7 +31,11 @@ suffix = @install_suffix@
|
|||
bindir = $(exec_prefix)/bin
|
||||
libdir = $(exec_prefix)/lib
|
||||
includedir = $(prefix)/include
|
||||
mandir = @mandir@
|
||||
# This is actually the directory where we install our own header files.
|
||||
# It is a little different from the generic includedir.
|
||||
ivl_includedir = @includedir@/iverilog$(suffix)
|
||||
man1dir = @mandir@/man1
|
||||
docdir = @docdir@
|
||||
|
||||
dllib=@DLLIB@
|
||||
|
||||
|
|
@ -39,8 +43,11 @@ CC = @CC@
|
|||
HOSTCC := @CC@
|
||||
WINDRES = @WINDRES@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
MAN = @MAN@
|
||||
PS2PDF = @PS2PDF@
|
||||
|
||||
ifeq (@srcdir@,.)
|
||||
INCLUDE_PATH = -I. -I..
|
||||
|
|
@ -48,19 +55,36 @@ else
|
|||
INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/..
|
||||
endif
|
||||
|
||||
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@
|
||||
CPPFLAGS = @DEFS@ $(INCLUDE_PATH) @CPPFLAGS@
|
||||
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
|
||||
CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
PICFLAGS = @PICFLAG@
|
||||
LDFLAGS = @rdynamic@ @LDFLAGS@
|
||||
|
||||
O = main.o res.o
|
||||
|
||||
ifeq (@MINGW32@,yes)
|
||||
all: iverilog-vpi@EXEEXT@
|
||||
else
|
||||
all: iverilog-vpi
|
||||
endif
|
||||
|
||||
INSTALL_DOC =
|
||||
ifneq ($(MAN),none)
|
||||
INSTALL_DOC += installman
|
||||
ifneq ($(PS2PDF),none)
|
||||
ifeq (@MINGW32@,yes)
|
||||
INSTALL_DOC += installpdf
|
||||
all: iverilog-vpi.pdf
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
check: all
|
||||
|
||||
clean:
|
||||
rm -f *.o config.h iverilog-vpi@EXEEXT@ res.rc
|
||||
rm -f *.o config.h iverilog-vpi@EXEEXT@ iverilog-vpi \
|
||||
iverilog-vpi.man iverilog-vpi.ps iverilog-vpi.pdf res.rc
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile config.log
|
||||
|
|
@ -75,8 +99,24 @@ cppcheck: main.c config.h
|
|||
Makefile: $(srcdir)/Makefile.in ../config.status
|
||||
cd ..; ./config.status --file=driver-vpi/$@
|
||||
|
||||
ifeq (@MINGW32@,yes)
|
||||
iverilog-vpi@EXEEXT@: $O
|
||||
$(CC) $(LDFLAGS) $O -o iverilog-vpi@EXEEXT@ @EXTRALIBS@
|
||||
endif
|
||||
ifeq (@MINGW32@,no)
|
||||
iverilog-vpi: $(srcdir)/iverilog-vpi.sh ../config.status
|
||||
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@;$(ivl_includedir);' \
|
||||
-e 's;@LIBDIR@;@libdir@;' $< > $@
|
||||
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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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:<stdout>
|
||||
duplicateBreak:<stdout>
|
||||
nullPointer:<stdout>
|
||||
redundantInitialization:<stdout>
|
||||
staticFunction:<stdout>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
module top;
|
||||
initial $display("Hello World!");
|
||||
endmodule
|
||||
|
|
@ -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<feature>]
|
||||
[\-g1995\:|\-g2001\:|\-g2005\:|\-g2005-sv\:|\-g2009\:|\-g2012\:|\-g2017\:|\-g2023\:|\-g<feature>]
|
||||
[\-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
|
||||
|
|
|
|||
|
|
@ -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<feature>]\n"
|
||||
"Usage: iverilog [-EiRSuvV] [-B[IMPVt] base] [-c cmdfile|-f cmdfile]\n"
|
||||
" [-g1995|-g2001|-g2005|-g2005-sv|-g2009|-g2012|-g2017|-g2023] [-g<feature>]\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);
|
||||
}
|
||||
|
||||
|
|
|
|||
116
elab_expr.cc
116
elab_expr.cc
|
|
@ -499,6 +499,9 @@ NetExpr* PEAssignPattern::elaborate_expr_uarray_(Design *des, NetScope *scope,
|
|||
if (const auto ap = dynamic_cast<PEAssignPattern*>(parms_[idx])) {
|
||||
expr = ap->elaborate_expr_uarray_(des, scope, uarray_type,
|
||||
dims, cur_dim, need_const);
|
||||
} else if (const auto s = dynamic_cast<PEString*>(parms_[idx])) {
|
||||
expr = s->elaborate_expr_uarray_(des, scope, uarray_type,
|
||||
dims, cur_dim);
|
||||
} else if (dynamic_cast<PEConcat*>(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<const NetEConstEnum*> (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<PEAssignPattern*> (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<const netarray_t*> (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<netrange_t> &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<NetExpr*> 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<const netuarray_t*>(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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
41
elab_net.cc
41
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<long> 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
|
||||
|
|
|
|||
20
elab_sig.cc
20
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()];
|
||||
|
||||
vector<PExpr*>pins (rmod->port_count());
|
||||
vector<bool>pins_fromwc (rmod->port_count(), false);
|
||||
vector<bool>pins_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;
|
||||
}
|
||||
|
|
|
|||
34
elab_type.cc
34
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<struct_member_t*>::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<const netenum_t *>(elab_type);
|
||||
break;
|
||||
case STRUCT: {
|
||||
const netstruct_t *struct_type = dynamic_cast<const netstruct_t *>(elab_type);
|
||||
type_ok = struct_type && !struct_type->union_flag();
|
||||
break;
|
||||
}
|
||||
case UNION: {
|
||||
const netstruct_t *struct_type = dynamic_cast<const netstruct_t *>(elab_type);
|
||||
type_ok = struct_type && struct_type->union_flag();
|
||||
break;
|
||||
}
|
||||
case CLASS:
|
||||
type_ok = dynamic_cast<const netclass_t *>(elab_type);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
bool type_ok = basic_type.matches(elab_type);
|
||||
|
||||
if (!type_ok) {
|
||||
cerr << data_type->get_fileline() << " error: "
|
||||
|
|
|
|||
485
elaborate.cc
485
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<NetESelect*>(rval_expr)) ||
|
||||
(dynamic_cast<NetEConcat*>(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<PEAssignPattern*> (expr)) {
|
||||
} else if (dynamic_cast<PEAssignPattern*> (expr) ||
|
||||
dynamic_cast<PEString*> (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<PEIdent*> (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<PExpr*>&pins,
|
||||
vector<bool>&pins_fromwc,
|
||||
vector<bool>&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.
|
||||
vector<PExpr*>pins (rmod->port_count());
|
||||
vector<bool>pins_fromwc (rmod->port_count(), false);
|
||||
vector<bool>pins_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<long,NetScope::interface_port_alias_t> 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<const PEIdent*>(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<const PEIdent*>(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<long,NetScope::interface_port_alias_t>*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<PExpr*>&pins,
|
||||
const vector<bool>&) 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.
|
||||
vector<PExpr*>pins (rmod->port_count());
|
||||
vector<bool>pins_fromwc (rmod->port_count(), false);
|
||||
vector<bool>pins_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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -34,4 +34,5 @@ tmp_blif.vvp
|
|||
dump.vcd
|
||||
dump.lxt
|
||||
dump.lx2
|
||||
dump.fst
|
||||
foo.vcd
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -0,0 +1 @@
|
|||
FST info: dumpfile dump.fst opened for output.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue