Compare commits

..
35 Commits
Author SHA1 Message Date
Stephen Williams cc7516eab3 Minor release update. 2016-02-10 11:39:12 -08:00
Stephen Williams 1a5ae96540 Fix broken "inherits dimensions from var/net" warning.
(cherry picked from commit 12c39aa4bb)
2016-02-10 11:23:44 -08:00
Stephen Williams 1ea8a13bf8 Prepare for 10.1 release. 2016-02-06 17:23:23 -08:00
Stephen Williams 490884cf7b Add the -Wimplicit-dimensions warning.
(cherry picked from commit f3647578d4)

Conflicts:
	scripts/devel-stub.conf
2016-02-06 16:48:43 -08:00
Martin Whitaker ca1d7ccffe Temporary fix for br993 - assertion failure in flip-flop synthesis.
(cherry-picked from master branch)

Synthesis does not currently support some commonly used styles for
representing flip-flops, e.g.

  q <= 0;
  if (en) q <= 1;

or

  if (clr) q <= 0;
  if (set) q <= 1;

For now, output a "sorry" message.
2016-01-30 22:44:26 +00:00
Martin Whitaker faf9bfe158 Fix for br994 - assertion failure when synthesising a mux.
(cherry-picked from master branch)

The elaborator allows the RHS of assignment to be wider than the
LHS. When using an if statement to represent a mux, this meant the
mux inputs could be different widths, resulting in an assertion
failure during synthesis. The fix is to prune the RHS to match the
LHS for each assignment. This has the benefit of minimising the
mux width.
2016-01-30 20:19:05 +00:00
Martin Whitaker 086ce04cf5 Temporary fix for br995 - assignment to memory not supported in synthesis.
(cherry-picked from master branch)

For now, output a "sorry" message.
2016-01-30 17:05:09 +00:00
Martin Whitaker 7b7231c417 Fix for br999 - incorrect result from binary comparison.
(cherry-picked from master branch)

When a binary (in)equality comparison has a constant left operand,
the tgt-vvp code generator swaps the left and right operands to
allow the cmpi instruction to be used. The code for swapping the
operands was incorrect.
2016-01-07 19:23:36 +00:00
Cary R d7b919f6d0 Update cppcheck suppression file 2015-12-19 11:58:38 -08:00
Cary R 9b34a96cb9 V10: Fix some compile warnings 2015-12-19 11:15:32 -08:00
Cary R 90cf0e5794 VHDL-10: fix a compile warning and add some missing newlines 2015-12-19 10:50:42 -08:00
Cary R 818379b9bc GTKWave (fstapi.c) needs realpath() so check for it 2015-12-19 09:11:56 -08:00
Cary R 9fbb7f84e6 A VHDL ExpAttribute() can share the base so don't just delete them 2015-12-13 19:02:26 -08:00
Cary R ed7d6c1002 Fix memory leak found with valgrind 2015-12-13 14:56:49 -08:00
Cary R a4306dbac1 Fix the modpath delay to ignore bits that are not changing 2015-10-21 22:02:17 -07:00
Cary R a682e13d82 Update LZ4 files to latest from GTKWave 2015-10-02 10:32:45 -07:00
Cary R 643e0a984e Fix some cppcheck warnings 2015-10-02 09:44:02 -07:00
Stephen Williams 63d2059b85 Have scope auto-rename generate names that use the index numbers
In generate blocks such as for loops, there may be many generated
scopes that have the same generated name. But in these cases, there
is an index number in the hname that can be used. So do so.

(cherry picked from commit 81f54ec0cb)
2015-09-30 09:48:56 -07:00
Martin Whitaker d9e09ceb59 Fix for GitHub issue #79 - literal numbers must have at least one digit.
(cherry-picked from master branch)

The bug report was for an assertion failure when a number contained only
a lowline (e.g. 'b_), but the standard says that a number can't start
with a lowline (e.g. 'b_1). The parser already rejected these cases for
decimal numbers, but allowed them through for binary/octal/hex numbers.
2015-09-23 00:15:50 +01:00
Stephen Williams 6d0ab9978f rpm spec file aware of stable versions. 2015-08-23 14:41:41 -07:00
Martin Whitaker e25cdf86ac Fix for br992 - prevent assertion/crash on declarations outside a module.
parse.y has been updated to allow declarations outside a module (legal
in SystemVerilog), but not all types of declaration are supported yet.
Output a sorry or error message as appropriate.
2015-08-21 00:11:59 +01:00
Stephen Williams 13bff8c50d Remove synthesis warning.
(cherry picked from commit d2c72a126d)
2015-08-20 13:53:13 -07:00
Stephen Williams b1b017251a Fix windres input version string for v10 and later. 2015-08-20 13:50:57 -07:00
Cary R e13a52637a A concatenation or the expression being replicated must have a non-zero width 2015-08-18 16:23:33 -07:00
Stephen Williams 4803f0d12b Rework vvp file version checking. 2015-08-17 15:38:27 -07:00
Martin Whitaker be44289fc0 Updated a few more copyright dates. 2015-08-17 22:23:43 +01:00
Martin Whitaker e682166253 Fix for br991 - compiler crashes due to null statements.
The reported problem was caused by a null statement in a case statement,
which caused the check for an infinite loop to fail. Further testing
exposed more problems with null statements in loop statements - these
caused crashes earlier in elaboration.
2015-08-17 22:19:36 +01:00
Larry Doolittle e2a1f21896 Squelch just a few trailing spaces in source code 2015-08-17 11:44:55 -07:00
Larry Doolittle cb73accd84 Spelling fixes 2015-08-17 11:34:58 -07:00
Stephen Williams a66361a4f2 Update some copyright dates. 2015-08-17 08:02:51 -07:00
Martin Whitaker 1159de0482 Fixed version number in vvp man page. 2015-08-16 23:11:54 +01:00
Stephen Williams ac5d4114ad Update v10 vvp examples to have correct version number 2015-08-16 12:30:43 -07:00
Stephen Williams 85f796fda2 Release compatible version stamp 2015-08-15 14:26:33 -07:00
Stephen Williams 8612ec5452 Main copyright date update. 2015-08-15 14:15:32 -07:00
Stephen Williams 870a351944 Change Version numbering scheme. 2015-08-15 13:42:57 -07:00
393 changed files with 10767 additions and 27355 deletions
-71
View File
@@ -1,71 +0,0 @@
language: cpp
sudo: required
dist: xenial
addons:
apt:
packages:
- gperf
sudo: false
notifications:
email: false
jobs:
include:
- stage: Test
os: linux
dist: xenial
before_install:
- git clone https://github.com/steveicarus/ivtest.git
- export PATH=$HOME/bin:$PATH
script:
- autoconf
- ./configure --prefix=$HOME
- make install
- make check
- cd ivtest
- perl vvp_reg.pl
- diff regression_report-devel.txt regression_report.txt
- perl vpi_reg.pl
- stage: Test
os: linux
dist: bionic
before_install:
- git clone https://github.com/steveicarus/ivtest.git
- export PATH=$HOME/bin:$PATH
script:
- autoconf
- ./configure --prefix=$HOME
- make install
- make check
- cd ivtest
- perl vvp_reg.pl
- diff regression_report-devel.txt regression_report.txt
- perl vpi_reg.pl
- stage: Test
os: windows
before_install:
- git clone https://github.com/steveicarus/ivtest.git
- choco uninstall -y mingw
- choco upgrade --no-progress -y msys2
- export msys2='cmd //C RefreshEnv.cmd '
- export msys2+='& set MSYS=winsymlinks:nativestrict '
- export msys2+='& C:\\tools\\msys64\\msys2_shell.cmd -defterm -no-start'
- export mingw64="$msys2 -mingw64 -full-path -here -c "\"\$@"\" --"
- export msys2+=" -msys2 -c "\"\$@"\" --"
- $msys2 pacman --sync --noconfirm --needed base-devel mingw-w64-x86_64-toolchain
script:
- $mingw64 ./autoconf.sh
- $mingw64 ./configure
- $mingw64 make install
- $mingw64 make check
- cd ivtest
- $mingw64 perl update_msys2_report.pl
- $mingw64 perl vvp_reg.pl
- diff --strip-trailing-cr regression_report-msys2.txt regression_report.txt
- $mingw64 perl vpi_reg.pl
+9 -13
View File
@@ -116,17 +116,13 @@ programs.
RESEARCHING EXISTING/PAST BUGS, AND FILING REPORTS
The URL <https://sourceforge.net/p/iverilog/bugs/> is the main
bug tracking system, although some users have reported bugs at
<https://github.com/steveicarus/iverilog/issues/>. Once you believe
you have found a bug, you may browse the bugs database for existing
bugs that may be related to yours. You might find that your bug has
already been fixed in a later release or snapshot. If that's the case,
then you are set. Also, consider if you are reporting a bug or really
asking for a new feature, and use the appropriate tracker.
system (although you will also find bug rep
The URL <http://sourceforge.net/tracker/?group_id=149850> is the main
bug tracking system. Once you believe you have found a bug, you may
browse the bugs database for existing bugs that may be related to
yours. You might find that your bug has already been fixed in a later
release or snapshot. If that's the case, then you are set. Also,
consider if you are reporting a bug or really asking for a new
feature, and use the appropriate tracker.
The bug database supports basic keyword searches, and you can
optionally limit your search to active bugs, or fixed bugs. You may
@@ -149,7 +145,7 @@ version from git. Please see the developer documentation for more
detailed instructions -- <http://iverilog.wikia.com/wiki/>.
When you make a patch, submit it to the "Patches" tracker at
<https://sourceforge.net/p/iverilog/patches/>. Patches added to
<http://sourceforge.net/tracker/?group_id=149850>. Patches added to
the "Patches" tracker enter the developer workflow, are checked,
applied to the appropriate git branch, and are pushed. Then the
tracker item is closed.
@@ -162,7 +158,7 @@ clarification before applying it.)
COPYRIGHT ISSUES
Icarus Verilog is Copyright (c) 1998-2018 Stephen Williams except
Icarus Verilog is Copyright (c) 1998-2008 Stephen Williams except
where otherwise noted. Minor patches are covered as derivative works
(or editorial comment or whatever the appropriate legal term is) and
folded into the rest of ivl. However, if a submission can reasonably
+54 -49
View File
@@ -70,8 +70,7 @@ dllib=@DLLIB@
HOSTCC = @CC@
HOSTCFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
BUILDCC = @CC_FOR_BUILD@
BUILDEXT = @BUILD_EXEEXT@
CC = @CC@
CXX = @CXX@
DLLTOOL = @DLLTOOL@
INSTALL = @INSTALL@
@@ -101,7 +100,7 @@ CTARGETFLAGS = @CTARGETFLAGS@
M = LineInfo.o StringHeap.o
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o t-dll-analog.o
FF = cprop.o exposenodes.o nodangle.o synth.o synth2.o syn-rules.o
FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o
O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
elab_expr.o elaborate_analog.o elab_lval.o elab_net.o \
@@ -117,10 +116,10 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
net_udp.o pad_to_width.o parse.o parse_misc.o pform.o pform_analog.o \
pform_disciplines.o pform_dump.o pform_package.o pform_pclass.o \
pform_class_type.o pform_string_type.o pform_struct_type.o pform_types.o \
symbol_search.o sync.o sys_funcs.o verinum.o verireal.o vpi_modules.o target.o \
Attrib.o HName.o Module.o PClass.o PDelays.o PEvent.o PExpr.o PFunction.o \
PGate.o PGenerate.o PModport.o PNamedItem.o PPackage.o PScope.o PSpec.o \
PTask.o PUdp.o PWire.o Statement.o AStatement.o $M $(FF) $(TT)
symbol_search.o sync.o sys_funcs.o verinum.o verireal.o target.o \
Attrib.o HName.o Module.o PClass.o PDelays.o PEvent.o PExpr.o PGate.o \
PGenerate.o PModport.o PPackage.o PScope.o PSpec.o PTask.o PUdp.o \
PFunction.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
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
@@ -128,9 +127,9 @@ all: dep config.h _pli_types.h version_tag.h ivl@EXEEXT@ version.exe iverilog-vp
# In the windows world, the installer will need a dosify program to
# dosify text files.
ifeq (@MINGW32@,yes)
all: dosify$(BUILDEXT)
dosify$(BUILDEXT): $(srcdir)/dosify.c
$(BUILDCC) $(CFLAGS) -o dosify$(BUILDEXT) $(srcdir)/dosify.c
all: dosify.exe
dosify.exe: $(srcdir)/dosify.c
$(HOSTCC) $(HOSTCFLAGS) -o dosify.exe $(srcdir)/dosify.c
endif
# This rule rules the compiler in the trivial hello.vl program to make
@@ -138,7 +137,7 @@ endif
check: all
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
test -r check.conf || cp $(srcdir)/check.conf .
driver/iverilog -B. -BMvpi -BPivlpp -tcheck -ocheck.vvp $(srcdir)/examples/hello.vl
driver/iverilog -B. -BPivlpp -tcheck -ocheck.vvp $(srcdir)/examples/hello.vl
ifeq (@WIN32@,yes)
ifeq (@install_suffix@,)
vvp/vvp -M- -M./vpi ./check.vvp | grep 'Hello, World'
@@ -157,7 +156,7 @@ 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 parse.output syn-rules.output dosify$(BUILDEXT) ivl@EXEEXT@ check.vvp
rm -f parse.output syn-rules.output dosify.exe ivl@EXEEXT@ check.vvp
rm -f lexor_keyword.cc libivl.a libvpi.a iverilog-vpi syn-rules.cc
rm -rf dep
rm -f version.exe
@@ -175,8 +174,7 @@ endif
rm -rf autom4te.cache
cppcheck: $(O:.o=.cc) $(srcdir)/dosify.c $(srcdir)/version.c
cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \
--suppressions-list=$(srcdir)/cppcheck.sup \
cppcheck --enable=all -f --suppressions-list=$(srcdir)/cppcheck.sup \
-UYYPARSE_PARAM -UYYPRINT -Ushort -Usize_t -Uyyoverflow \
-UYYTYPE_INT8 -UYYTYPE_INT16 -UYYTYPE_UINT8 -UYYTYPE_UINT16 \
--relative-paths=$(srcdir) $(INCLUDE_PATH) $^
@@ -241,7 +239,7 @@ iverilog-vpi: $(srcdir)/iverilog-vpi.sh Makefile
endif
version.exe: $(srcdir)/version.c $(srcdir)/version_base.h version_tag.h
$(BUILDCC) $(CFLAGS) -o version.exe -I. -I$(srcdir) $(srcdir)/version.c
$(HOSTCC) $(HOSTCFLAGS) -o version.exe -I. -I$(srcdir) $(srcdir)/version.c
%.o: %.cc config.h
$(CXX) $(CPPFLAGS) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o
@@ -254,9 +252,11 @@ lexor.o: lexor.cc parse.h
parse.o: parse.cc
# Use pattern rules to avoid parallel build issues (see pr3462585)
parse%cc parse%h: $(srcdir)/parse%y
$(YACC) --verbose -t -p VL --defines=parse.h -o parse.cc $<
# Build this in two steps to avoid parallel build issues (see pr3462585)
parse.cc: $(srcdir)/parse.y
$(YACC) --verbose -t -p VL -d -o $@ $<
parse.h: parse.cc
mv parse.cc.h $@ 2>/dev/null || mv parse.hh $@
syn-rules.cc: $(srcdir)/syn-rules.y
$(YACC) --verbose -t -p syn_ -o $@ $<
@@ -305,61 +305,66 @@ version_tag.h version:
ifeq (@MINGW32@,yes)
ifeq ($(MAN),none)
INSTALL_DOC = installman
INSTALL_DOC = $(mandir)/man1/iverilog-vpi$(suffix).1
else
ifeq ($(PS2PDF),none)
INSTALL_DOC = installman
INSTALL_DOC = $(mandir)/man1/iverilog-vpi$(suffix).1
else
INSTALL_DOC = installpdf installman
INSTALL_DOC = $(prefix)/iverilog-vpi$(suffix).pdf $(mandir)/man1/iverilog-vpi$(suffix).1
all: dep iverilog-vpi.pdf
endif
endif
INSTALL_DOCDIR = $(mandir)/man1
else
INSTALL_DOC = installman
INSTALL_DOC = $(mandir)/man1/iverilog-vpi$(suffix).1
INSTALL_DOCDIR = $(mandir)/man1
endif
ifeq (@MINGW32@,yes)
WIN32_INSTALL =
else
WIN32_INSTALL = installwin32
WIN32_INSTALL = $(bindir)/iverilog-vpi$(suffix)
endif
install: all installdirs installfiles
install: all installdirs $(libdir)/ivl$(suffix)/ivl@EXEEXT@ $(libdir)/ivl$(suffix)/include/constants.vams $(libdir)/ivl$(suffix)/include/disciplines.vams $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/sv_vpi_user.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
F = ./ivl@EXEEXT@ \
$(srcdir)/constants.vams \
$(srcdir)/disciplines.vams \
$(srcdir)/ivl_target.h \
./_pli_types.h \
$(srcdir)/sv_vpi_user.h \
$(srcdir)/vpi_user.h \
$(srcdir)/acc_user.h \
$(srcdir)/veriuser.h \
$(INSTALL_DOC) \
$(WIN32_INSTALL)
installwin32: ./iverilog-vpi installdirs
$(bindir)/iverilog-vpi$(suffix): ./iverilog-vpi
$(INSTALL_SCRIPT) ./iverilog-vpi "$(DESTDIR)$(bindir)/iverilog-vpi$(suffix)"
installman: iverilog-vpi.man installdirs
$(libdir)/ivl$(suffix)/ivl@EXEEXT@: ./ivl@EXEEXT@
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ "$(DESTDIR)$(libdir)/ivl$(suffix)/ivl@EXEEXT@"
$(libdir)/ivl$(suffix)/include/constants.vams: $(srcdir)/constants.vams
$(INSTALL_DATA) $(srcdir)/constants.vams "$(DESTDIR)$(libdir)/ivl$(suffix)/include/constants.vams"
$(libdir)/ivl$(suffix)/include/disciplines.vams: $(srcdir)/disciplines.vams
$(INSTALL_DATA) $(srcdir)/disciplines.vams "$(DESTDIR)$(libdir)/ivl$(suffix)/include/disciplines.vams"
$(includedir)/ivl_target.h: $(srcdir)/ivl_target.h
$(INSTALL_DATA) $(srcdir)/ivl_target.h "$(DESTDIR)$(includedir)/ivl_target.h"
$(includedir)/_pli_types.h: _pli_types.h
$(INSTALL_DATA) $< "$(DESTDIR)$(includedir)/_pli_types.h"
$(includedir)/sv_vpi_user.h: $(srcdir)/sv_vpi_user.h
$(INSTALL_DATA) $(srcdir)/sv_vpi_user.h "$(DESTDIR)$(includedir)/sv_vpi_user.h"
$(includedir)/vpi_user.h: $(srcdir)/vpi_user.h
$(INSTALL_DATA) $(srcdir)/vpi_user.h "$(DESTDIR)$(includedir)/vpi_user.h"
$(includedir)/acc_user.h: $(srcdir)/acc_user.h
$(INSTALL_DATA) $(srcdir)/acc_user.h "$(DESTDIR)$(includedir)/acc_user.h"
$(includedir)/veriuser.h: $(srcdir)/veriuser.h
$(INSTALL_DATA) $(srcdir)/veriuser.h "$(DESTDIR)$(includedir)/veriuser.h"
$(mandir)/man1/iverilog-vpi$(suffix).1: iverilog-vpi.man
$(INSTALL_DATA) iverilog-vpi.man "$(DESTDIR)$(mandir)/man1/iverilog-vpi$(suffix).1"
installpdf: iverilog-vpi.pdf installdirs
$(prefix)/iverilog-vpi$(suffix).pdf: iverilog-vpi.pdf
$(INSTALL_DATA) iverilog-vpi.pdf "$(DESTDIR)$(prefix)/iverilog-vpi$(suffix).pdf"
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"
installdirs: $(srcdir)/mkinstalldirs
$(srcdir)/mkinstalldirs "$(DESTDIR)$(bindir)" \
+5 -12
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2019 Stephen Williams ([email protected])
* Copyright (c) 1998-2010 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -32,9 +32,12 @@ Module::Module(LexicalScope*parent, perm_string n)
{
library_flag = false;
is_cell = false;
is_interface = false;
program_block = false;
uc_drive = UCD_NONE;
timescale_warn_done = false;
time_unit = 0;
time_precision = 0;
time_from_timescale = false;
}
Module::~Module()
@@ -122,13 +125,3 @@ const list<PGate*>& Module::get_gates() const
{
return gates_;
}
PNamedItem::SymbolType Module::symbol_type() const
{
if (program_block)
return PROGRAM;
if (is_interface)
return INTERFACE;
return MODULE;
}
+10 -6
View File
@@ -1,7 +1,7 @@
#ifndef IVL_Module_H
#define IVL_Module_H
/*
* Copyright (c) 1998-2019 Stephen Williams ([email protected])
* Copyright (c) 1998-2015 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -28,7 +28,7 @@
# include "HName.h"
# include "named.h"
# include "PScope.h"
# include "PNamedItem.h"
# include "LineInfo.h"
# include "netlist.h"
# include "pform_types.h"
class PExpr;
@@ -54,7 +54,7 @@ class NetScope;
* these containers as well.
*/
class Module : public PScopeExtra, public PNamedItem {
class Module : public PScopeExtra, public LineInfo {
/* The module ports are in general a vector of port_t
objects. Each port has a name and an ordered list of
@@ -97,7 +97,7 @@ class Module : public PScopeExtra, public PNamedItem {
/* specparams are simpler than other parameters, in that they
can have a range, but not an explicit type. The restrictions
are enforced by the parser. */
map<perm_string,param_expr_t*>specparams;
map<perm_string,param_expr_t>specparams;
/* The module also has defparam assignments which don't create
new parameters within the module, but may be used to set
@@ -121,6 +121,12 @@ class Module : public PScopeExtra, public PNamedItem {
map<perm_string,PExpr*> attributes;
/* These are the timescale for this module. The default is
set by the `timescale directive. */
int time_unit, time_precision;
bool time_from_timescale;
bool timescale_warn_done;
/* The module has a list of generate schemes that appear in
the module definition. These are used at elaboration time. */
list<PGenerate*> generate_schemes;
@@ -160,8 +166,6 @@ class Module : public PScopeExtra, public PNamedItem {
bool elaborate_sig(Design*, NetScope*scope) const;
SymbolType symbol_type() const;
private:
void dump_specparams_(ostream&out, unsigned indent) const;
list<PGate*> gates_;
+1 -6
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2019 Stephen Williams ([email protected])
* Copyright (c) 2012 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -28,8 +28,3 @@ PClass::PClass(perm_string name, LexicalScope*parent)
PClass::~PClass()
{
}
PNamedItem::SymbolType PClass::symbol_type() const
{
return CLASS;
}
+3 -5
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PClass_H
#define IVL_PClass_H
/*
* Copyright (c) 2012-2019 Stephen Williams ([email protected])
* Copyright (c) 2012-2014 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -20,7 +20,7 @@
*/
# include "PScope.h"
# include "PNamedItem.h"
# include "LineInfo.h"
# include "StringHeap.h"
# include <iostream>
@@ -32,7 +32,7 @@ class PChainConstructor;
* collected.
*/
class PClass : public PScopeExtra, public PNamedItem {
class PClass : public PScopeExtra, public LineInfo {
public:
explicit PClass (perm_string name, LexicalScope*parent);
@@ -40,8 +40,6 @@ class PClass : public PScopeExtra, public PNamedItem {
void dump(std::ostream&out, unsigned indent) const;
SymbolType symbol_type() const;
public:
class_type_t*type;
};
+19 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2017 Stephen Williams ([email protected])
* Copyright (c) 1999-2011 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -26,6 +26,11 @@
# include "verinum.h"
# include "netmisc.h"
bool dly_used_no_timescale = false;
bool dly_used_timescale = false;
bool display_ts_dly_warning = true;
PDelays::PDelays()
{
delete_flag_ = true;
@@ -75,7 +80,19 @@ static NetExpr*calculate_val(Design*des, NetScope*scope, PExpr*expr)
{
NetExpr*dex = elab_and_eval(des, scope, expr, -1);
check_for_inconsistent_delays(scope);
/* Print a warning if we find default and `timescale based
* delays in the design, since this is likely an error. */
if (scope->time_from_timescale()) dly_used_timescale = true;
else dly_used_no_timescale = true;
if (display_ts_dly_warning &&
dly_used_no_timescale && dly_used_timescale) {
cerr << "warning: Found both default and "
"`timescale based delays. Use" << endl;
cerr << " -Wtimescale to find the "
"module(s) with no `timescale." << endl;
display_ts_dly_warning = false;
}
/* If the delay expression is a real constant or vector
constant, then evaluate it, scale it to the local time
+1 -5
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2004-2019 Stephen Williams ([email protected])
* Copyright (c) 2004 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -35,7 +35,3 @@ perm_string PEvent::name() const
return name_;
}
PNamedItem::SymbolType PEvent::symbol_type() const
{
return EVENT;
}
+3 -5
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PEvent_H
#define IVL_PEvent_H
/*
* Copyright (c) 2000-2019 Stephen Williams ([email protected])
* Copyright (c) 2000-2014 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -19,7 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "PNamedItem.h"
# include "LineInfo.h"
# include "StringHeap.h"
# include <string>
@@ -31,7 +31,7 @@ class NetScope;
* are declared in Verilog as ``event foo;'' The name passed to the
* constructor is the "foo" part of the declaration.
*/
class PEvent : public PNamedItem {
class PEvent : public LineInfo {
public:
// The name is a perm-allocated string. It is the simple name
@@ -43,8 +43,6 @@ class PEvent : public PNamedItem {
void elaborate_scope(Design*des, NetScope*scope) const;
SymbolType symbol_type() const;
private:
perm_string name_;
+13 -12
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2020 Stephen Williams <[email protected]>
* Copyright (c) 1998-2012 Stephen Williams <[email protected]>
* Copyright CERN 2013 / Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
@@ -126,8 +126,9 @@ PEBinary::~PEBinary()
void PEBinary::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
{
if (left_) left_->declare_implicit_nets(scope, type);
if (right_) right_->declare_implicit_nets(scope, type);
assert(left_ && right_);
left_->declare_implicit_nets(scope, type);
right_->declare_implicit_nets(scope, type);
}
bool PEBinary::has_aa_term(Design*des, NetScope*scope) const
@@ -136,7 +137,7 @@ bool PEBinary::has_aa_term(Design*des, NetScope*scope) const
return left_->has_aa_term(des, scope) || right_->has_aa_term(des, scope);
}
PECastSize::PECastSize(PExpr*si, PExpr*b)
PECastSize::PECastSize(unsigned si, PExpr*b)
: size_(si), base_(b)
{
}
@@ -168,7 +169,7 @@ PEBComp::~PEBComp()
PEBLogic::PEBLogic(char op, PExpr*l, PExpr*r)
: PEBinary(op, l, r)
{
assert(op == 'a' || op == 'o' || op == 'q' || op == 'Q');
assert(op == 'a' || op == 'o');
}
PEBLogic::~PEBLogic()
@@ -203,12 +204,12 @@ PEBShift::~PEBShift()
}
PECallFunction::PECallFunction(const pform_name_t&n, const vector<PExpr *> &parms)
: package_(0), path_(n), parms_(parms), is_overridden_(false)
: package_(0), path_(n), parms_(parms)
{
}
PECallFunction::PECallFunction(PPackage*pkg, const pform_name_t&n, const vector<PExpr *> &parms)
: package_(pkg), path_(n), parms_(parms), is_overridden_(false)
: package_(pkg), path_(n), parms_(parms)
{
}
@@ -221,7 +222,7 @@ static pform_name_t pn_from_ps(perm_string n)
}
PECallFunction::PECallFunction(PPackage*pkg, perm_string n, const list<PExpr *> &parms)
: package_(pkg), path_(pn_from_ps(n)), parms_(parms.size()), is_overridden_(false)
: package_(pkg), path_(pn_from_ps(n)), parms_(parms.size())
{
int tmp_idx = 0;
assert(parms_.size() == parms.size());
@@ -231,18 +232,18 @@ PECallFunction::PECallFunction(PPackage*pkg, perm_string n, const list<PExpr *>
}
PECallFunction::PECallFunction(perm_string n, const vector<PExpr*>&parms)
: package_(0), path_(pn_from_ps(n)), parms_(parms), is_overridden_(false)
: package_(0), path_(pn_from_ps(n)), parms_(parms)
{
}
PECallFunction::PECallFunction(perm_string n)
: package_(0), path_(pn_from_ps(n)), is_overridden_(false)
: package_(0), path_(pn_from_ps(n))
{
}
// NOTE: Anachronism. Try to work all use of svector out.
PECallFunction::PECallFunction(const pform_name_t&n, const list<PExpr *> &parms)
: package_(0), path_(n), parms_(parms.size()), is_overridden_(false)
: package_(0), path_(n), parms_(parms.size())
{
int tmp_idx = 0;
assert(parms_.size() == parms.size());
@@ -252,7 +253,7 @@ PECallFunction::PECallFunction(const pform_name_t&n, const list<PExpr *> &parms)
}
PECallFunction::PECallFunction(perm_string n, const list<PExpr*>&parms)
: package_(0), path_(pn_from_ps(n)), parms_(parms.size()), is_overridden_(false)
: package_(0), path_(pn_from_ps(n)), parms_(parms.size())
{
int tmp_idx = 0;
assert(parms_.size() == parms.size());
+11 -12
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PExpr_H
#define IVL_PExpr_H
/*
* Copyright (c) 1998-2019 Stephen Williams <[email protected]>
* Copyright (c) 1998-2014 Stephen Williams <[email protected]>
* Copyright CERN 2013 / Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
@@ -379,8 +379,6 @@ class PEIdent : public PExpr {
virtual bool is_collapsible_net(Design*des, NetScope*scope) const;
const PPackage* package() const { return package_; }
const pform_name_t& path() const { return path_; }
private:
@@ -435,10 +433,10 @@ class PEIdent : public PExpr {
bool need_const_idx) const;
NetAssign_*elaborate_lval_net_class_member_(Design*, NetScope*,
NetNet*,
pform_name_t) const;
const perm_string&) const;
bool elaborate_lval_net_packed_member_(Design*, NetScope*,
NetAssign_*,
pform_name_t member_path) const;
const name_component_t&) const;
bool elaborate_lval_darray_bit_(Design*, NetScope*,
NetAssign_*) const;
@@ -523,13 +521,17 @@ class PEIdent : public PExpr {
unsigned flags) const;
unsigned test_width_method_(Design*des, NetScope*scope, width_mode_t&mode);
NetExpr*elaborate_expr_method_(Design*des,
NetScope*scope,
unsigned expr_wid,
unsigned flags) const;
private:
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
bool bidirectional_flag) const;
NetAssign_*scan_lname_for_nested_members_(Design*des, NetScope*scope,
const pform_name_t&path) const;
bool eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
long&midx, long&lidx) const;
};
@@ -928,9 +930,6 @@ class PECallFunction : public PExpr {
pform_name_t path_;
std::vector<PExpr *> parms_;
// For system functions.
bool is_overridden_;
bool check_call_matches_definition_(Design*des, NetScope*dscope) const;
@@ -972,7 +971,7 @@ class PECallFunction : public PExpr {
class PECastSize : public PExpr {
public:
explicit PECastSize(PExpr*size, PExpr*base);
explicit PECastSize(unsigned expr_wid, PExpr*base);
~PECastSize();
void dump(ostream &out) const;
@@ -985,7 +984,7 @@ class PECastSize : public PExpr {
width_mode_t&mode);
private:
PExpr* size_;
unsigned size_;
PExpr* base_;
};
+3 -9
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2019 Stephen Williams ([email protected])
* Copyright (c) 1999-2013 Stephen Williams ([email protected])
*
* 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,7 +43,7 @@ void PFunction::set_statement(Statement*s)
void PFunction::push_statement_front(Statement*stmt)
{
// This should not be possible.
// This can only happen after the statement is initially set.
ivl_assert(*this, statement_);
// Get the PBlock of the statement. If it is not a PBlock,
@@ -75,8 +75,7 @@ PChainConstructor* PFunction::extract_chain_constructor()
PChainConstructor*res = 0;
if ((res = dynamic_cast<PChainConstructor*> (statement_))) {
statement_ = new PBlock(PBlock::BL_SEQ);
statement_->set_line(*this);
statement_ = 0;
} else if (PBlock*blk = dynamic_cast<PBlock*>(statement_)) {
res = blk->extract_chain_constructor();
@@ -84,8 +83,3 @@ PChainConstructor* PFunction::extract_chain_constructor()
return res;
}
PNamedItem::SymbolType PFunction::symbol_type() const
{
return FUNCTION;
}
+1 -6
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2019 Stephen Williams ([email protected])
* Copyright (c) 1999-2013 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -117,11 +117,6 @@ unsigned PGate::delay_count() const
return delay_.delay_count();
}
PNamedItem::SymbolType PGate::symbol_type() const
{
return INSTANCE;
}
PGAssign::PGAssign(list<PExpr*>*pins)
: PGate(perm_string(), pins)
{
+3 -7
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PGate_H
#define IVL_PGate_H
/*
* Copyright (c) 1998-2019 Stephen Williams ([email protected])
* Copyright (c) 1998-2014 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -22,7 +22,7 @@
# include "svector.h"
# include "StringHeap.h"
# include "named.h"
# include "PNamedItem.h"
# include "LineInfo.h"
# include "PDelays.h"
# include "netlist.h"
# include <map>
@@ -47,7 +47,7 @@ class Module;
* single strength pair. There is a strength of the 0 drive, and a
* strength of the 1 drive.
*/
class PGate : public PNamedItem {
class PGate : public LineInfo {
public:
explicit PGate(perm_string name, list<PExpr*>*pins,
@@ -88,8 +88,6 @@ class PGate : public PNamedItem {
virtual void elaborate_scope(Design*des, NetScope*sc) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
SymbolType symbol_type() const;
protected:
const vector<PExpr*>& get_pins() const { return pins_; }
@@ -219,8 +217,6 @@ class PGModule : public PGate {
// method to pass the range to the pform.
void set_range(PExpr*msb, PExpr*lsb);
map<perm_string,PExpr*> attributes;
virtual void dump(ostream&out, unsigned ind =4) const;
virtual void elaborate(Design*, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*sc) const;
+1 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2020 Stephen Williams ([email protected])
* Copyright (c) 2006-2011 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -26,7 +26,6 @@ PGenerate::PGenerate(LexicalScope*parent, unsigned id)
{
direct_nested_ = false;
scheme_type = GS_NONE;
local_index = false;
loop_init = 0;
loop_test = 0;
loop_step = 0;
@@ -113,8 +112,3 @@ ostream& operator << (ostream&out, PGenerate::scheme_t type)
}
return out;
}
PNamedItem::SymbolType PGenerate::symbol_type() const
{
return GENBLOCK;
}
+3 -8
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PGenerate_H
#define IVL_PGenerate_H
/*
* Copyright (c) 2006-2020 Stephen Williams ([email protected])
* Copyright (c) 2006-2014 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -19,7 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "PNamedItem.h"
# include "LineInfo.h"
# include "StringHeap.h"
# include "HName.h"
# include "PScope.h"
@@ -50,7 +50,7 @@ class PWire;
* The parent points to the GS_CASE that contains this item.
* the loop_test is compared with the parent->loop_test expression.
*/
class PGenerate : public PNamedItem, public LexicalScope {
class PGenerate : public LineInfo, public LexicalScope {
public:
explicit PGenerate(LexicalScope*parent, unsigned id_number);
@@ -71,9 +71,6 @@ class PGenerate : public PNamedItem, public LexicalScope {
// generate loops have an index variable and three
// expressions: for (index = <init>; <test>; index=<step>)
// the index is local if it was declared in the init expression,
// e.g. for (genvar index = <init>; <test>; index=<step>)
bool local_index;
perm_string loop_index;
PExpr*loop_init;
PExpr*loop_test;
@@ -110,8 +107,6 @@ class PGenerate : public PNamedItem, public LexicalScope {
void dump(ostream&out, unsigned indent) const;
SymbolType symbol_type() const;
private:
bool generate_scope_loop_(Design*des, NetScope*container);
bool generate_scope_condit_(Design*des, NetScope*container, bool else_flag);
+1 -6
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2019 Stephen Williams ([email protected])
* Copyright (c) 2015 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -29,8 +29,3 @@ PModport::PModport(perm_string n)
PModport::~PModport()
{
}
PNamedItem::SymbolType PModport::symbol_type() const
{
return MODPORT;
}
+3 -5
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PModport_H
#define IVL_PModport_H
/*
* Copyright (c) 2015-2019 Stephen Williams ([email protected])
* Copyright (c) 2015 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -19,7 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "PNamedItem.h"
# include "LineInfo.h"
# include "PScope.h"
# include "StringHeap.h"
# include "netlist.h"
@@ -28,7 +28,7 @@
/*
* The PModport class represents a parsed SystemVerilog modport list.
*/
class PModport : public PNamedItem {
class PModport : public LineInfo {
public:
// The name is a perm-allocated string. It is the simple name
@@ -41,8 +41,6 @@ class PModport : public PNamedItem {
typedef pair <NetNet::PortType,PExpr*> simple_port_t;
map<perm_string,simple_port_t> simple_ports;
SymbolType symbol_type() const;
private:
perm_string name_;
-116
View File
@@ -1,116 +0,0 @@
/*
* Copyright (c) 2019 Martin Whitaker ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "PNamedItem.h"
# include <ostream>
PNamedItem::PNamedItem()
{
}
PNamedItem::~PNamedItem()
{
}
PNamedItem::SymbolType PNamedItem::symbol_type() const
{
return ANY;
}
std::ostream& operator << (std::ostream&o, PNamedItem::SymbolType st)
{
switch (st) {
case PNamedItem::ANY:
o << "a symbol";
break;
case PNamedItem::PARAM:
o << "a parameter";
break;
case PNamedItem::NET:
o << "a net";
break;
case PNamedItem::VAR:
o << "a variable";
break;
case PNamedItem::GENVAR:
o << "a genvar";
break;
case PNamedItem::EVENT:
o << "an event";
break;
case PNamedItem::TYPE:
o << "a type";
break;
case PNamedItem::ENUM:
o << "an enum type or value";
break;
case PNamedItem::CLASS:
o << "a class";
break;
case PNamedItem::FUNCTION:
o << "a function";
break;
case PNamedItem::TASK:
o << "a task";
break;
case PNamedItem::BLOCK:
o << "a named block";
break;
case PNamedItem::GENBLOCK:
o << "a generate block";
break;
case PNamedItem::MODPORT:
o << "a modport";
break;
case PNamedItem::PACKAGE:
o << "a package";
break;
case PNamedItem::MODULE:
o << "a module";
break;
case PNamedItem::PROGRAM:
o << "a program";
break;
case PNamedItem::INTERFACE:
o << "an interface";
break;
case PNamedItem::PRIMITIVE:
o << "a primitive";
break;
case PNamedItem::INSTANCE:
o << "an instance name";
break;
default:
break;
}
return o;
}
PGenvar::PGenvar()
{
}
PGenvar::~PGenvar()
{
}
PNamedItem::SymbolType PGenvar::symbol_type() const
{
return GENVAR;
}
-57
View File
@@ -1,57 +0,0 @@
#ifndef IVL_PNamedItem_H
#define IVL_PNamedItem_H
/*
* Copyright (c) 2019 Martin Whitaker ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "LineInfo.h"
/*
* The PNamedItem class is the base class for all items that can be added
* to a scope's local symbol map.
*/
class PNamedItem : virtual public LineInfo {
public:
enum SymbolType { ANY, PARAM, NET, VAR, GENVAR, EVENT, TYPE, ENUM,
CLASS, FUNCTION, TASK, BLOCK, GENBLOCK, MODPORT,
PACKAGE, MODULE, PROGRAM, INTERFACE, PRIMITIVE,
INSTANCE };
explicit PNamedItem();
virtual ~PNamedItem();
virtual SymbolType symbol_type() const;
};
extern std::ostream& operator << (std::ostream&, PNamedItem::SymbolType);
/*
* The PGenvar class represents a genvar. This is only used to represent
* genvar in a scope's local symbol map.
*/
class PGenvar : public PNamedItem {
public:
explicit PGenvar();
virtual ~PGenvar();
SymbolType symbol_type() const;
};
#endif /* IVL_PNamedItem_H */
+21 -26
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008-2019 Stephen Williams ([email protected])
* Copyright (c) 2008,2010 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -19,9 +19,21 @@
# include "PScope.h"
bool LexicalScope::var_init_needs_explicit_lifetime() const
PScope::PScope(perm_string n, LexicalScope*parent)
: LexicalScope(parent), name_(n)
{
return false;
}
PScope::PScope(perm_string n)
: LexicalScope(0), name_(n)
{
}
PScope::~PScope()
{
for(map<perm_string, data_type_t*>::iterator it = typedefs.begin();
it != typedefs.end(); ++it)
delete it->second;
}
PWire* LexicalScope::wires_find(perm_string name)
@@ -33,34 +45,17 @@ PWire* LexicalScope::wires_find(perm_string name)
return (*cur).second;
}
PNamedItem::SymbolType LexicalScope::param_expr_t::symbol_type() const
{
return PARAM;
}
PScope::PScope(perm_string n, LexicalScope*parent)
: LexicalScope(parent), name_(n)
{
time_unit = 0;
time_precision = 0;
time_unit_is_default = true;
time_prec_is_default = true;
}
PScope::~PScope()
{
for(map<perm_string, data_type_t*>::iterator it = typedefs.begin();
it != typedefs.end(); ++it)
delete it->second;
}
PScopeExtra::PScopeExtra(perm_string n, LexicalScope*parent)
: PScope(n, parent)
{
time_unit_is_local = false;
time_prec_is_local = false;
}
PScopeExtra::PScopeExtra(perm_string n)
: PScope(n)
{
}
PScopeExtra::~PScopeExtra()
{
}
+15 -60
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PScope_H
#define IVL_PScope_H
/*
* Copyright (c) 2008-2019 Stephen Williams ([email protected])
* Copyright (c) 2008-2014 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -19,7 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "PNamedItem.h"
# include "LineInfo.h"
# include "StringHeap.h"
# include "pform_types.h"
# include "ivl_target.h"
@@ -36,7 +36,6 @@ class PProcess;
class PClass;
class PTask;
class PWire;
class Statement;
class Design;
class NetScope;
@@ -53,32 +52,10 @@ class NetScope;
class LexicalScope {
public:
enum lifetime_t { INHERITED, STATIC, AUTOMATIC };
explicit LexicalScope(LexicalScope*parent) : default_lifetime(INHERITED), parent_(parent) { }
explicit LexicalScope(LexicalScope*parent) : parent_(parent) { }
// A virtual destructor is so that dynamic_cast can work.
virtual ~LexicalScope() { }
lifetime_t default_lifetime;
// Symbols that are defined or declared in this scope.
std::map<perm_string,PNamedItem*>local_symbols;
// Symbols that are explicitly imported. Bind the imported name
// to the package from which the name is imported.
std::map<perm_string,PPackage*>explicit_imports;
// Packages that are wildcard imported. When identifiers from
// these packages are referenced, they will be added to the
// explicit imports (IEEE 1800-2012 26.3).
std::set<PPackage*>potential_imports;
// A task or function call may reference a task or function defined
// later in the scope. So here we stash the potential imports for
// task and function calls. They will be added to the explicit
// imports if we don't find a local definition.
std::map<perm_string,PPackage*>possible_imports;
struct range_t {
// True if this is an exclude
bool exclude_flag;
@@ -97,7 +74,7 @@ class LexicalScope {
/* The scope has parameters that are evaluated when the scope
is elaborated. During parsing, I put the parameters into
this map. */
struct param_expr_t : public PNamedItem {
struct param_expr_t : public LineInfo {
param_expr_t() : type(IVL_VT_NO_TYPE), msb(0), lsb(0), signed_flag(false), expr(0), range(0) { }
// Type information
ivl_variable_type_t type;
@@ -108,11 +85,9 @@ class LexicalScope {
PExpr*expr;
// If there are range constraints, list them here
range_t*range;
SymbolType symbol_type() const;
};
map<perm_string,param_expr_t*>parameters;
map<perm_string,param_expr_t*>localparams;
map<perm_string,param_expr_t>parameters;
map<perm_string,param_expr_t>localparams;
// Defined types in the scope.
map<perm_string,data_type_t*>typedefs;
@@ -120,6 +95,10 @@ class LexicalScope {
// Named events in the scope.
map<perm_string,PEvent*>events;
// Symbols that are imported. Bind the imported name to the
// package from which the name is imported.
std::map<perm_string,PPackage*>imports;
// Nets and variables (wires) in the scope
map<perm_string,PWire*>wires;
PWire* wires_find(perm_string name);
@@ -129,9 +108,6 @@ class LexicalScope {
// creating implicit nets.
map<perm_string,LineInfo*> genvars;
// Variable initializations in this scope
vector<Statement*> var_inits;
// Behaviors (processes) in this scope
list<PProcess*> behaviors;
list<AProcess*> analog_behaviors;
@@ -141,8 +117,6 @@ class LexicalScope {
LexicalScope* parent_scope() const { return parent_; }
virtual bool var_init_needs_explicit_lifetime() const;
protected:
void dump_typedefs_(ostream&out, unsigned indent) const;
@@ -156,10 +130,6 @@ class LexicalScope {
void dump_wires_(ostream&out, unsigned indent) const;
void dump_var_inits_(ostream&out, unsigned indent) const;
bool elaborate_var_inits_(Design*des, NetScope*scope) const;
private:
LexicalScope*parent_;
};
@@ -175,24 +145,12 @@ class PScope : public LexicalScope {
// modules do not nest in Verilog, the parent must be nil for
// modules. Scopes for tasks and functions point to their
// containing module.
explicit PScope(perm_string name, LexicalScope*parent =0);
PScope(perm_string name, LexicalScope*parent);
PScope(perm_string name);
virtual ~PScope();
perm_string pscope_name() const { return name_; }
/* These are the timescale for this scope. The value is
set by the `timescale directive or, in SystemVerilog,
by timeunit and timeprecision statements. */
int time_unit, time_precision;
/* Flags used to support warnings about timescales. */
bool time_unit_is_default;
bool time_prec_is_default;
bool has_explicit_timescale() const {
return !(time_unit_is_default || time_prec_is_default);
}
protected:
bool elaborate_sig_wires_(Design*des, NetScope*scope) const;
@@ -210,22 +168,19 @@ class PScope : public LexicalScope {
class PScopeExtra : public PScope {
public:
explicit PScopeExtra(perm_string, LexicalScope*parent =0);
PScopeExtra(perm_string, LexicalScope*parent);
PScopeExtra(perm_string);
~PScopeExtra();
/* Task definitions within this module */
std::map<perm_string,PTask*> tasks;
std::map<perm_string,PFunction*> funcs;
/* Class definitions within this module. */
/* class definitions within this module. */
std::map<perm_string,PClass*> classes;
/* This is the lexical order of the classes, and is used by
elaboration to choose an elaboration order. */
std::vector<PClass*> classes_lexical;
/* Flags used to support warnings about timescales. */
bool time_unit_is_local;
bool time_prec_is_local;
protected:
void dump_classes_(ostream&out, unsigned indent) const;
void dump_tasks_(ostream&out, unsigned indent) const;
+1 -11
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2019 Stephen Williams ([email protected])
* Copyright (c) 1999-2008,2010 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -30,11 +30,6 @@ PTaskFunc::~PTaskFunc()
{
}
bool PTaskFunc::var_init_needs_explicit_lifetime() const
{
return default_lifetime == STATIC;
}
void PTaskFunc::set_ports(vector<pform_tf_port_t>*p)
{
assert(ports_ == 0);
@@ -73,8 +68,3 @@ void PTask::set_statement(Statement*s)
assert(statement_ == 0);
statement_ = s;
}
PNamedItem::SymbolType PTask::symbol_type() const
{
return TASK;
}
+3 -9
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PTask_H
#define IVL_PTask_H
/*
* Copyright (c) 1999-2019 Stephen Williams ([email protected])
* Copyright (c) 1999-2014 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -19,8 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "LineInfo.h"
# include "PScope.h"
# include "PNamedItem.h"
# include "StringHeap.h"
# include <string>
# include <vector>
@@ -35,14 +35,12 @@ class Statement;
class PExpr;
class PTaskFunc : public PScope, public PNamedItem {
class PTaskFunc : public PScope, public LineInfo {
public:
PTaskFunc(perm_string name, LexicalScope*parent);
~PTaskFunc();
bool var_init_needs_explicit_lifetime() const;
void set_ports(std::vector<pform_tf_port_t>*p);
void set_this(class_type_t*use_type, PWire*this_wire);
@@ -99,8 +97,6 @@ class PTask : public PTaskFunc {
void dump(ostream&, unsigned) const;
SymbolType symbol_type() const;
private:
Statement*statement_;
bool is_auto_;
@@ -150,8 +146,6 @@ class PFunction : public PTaskFunc {
void dump(ostream&, unsigned) const;
SymbolType symbol_type() const;
private:
data_type_t* return_type_;
Statement *statement_;
+2 -15
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2019 Stephen Williams ([email protected])
* Copyright (c) 1999-2012 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -29,7 +29,7 @@ PWire::PWire(perm_string n,
: name_(n), type_(t), port_type_(pt), data_type_(dt),
signed_(false), isint_(false),
port_set_(false), net_set_(false), is_scalar_(false),
error_cnt_(0), uarray_type_(0), set_data_type_(0),
error_cnt_(0), set_data_type_(0),
discipline_(0)
{
if (t == NetNet::INTEGER) {
@@ -67,7 +67,6 @@ bool PWire::set_wire_type(NetNet::Type t)
isint_ = true;
return true;
}
if (t == NetNet::IMPLICIT_REG) return true;
return false;
case NetNet::REG:
if (t == NetNet::INTEGER) {
@@ -283,15 +282,3 @@ ivl_discipline_t PWire::get_discipline(void) const
{
return discipline_;
}
PNamedItem::SymbolType PWire::symbol_type() const
{
switch (type_) {
case NetNet::IMPLICIT_REG:
case NetNet::INTEGER:
case NetNet::REG:
return VAR;
default:
return NET;
}
}
+3 -7
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PWire_H
#define IVL_PWire_H
/*
* Copyright (c) 1998-2019 Stephen Williams ([email protected])
* Copyright (c) 1998-2014 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -20,7 +20,7 @@
*/
# include "netlist.h"
# include "PNamedItem.h"
# include "LineInfo.h"
# include <list>
# include <map>
# include "StringHeap.h"
@@ -51,7 +51,7 @@ enum PWSRType {SR_PORT, SR_NET, SR_BOTH};
* from that perspective, sub-scopes within the module are a part of
* the wire name.
*/
class PWire : public PNamedItem {
class PWire : public LineInfo {
public:
PWire(perm_string name,
@@ -80,7 +80,6 @@ class PWire : public PNamedItem {
void set_range(const std::list<pform_range_t>&ranges, PWSRType type);
void set_unpacked_idx(const std::list<pform_range_t>&ranges);
void set_uarray_type(uarray_type_t*type) { uarray_type_ = type; }
void set_data_type(data_type_t*type);
@@ -94,8 +93,6 @@ class PWire : public PNamedItem {
NetNet* elaborate_sig(Design*, NetScope*scope) const;
SymbolType symbol_type() const;
private:
perm_string name_;
NetNet::Type type_;
@@ -120,7 +117,6 @@ class PWire : public PNamedItem {
// If this wire is actually a memory, these indices will give
// me the size and address ranges of the memory.
std::list<pform_range_t>unpacked_;
uarray_type_t*uarray_type_;
// This is the complex type of the wire. the data_type_ may
// modify how this is interpreted.
+33 -49
View File
@@ -1,12 +1,12 @@
THE ICARUS VERILOG COMPILATION SYSTEM
Copyright 2000-2019 Stephen Williams
Copyright 2000-2004 Stephen Williams
1.0 What is ICARUS Verilog?
Icarus Verilog is intended to compile ALL of the Verilog HDL as
described in the IEEE-1364 standard. Of course, it's not quite there
yet. It does currently handle a mix of structural and behavioural
yet. It does currently handle a mix of structural and behavioral
constructs. For a view of the current state of Icarus Verilog, see its
home page at <http://iverilog.icarus.com/>.
@@ -20,13 +20,13 @@ tools.
2.0 Building/Installing Icarus Verilog From Source
If you are starting from the source, the build process is designed to be
If you are starting from source, the build process is designed to be
as simple as practical. Someone basically familiar with the target
system and C/C++ compilation should be able to build the source
distribution with little effort. Some actual programming skills are
not required, but helpful in case of problems.
If you are building on Windows, see the mingw.txt file.
If you are building for Windows, see the mingw.txt file.
2.1 Compile Time Prerequisites
@@ -46,12 +46,8 @@ on a UNIX-like system:
to work. MSVC++ 5 and 6 are known to definitely *not* work.
- bison and flex
OSX note: bison 2.3 shipped with MacOS including Catalina generates
broken code, but bison 3+ works. We recommend using the Fink
project version of bison and flex (finkproject.org), brew version
works fine either.
- gperf 3.0 or later
- gperf 2.7
The lexical analyzer doesn't recognize keywords directly,
but instead matches symbols and looks them up in a hash
table in order to get the proper lexical code. The gperf
@@ -60,18 +56,18 @@ on a UNIX-like system:
A version problem with this program is the most common cause
of difficulty. See the Icarus Verilog FAQ.
- readline 4.2 or later
- readline 4.2
On Linux systems, this usually means the readline-devel
rpm. In any case, it is the development headers of readline
that are needed.
- termcap
The readline library, in turn, uses termcap.
The readline library in turn uses termcap.
If you are building from git, you will also need software to generate
the configure scripts.
- autoconf 2.53 or later
- autoconf 2.53
This generates configure scripts from configure.in. The 2.53
or later versions are known to work, autoconf 2.13 is
reported to *not* work.
@@ -79,21 +75,15 @@ the configure scripts.
2.2 Compilation
Unpack the tar-ball and cd into the verilog-######### directory
(presumably, that is how you got to this README) and compile the source
(presumably that is how you got to this README) and compile the source
with the commands:
./configure
make
If you are building from git, you have to run the command below before
compiling the source. This will generate the "configure" file, which is
automatically done when building from tarball.
sh autoconf.sh
Normally, this command automatically figures out everything it needs
to know. It generally works pretty well. There are a few flags to the
configure script that modify its behaviour:
configure script that modify its behavior:
--prefix=<root>
The default is /usr/local, which causes the tool suite to
@@ -116,12 +106,6 @@ configure script that modify its behaviour:
with the same prefix but different suffix are guaranteed
to not interfere with each other.
--host=<host-type>
Compile iverilog for a different platform. You can use:
x64_64-w64-mingw32 for building 64-bit Windows executables
i686-w64-mingw32 for building 32-bit Windows executables
Both options require installing the required mingw-w64 packages.
2.3 (Optional) Testing
To run a simple test before installation, execute
@@ -171,7 +155,7 @@ output of the parse is a list of Module objects in "pform". The pform
step. There may be dangling references, and it is not yet clear which
module is the root.
One can see a human-readable version of the final pform by using the
One can see a human readable version of the final pform by using the
``-P <path>'' flag to the ``ivl'' subcommand. This will cause ivl
to dump the pform into the file named <path>. (Note that this is not
normally done, unless debugging the ``ivl'' subcommand.)
@@ -183,17 +167,17 @@ This phase takes the pform and generates a netlist. The driver selects
resolves references and expands the instantiations to form the design
netlist. (See netlist.txt.) Final semantic checks are performed during
elaboration, and some simple optimizations are performed. The netlist
includes all the behavioural descriptions, as well as gates and wires.
includes all the behavioral descriptions, as well as gates and wires.
The elaborate() function performs the elaboration.
One can see a human-readable version of the final, elaborated and
One can see a human readable version of the final, elaborated and
optimized netlist by using the ``-N <path>'' flag to the compiler. If
elaboration succeeds, the final netlist (i.e., after optimizations but
before code generation) will be dumped into the file named <path>.
Elaboration is performed in two steps: scopes and parameters
first, followed by the structural and behavioural elaboration.
Elaboration is actually performed in two steps: scopes and parameters
first, followed by the structural and behavioral elaboration.
3.3.1 Scope Elaboration
@@ -202,7 +186,7 @@ tree of NetScope objects is built up and placed in the Design object,
with the root module represented by the root NetScope object. The
elab_scope.cc file contains most of the code for handling this phase.
The tail of the elaborate_scope behaviour (after the pform is
The tail of the elaborate_scope behavior (after the pform is
traversed) includes a scan of the NetScope tree to locate defparam
assignments that were collected during scope elaboration. This is when
the defparam overrides are applied to the parameters.
@@ -211,14 +195,14 @@ the defparam overrides are applied to the parameters.
After the scopes and parameters are generated and the NetScope tree
fully formed, the elaboration runs through the pform again, this time
generating the structural and behavioural netlist. Parameters are
generating the structural and behavioral netlist. Parameters are
elaborated and evaluated by now so all the constants of code
generation are now known locally, so the netlist can be generated by
simply passing through the pform.
3.4 Optimization
This is a collection of processing steps that perform
This is actually a collection of processing steps that perform
optimizations that do not depend on the target technology. Examples of
some useful transformations are
@@ -236,7 +220,7 @@ generator (see target.h). This may require transforming the
design to suit the technology.
The emit() method of the Design class performs this step. It runs
through the design elements, calling target functions as the need arises
through the design elements, calling target functions as need arises
to generate actual output.
The user selects the target code generator with the -t flag on the
@@ -244,7 +228,7 @@ command line.
3.6 ATTRIBUTES
NOTE: The $attribute syntax will soon be deprecated in favour of the
NOTE: The $attribute syntax will soon be deprecated in favor of the
Verilog-2001 attribute syntax, which is cleaner and standardized.
The parser accepts, as an extension to Verilog, the $attribute module
@@ -267,7 +251,7 @@ Attributes can also be applied to gate types. When this is done, the
attribute is given to every instantiation of the primitive. The syntax
for the attribute statement is the same, except that the <identifier>
names a primitive earlier in the compilation unit and the statement is
placed in the global scope, instead of within a module. The semicolon is
placed in global scope, instead of within a module. The semicolon is
not part of a type attribute.
Note that attributes are also occasionally used for communication
@@ -326,7 +310,7 @@ by the compiler. See the iverilog(1) man page.
Icarus Verilog is in development - as such it still only supports a
(growing) subset of Verilog. Below is a description of some of the
currently unsupported Verilog features. This list is not exhaustive
currently unsupported Verilog features. This list is not exhaustive,
and does not account for errors in the compiler. See the Icarus
Verilog web page for the current state of support for Verilog, and in
particular, browse the bug report database for reported unsupported
@@ -355,7 +339,7 @@ constructs.
5.1 Nonstandard Constructs or Behaviors
Icarus Verilog includes some features that are not part of the
IEEE1364 standard, but have well-defined meaning, and also sometimes
IEEE1364 standard, but have well defined meaning, and also sometimes
gives nonstandard (but extended) meanings to some features of the
language that are defined. See the "extensions.txt" documentation for
more details.
@@ -372,7 +356,7 @@ more details.
function is undefined if the argument doesn't have a
self-determined size.
The $sizeof function is deprecated in favour of $bits, which is
The $sizeof function is deprecated in favor of $bits, which is
the same thing, but included in the SystemVerilog definition.
$simtime
@@ -398,8 +382,8 @@ more details.
Builtin system functions
Certain of the system functions have well-defined meanings, so
can theoretically be evaluated at compile-time, instead of
Certain of the system functions have well defined meanings, so
can theoretically be evaluated at compile time, instead of
using runtime VPI code. Doing so means that VPI cannot
override the definitions of functions handled in this
manner. On the other hand, this makes them synthesizable, and
@@ -418,8 +402,8 @@ more details.
Icarus Verilog does preprocess modules that are loaded from
libraries via the -y mechanism. However, the only macros
defined during the compilation of that file are those that it
defines itself (or includes) or that are defined in the
defined during compilation of that file are those that it
defines itself (or includes) or that are defined on the
command line or command file.
Specifically, macros defined in the non-library source files
@@ -436,7 +420,7 @@ more details.
Standard Verilog does not allow width fields in the %t formats
of display strings. For example, this is illegal:
$display("Time is %0t", $time);
$display("Time is %0t", %time);
Standard Verilog instead relies on the $timeformat to
completely specify the format.
@@ -460,7 +444,7 @@ more details.
time 0 race resolution.
Combinational logic is routinely modelled using always
Combinational logic is routinely modeled using always
blocks. However, this can lead to race conditions if the
inputs to the combinational block are initialized in initial
statements. Icarus Verilog slightly modifies time 0 scheduling
@@ -471,7 +455,7 @@ more details.
Nets with Types
Icarus Verilog supports an extended syntax that allows nets
Icarus Verilog support an extension syntax that allows nets
and regs to be explicitly typed. The currently supported types
are logic, bool and real. This implies that "logic" and "bool"
are new keywords. Typical syntax is:
@@ -488,6 +472,6 @@ more details.
Except where otherwise noted, Icarus Verilog, ivl and ivlpp are
Copyright Stephen Williams. The proper notices are in the head of each
file. However, I have early on received aid in the form of fixes,
Verilog guidance, and especially testing from many people. Testers, in
particular, include a larger community of people interested in a GPL
Verilog guidance, and especially testing from many people. Testers in
particular include a larger community of people interested in a GPL
Verilog for Linux.
+9 -19
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2019 Stephen Williams ([email protected])
* Copyright (c) 1998-2013 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -115,11 +115,6 @@ PBlock::~PBlock()
delete list_[idx];
}
bool PBlock::var_init_needs_explicit_lifetime() const
{
return default_lifetime == STATIC;
}
PChainConstructor* PBlock::extract_chain_constructor()
{
if (list_.empty())
@@ -158,11 +153,6 @@ void PBlock::push_statement_front(Statement*that)
list_[0] = that;
}
PNamedItem::SymbolType PBlock::symbol_type() const
{
return BLOCK;
}
PCallTask::PCallTask(const pform_name_t&n, const list<PExpr*>&p)
: package_(0), path_(n), parms_(p.size())
{
@@ -206,8 +196,8 @@ const pform_name_t& PCallTask::path() const
return path_;
}
PCase::PCase(ivl_case_quality_t q, NetCase::TYPE t, PExpr*ex, svector<PCase::Item*>*l)
: quality_(q), type_(t), expr_(ex), items_(l)
PCase::PCase(NetCase::TYPE t, PExpr*ex, svector<PCase::Item*>*l)
: type_(t), expr_(ex), items_(l)
{
}
@@ -299,20 +289,20 @@ PDoWhile::~PDoWhile()
}
PEventStatement::PEventStatement(const svector<PEEvent*>&ee)
: expr_(ee), statement_(0), always_sens_(false)
: expr_(ee), statement_(0)
{
assert(expr_.count() > 0);
}
PEventStatement::PEventStatement(PEEvent*ee)
: expr_(1), statement_(0), always_sens_(false)
: expr_(1), statement_(0)
{
expr_[0] = ee;
}
PEventStatement::PEventStatement(bool always_sens)
: statement_(0), always_sens_(always_sens)
PEventStatement::PEventStatement(void)
: statement_(0)
{
}
@@ -416,8 +406,8 @@ PReturn::~PReturn()
delete expr_;
}
PTrigger::PTrigger(PPackage*pkg, const pform_name_t&e)
: package_(pkg), event_(e)
PTrigger::PTrigger(const pform_name_t&e)
: event_(e)
{
}
+9 -24
View File
@@ -1,7 +1,7 @@
#ifndef IVL_Statement_H
#define IVL_Statement_H
/*
* Copyright (c) 1998-2020 Stephen Williams ([email protected])
* Copyright (c) 1998-2014 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -75,7 +75,7 @@ class PProcess : public LineInfo {
* fact, the Statement class is abstract and represents all the
* possible kinds of statements that exist in Verilog.
*/
class Statement : virtual public LineInfo {
class Statement : public LineInfo {
public:
Statement() { }
@@ -108,8 +108,7 @@ class PAssign_ : public Statement {
NetAssign_* elaborate_lval(Design*, NetScope*scope) const;
NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t lv_net_type,
ivl_variable_type_t lv_type,
unsigned lv_width,
bool force_unsigned =false) const;
unsigned lv_width) const;
NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t ntype) const;
NetExpr* elaborate_rval_obj_(Design*, NetScope*,
@@ -170,7 +169,7 @@ class PAssignNB : public PAssign_ {
* statements before constructing this object, so it knows a priori
* what is contained.
*/
class PBlock : public PScope, public Statement, public PNamedItem {
class PBlock : public PScope, public Statement {
public:
enum BL_TYPE { BL_SEQ, BL_PAR, BL_JOIN_NONE, BL_JOIN_ANY };
@@ -183,8 +182,6 @@ class PBlock : public PScope, public Statement, public PNamedItem {
BL_TYPE bl_type() const { return bl_type_; }
bool var_init_needs_explicit_lifetime() const;
// This is only used if this block is the statement list for a
// constructor. We look for a PChainConstructor as the first
// statement, and if it is there, extract it.
@@ -205,8 +202,6 @@ class PBlock : public PScope, public Statement, public PNamedItem {
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
SymbolType symbol_type() const;
private:
BL_TYPE bl_type_;
std::vector<Statement*>list_;
@@ -232,8 +227,6 @@ class PCallTask : public Statement {
NetProc*elaborate_method_(Design*des, NetScope*scope,
bool add_this_flag = false) const;
NetProc*elaborate_function_(Design*des, NetScope*scope) const;
NetProc*elaborate_void_function_(Design*des, NetScope*scope,
NetFuncDef*def) const;
NetProc*elaborate_build_call_(Design*des, NetScope*scope,
NetScope*task, NetExpr*use_this) const;
@@ -241,10 +234,6 @@ class PCallTask : public Statement {
NetNet*net,
perm_string method_name,
const char*sys_task_name) const;
NetProc*elaborate_queue_method_(Design*des, NetScope*scope,
NetNet*net,
perm_string method_name,
const char*sys_task_name) const;
bool test_task_calls_ok_(Design*des, NetScope*scope) const;
PPackage*package_;
@@ -260,7 +249,7 @@ class PCase : public Statement {
Statement*stat;
};
PCase(ivl_case_quality_t, NetCase::TYPE, PExpr*ex, svector<Item*>*);
PCase(NetCase::TYPE, PExpr*ex, svector<Item*>*);
~PCase();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
@@ -269,7 +258,6 @@ class PCase : public Statement {
virtual void dump(ostream&out, unsigned ind) const;
private:
ivl_case_quality_t quality_;
NetCase::TYPE type_;
PExpr*expr_;
@@ -301,7 +289,7 @@ class PCAssign : public Statement {
*/
class PChainConstructor : public Statement {
public:
explicit PChainConstructor(const list<PExpr*>&parms);
PChainConstructor(const list<PExpr*>&parms);
~PChainConstructor();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
@@ -411,9 +399,8 @@ class PEventStatement : public Statement {
explicit PEventStatement(const svector<PEEvent*>&ee);
explicit PEventStatement(PEEvent*ee);
// Make an @* statement or make a special @* version with the items
// from functions added and outputs removed for always_comb/latch.
explicit PEventStatement(bool always_sens = false);
// Make an @* statement.
explicit PEventStatement(void);
~PEventStatement();
@@ -439,7 +426,6 @@ class PEventStatement : public Statement {
private:
svector<PEEvent*>expr_;
Statement*statement_;
bool always_sens_;
};
ostream& operator << (ostream&o, const PEventStatement&obj);
@@ -570,14 +556,13 @@ class PReturn : public Statement {
class PTrigger : public Statement {
public:
explicit PTrigger(PPackage*pkg, const pform_name_t&ev);
explicit PTrigger(const pform_name_t&ev);
~PTrigger();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
PPackage*package_;
pform_name_t event_;
};
Vendored
+3 -134
View File
@@ -23,13 +23,11 @@ AC_SUBST(install_suffix)
# ------------------------------
# Sub-macro for AX_C_UNDERSCORES_LEADING and AX_C_UNDERSCORES_TRAILING.
# Unwarranted assumptions:
# - the object file produced by AC_COMPILE_IFELSE is called
# "conftest.$ac_objext"
# - the nm(1) utility or an equivalent is available, and its name
# is defined by the $NM variable.
# - the object file produced by AC_COMPILE_IFELSE is called "conftest.$ac_objext"
# - the nm(1) utility is available, and its name is "nm".
AC_DEFUN([_AX_C_UNDERSCORES_MATCH_IF],
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([void underscore(void){}])],
[AS_IF([$NM conftest.$ac_objext|grep $1 >/dev/null 2>/dev/null],[$2],[$3])],
[AS_IF([nm conftest.$ac_objext|grep $1 >/dev/null 2>/dev/null],[$2],[$3])],
[AC_MSG_ERROR([underscore test crashed])]
)])
@@ -227,8 +225,6 @@ AC_DEFUN([AX_C99_STRTOD],
[# On MinGW we need to jump through hoops to get a C99 compliant strtod().
# mingw-w64 doesn't need this, and the 64-bit version doesn't support it.
case "${host}" in
x86_64-w64-mingw32)
;;
*-*-mingw32)
LDFLAGS+=" -Wl,--undefined=___strtod,--wrap,strtod,--defsym,___wrap_strtod=___strtod"
;;
@@ -248,130 +244,3 @@ _config_header=$1
_stamp_name=stamp-`expr //$_config_header : '.*/\([[^./]]*\)\.[[^./]]*$'`-h
echo "timestamp for $_config_header" > `AS_DIRNAME(["$_config_header"])`/[]$_stamp_name
]) #_AC_AM_CONFIG_HEADER_HOOK
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_PROG_CC_FOR_BUILD
#
# DESCRIPTION
#
# This macro searches for a C compiler that generates native executables,
# that is a C compiler that surely is not a cross-compiler. This can be
# useful if you have to generate source code at compile-time like for
# example GCC does.
#
# The macro sets the CC_FOR_BUILD and CPP_FOR_BUILD macros to anything
# needed to compile or link (CC_FOR_BUILD) and preprocess (CPP_FOR_BUILD).
# The value of these variables can be overridden by the user by specifying
# a compiler with an environment variable (like you do for standard CC).
#
# It also sets BUILD_EXEEXT and BUILD_OBJEXT to the executable and object
# file extensions for the build platform, and GCC_FOR_BUILD to `yes' if
# the compiler we found is GCC. All these variables but GCC_FOR_BUILD are
# substituted in the Makefile.
#
# LICENSE
#
# Copyright (c) 2008 Paolo Bonzini <[email protected]>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 8
AU_ALIAS([AC_PROG_CC_FOR_BUILD], [AX_PROG_CC_FOR_BUILD])
AC_DEFUN([AX_PROG_CC_FOR_BUILD], [dnl
AC_REQUIRE([AC_PROG_CC])dnl
AC_REQUIRE([AC_PROG_CPP])dnl
AC_REQUIRE([AC_EXEEXT])dnl
AC_REQUIRE([AC_CANONICAL_HOST])dnl
dnl Use the standard macros, but make them use other variable names
dnl
pushdef([ac_cv_prog_CPP], ac_cv_build_prog_CPP)dnl
pushdef([ac_cv_prog_gcc], ac_cv_build_prog_gcc)dnl
pushdef([ac_cv_prog_cc_works], ac_cv_build_prog_cc_works)dnl
pushdef([ac_cv_prog_cc_cross], ac_cv_build_prog_cc_cross)dnl
pushdef([ac_cv_prog_cc_g], ac_cv_build_prog_cc_g)dnl
pushdef([ac_cv_exeext], ac_cv_build_exeext)dnl
pushdef([ac_cv_objext], ac_cv_build_objext)dnl
pushdef([ac_exeext], ac_build_exeext)dnl
pushdef([ac_objext], ac_build_objext)dnl
pushdef([CC], CC_FOR_BUILD)dnl
pushdef([CPP], CPP_FOR_BUILD)dnl
pushdef([CFLAGS], CFLAGS_FOR_BUILD)dnl
pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl
pushdef([LDFLAGS], LDFLAGS_FOR_BUILD)dnl
pushdef([host], build)dnl
pushdef([host_alias], build_alias)dnl
pushdef([host_cpu], build_cpu)dnl
pushdef([host_vendor], build_vendor)dnl
pushdef([host_os], build_os)dnl
pushdef([ac_cv_host], ac_cv_build)dnl
pushdef([ac_cv_host_alias], ac_cv_build_alias)dnl
pushdef([ac_cv_host_cpu], ac_cv_build_cpu)dnl
pushdef([ac_cv_host_vendor], ac_cv_build_vendor)dnl
pushdef([ac_cv_host_os], ac_cv_build_os)dnl
pushdef([ac_cpp], ac_build_cpp)dnl
pushdef([ac_compile], ac_build_compile)dnl
pushdef([ac_link], ac_build_link)dnl
save_cross_compiling=$cross_compiling
save_ac_tool_prefix=$ac_tool_prefix
cross_compiling=no
ac_tool_prefix=
AC_PROG_CC
AC_PROG_CPP
AC_EXEEXT
ac_tool_prefix=$save_ac_tool_prefix
cross_compiling=$save_cross_compiling
dnl Restore the old definitions
dnl
popdef([ac_link])dnl
popdef([ac_compile])dnl
popdef([ac_cpp])dnl
popdef([ac_cv_host_os])dnl
popdef([ac_cv_host_vendor])dnl
popdef([ac_cv_host_cpu])dnl
popdef([ac_cv_host_alias])dnl
popdef([ac_cv_host])dnl
popdef([host_os])dnl
popdef([host_vendor])dnl
popdef([host_cpu])dnl
popdef([host_alias])dnl
popdef([host])dnl
popdef([LDFLAGS])dnl
popdef([CPPFLAGS])dnl
popdef([CFLAGS])dnl
popdef([CPP])dnl
popdef([CC])dnl
popdef([ac_objext])dnl
popdef([ac_exeext])dnl
popdef([ac_cv_objext])dnl
popdef([ac_cv_exeext])dnl
popdef([ac_cv_prog_cc_g])dnl
popdef([ac_cv_prog_cc_cross])dnl
popdef([ac_cv_prog_cc_works])dnl
popdef([ac_cv_prog_gcc])dnl
popdef([ac_cv_prog_CPP])dnl
dnl Finally, set Makefile variables
dnl
BUILD_EXEEXT=$ac_build_exeext
BUILD_OBJEXT=$ac_build_objext
AC_SUBST(BUILD_EXEEXT)dnl
AC_SUBST(BUILD_OBJEXT)dnl
AC_SUBST([CFLAGS_FOR_BUILD])dnl
AC_SUBST([CPPFLAGS_FOR_BUILD])dnl
AC_SUBST([LDFLAGS_FOR_BUILD])dnl
])
+5 -7
View File
@@ -59,7 +59,7 @@ distclean: clean
rm -f Makefile config.log
cppcheck: $(O:.o=.c)
cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f $(INCLUDE_PATH) $^
cppcheck --enable=all -f $(INCLUDE_PATH) $^
Makefile: $(srcdir)/Makefile.in ../config.status
cd ..; ./config.status --file=cadpli/$@
@@ -71,19 +71,17 @@ dep:
$(CC) $(CPPFLAGS) $(CFLAGS) @DEPENDENCY_FLAG@ -c $<
mv $*.d dep
SYSTEM_VPI_LDFLAGS = -L../vpi -lvpi
SYSTEM_VPI_LDFLAGS = -L../vvp -lvpi
ifeq (@MINGW32@,yes)
SYSTEM_VPI_LDFLAGS += @EXTRALIBS@
endif
cadpli.vpl: $O ../vpi/libvpi.a ../libveriuser/libveriuser.o
cadpli.vpl: $O ../vvp/libvpi.a ../libveriuser/libveriuser.o
$(CC) @shared@ $(LDFLAGS) -o $@ $O ../libveriuser/libveriuser.o $(SYSTEM_VPI_LDFLAGS)
install: all installdirs installfiles
install: all installdirs $(vpidir)/cadpli.vpl
F = ./cadpli.vpl
installfiles: $(F) | installdirs
$(vpidir)/cadpli.vpl: ./cadpli.vpl
$(INSTALL_PROGRAM) ./cadpli.vpl "$(DESTDIR)$(vpidir)/cadpli.vpl"
installdirs: $(srcdir)/../mkinstalldirs
+19 -40
View File
@@ -1,7 +1,7 @@
#ifndef IVL_compiler_H
#define IVL_compiler_H
/*
* Copyright (c) 1999-2019 Stephen Williams ([email protected])
* Copyright (c) 1999-2014 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -104,9 +104,6 @@ extern bool warn_sens_entire_arr;
/* Warn about level-appropriate anachronisms. */
extern bool warn_anachronisms;
/* Warn about nets that are references but not driven. */
extern bool warn_floating_nets;
/* This is true if verbose output is requested. */
extern bool verbose_flag;
@@ -117,13 +114,6 @@ extern bool debug_emit;
extern bool debug_synth2;
extern bool debug_optimizer;
/* Ignore errors about missing modules */
extern bool ignore_missing_modules;
/* Treat each source file as a separate compilation unit (as defined
by SystemVerilog). */
extern bool separate_compilation;
/* Control evaluation of functions at compile time:
* 0 = only for functions in constant expressions
* 1 = only for automatic functions
@@ -152,8 +142,7 @@ extern int build_library_index(const char*path, bool key_case_sensitive);
/* This is the generation of Verilog that the compiler is asked to
support. Then there are also more detailed controls for more
specific language features. Note that the compiler often assumes
this is an ordered list. */
specific language features. */
enum generation_t {
GN_VER1995 = 1,
GN_VER2001_NOCONFIG = 2,
@@ -177,12 +166,9 @@ extern bool gn_icarus_misc_flag;
is false, then skip elaboration of specify behavior. */
extern bool gn_specify_blocks_flag;
/* If this flag is true, then elaborate supported assertion statements. If
this flag is false, then stub out supported assertion statements. */
extern bool gn_supported_assertions_flag;
/* If this flag is true, then error on unsupported assertion statements. If
this flag is false, then stub out unsupported assertion statements. */
extern bool gn_unsupported_assertions_flag;
/* If this flag is true, then elaborate assertions. If this flag is
false, then stub out assertion statements. */
extern bool gn_assertions_flag;
/* If this flag is true, then support/elaborate Verilog-AMS. */
extern bool gn_verilog_ams_flag;
@@ -200,24 +186,25 @@ extern bool gn_strict_ca_eval_flag;
standard expression width rules. */
extern bool gn_strict_expr_width_flag;
/* If this flag is true, then don't add a for-loop control variable
to an implicit event_expression list if it is only used inside the
loop. */
extern bool gn_shared_loop_index_flag;
static inline bool gn_system_verilog(void)
/* If variables can be converted to uwires by a continuous assignment
(assuming no procedural assign, then return true. This will be true
for SystemVerilog */
static inline bool gn_var_can_be_uwire(void)
{
if (generation_flag >= GN_VER2005_SV)
if (generation_flag == GN_VER2005_SV ||
generation_flag == GN_VER2009 ||
generation_flag == GN_VER2012)
return true;
return false;
}
/* If variables can be converted to uwires by a continuous assignment
(assuming no procedural assign), then return true. This will be true
for SystemVerilog */
static inline bool gn_var_can_be_uwire(void)
static inline bool gn_system_verilog(void)
{
return gn_system_verilog();
if (generation_flag == GN_VER2005_SV ||
generation_flag == GN_VER2009 ||
generation_flag == GN_VER2012)
return true;
return false;
}
static inline bool gn_modules_nest(void)
@@ -286,20 +273,12 @@ struct sfunc_return_type {
const char* name;
ivl_variable_type_t type;
unsigned wid;
bool signed_flag;
bool override_flag;
int signed_flag;
};
extern void add_sys_func(const struct sfunc_return_type&ret_type);
extern const struct sfunc_return_type* lookup_sys_func(const char*name);
extern int load_sys_func_table(const char*path);
extern void cleanup_sys_func_table();
/*
* This temporarily loads a VPI module, to determine the return values
* of system functions provided by that module, and adds the return values
* to the system function table.
*/
extern bool load_vpi_module(const char*path);
/*
* In system Verilog it is allowed with a warning to call a function
+1 -11
View File
@@ -54,10 +54,6 @@ then
exit 1
fi
if test "x$NM" = "x"; then
NM=nm
fi
AC_EXEEXT
AC_SUBST(EXEEXT)
@@ -139,13 +135,7 @@ AC_CHECK_SIZEOF(unsigned)
# vvp uses these...
AC_CHECK_LIB(termcap, tputs)
AC_CHECK_LIB(readline, readline)
AC_CHECK_LIB(readline, add_history, NEED_LIBHISTORY=no, NEED_LIBHISTORY=yes)
if test "$NEED_LIBHISTORY" = "yes"; then
AC_CHECK_LIB(history, add_history)
else
# libreadline includes libhistory functions
AC_DEFINE(HAVE_LIBHISTORY, 1)
fi
AC_CHECK_HEADERS(readline/readline.h readline/history.h sys/resource.h)
case "${host}" in *linux*) AC_DEFINE([LINUX], [1], [Host operating system is Linux.]) ;; esac
@@ -335,5 +325,5 @@ then
AC_MSG_ERROR(cannot configure white space in libdir: $libdir)
fi
AC_MSG_RESULT(ok)
AX_PROG_CC_FOR_BUILD
AC_OUTPUT(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)
+2 -618
View File
@@ -1,619 +1,3 @@
// These are correct and are used to find the base (zero) pin.
thisSubtraction:netlist.h:5126
thisSubtraction:netlist.h:5135
// These are the functions that the compiler exports to the targets.
//ivl_branch_island()
unusedFunction:t-dll-api.cc:39
//ivl_branch_terminal()
unusedFunction:t-dll-api.cc:45
//ivl_const_bits()
unusedFunction:t-dll-api.cc:196
//ivl_const_delay()
unusedFunction:t-dll-api.cc:214
//ivl_const_file()
unusedFunction:t-dll-api.cc:221
//ivl_const_lineno()
unusedFunction:t-dll-api.cc:227
//ivl_const_nex()
unusedFunction:t-dll-api.cc:233
//ivl_const_real()
unusedFunction:t-dll-api.cc:239
//ivl_const_scope()
unusedFunction:t-dll-api.cc:246
//ivl_const_signed()
unusedFunction:t-dll-api.cc:252
//ivl_const_type()
unusedFunction:t-dll-api.cc:190
//ivl_const_width()
unusedFunction:t-dll-api.cc:258
//ivl_design_const()
unusedFunction:t-dll-api.cc:127
//ivl_design_consts()
unusedFunction:t-dll-api.cc:121
//ivl_design_delay_sel()
unusedFunction:t-dll-api.cc:52
//ivl_design_discipline()
unusedFunction:t-dll-api.cc:140
//ivl_design_disciplines()
unusedFunction:t-dll-api.cc:134
//ivl_design_flag()
unusedFunction:t-dll-api.cc:59
//ivl_design_process()
unusedFunction:t-dll-api.cc:66
//ivl_design_root()
unusedFunction:t-dll-api.cc:80
//ivl_design_roots()
unusedFunction:t-dll-api.cc:89
//ivl_design_time_precision()
unusedFunction:t-dll-api.cc:115
//ivl_discipline_domain()
unusedFunction:t-dll-api.cc:147
//ivl_discipline_flow()
unusedFunction:t-dll-api.cc:153
//ivl_discipline_name()
unusedFunction:t-dll-api.cc:159
//ivl_discipline_potential()
unusedFunction:t-dll-api.cc:165
//ivl_enum_bits()
unusedFunction:t-dll-api.cc:277
//ivl_enum_file()
unusedFunction:t-dll-api.cc:302
//ivl_enum_lineno()
unusedFunction:t-dll-api.cc:308
//ivl_enum_name()
unusedFunction:t-dll-api.cc:270
//ivl_enum_names()
unusedFunction:t-dll-api.cc:264
//ivl_enum_signed()
unusedFunction:t-dll-api.cc:296
//ivl_enum_type()
unusedFunction:t-dll-api.cc:284
//ivl_enum_width()
unusedFunction:t-dll-api.cc:290
//ivl_event_any()
unusedFunction:t-dll-api.cc:369
//ivl_event_file()
unusedFunction:t-dll-api.cc:345
//ivl_event_lineno()
unusedFunction:t-dll-api.cc:351
//ivl_event_name()
unusedFunction:t-dll-api.cc:314
//ivl_event_nany()
unusedFunction:t-dll-api.cc:363
//ivl_event_neg()
unusedFunction:t-dll-api.cc:382
//ivl_event_nneg()
unusedFunction:t-dll-api.cc:376
//ivl_event_npos()
unusedFunction:t-dll-api.cc:389
//ivl_event_pos()
unusedFunction:t-dll-api.cc:395
//ivl_event_scope()
unusedFunction:t-dll-api.cc:357
//ivl_expr_bits()
unusedFunction:t-dll-api.cc:402
//ivl_expr_branch()
unusedFunction:t-dll-api.cc:409
//ivl_expr_def()
unusedFunction:t-dll-api.cc:416
//ivl_expr_delay_val()
unusedFunction:t-dll-api.cc:432
//ivl_expr_dvalue()
unusedFunction:t-dll-api.cc:439
//ivl_expr_enumtype()
unusedFunction:t-dll-api.cc:446
//ivl_expr_event()
unusedFunction:t-dll-api.cc:656
//ivl_expr_file()
unusedFunction:t-dll-api.cc:178
//ivl_expr_lineno()
unusedFunction:t-dll-api.cc:184
//ivl_expr_name()
unusedFunction:t-dll-api.cc:459
//ivl_expr_nature()
unusedFunction:t-dll-api.cc:483
//ivl_expr_net_type()
unusedFunction:t-dll-api.cc:453
//ivl_expr_opcode()
unusedFunction:t-dll-api.cc:490
//ivl_expr_oper1()
unusedFunction:t-dll-api.cc:506
//ivl_expr_oper2()
unusedFunction:t-dll-api.cc:544
//ivl_expr_oper3()
unusedFunction:t-dll-api.cc:570
//ivl_expr_parameter()
unusedFunction:t-dll-api.cc:584
//ivl_expr_parm()
unusedFunction:t-dll-api.cc:599
//ivl_expr_parms()
unusedFunction:t-dll-api.cc:626
//ivl_expr_repeat()
unusedFunction:t-dll-api.cc:649
//ivl_expr_scope()
unusedFunction:t-dll-api.cc:670
//ivl_expr_sel_type()
unusedFunction:t-dll-api.cc:677
//ivl_expr_signed()
unusedFunction:t-dll-api.cc:702
//ivl_expr_sized()
unusedFunction:t-dll-api.cc:708
//ivl_expr_string()
unusedFunction:t-dll-api.cc:714
//ivl_expr_type()
unusedFunction:t-dll-api.cc:171
//ivl_expr_uvalue()
unusedFunction:t-dll-api.cc:721
//ivl_expr_value()
unusedFunction:t-dll-api.cc:747
//ivl_expr_width()
unusedFunction:t-dll-api.cc:753
//ivl_file_table_index()
unusedFunction:t-dll-api.cc:795
//ivl_file_table_item()
unusedFunction:t-dll-api.cc:785
//ivl_file_table_size()
unusedFunction:t-dll-api.cc:813
//ivl_island_flag_set()
unusedFunction:t-dll-api.cc:822
//ivl_island_flag_test()
unusedFunction:t-dll-api.cc:837
//ivl_logic_attr()
unusedFunction:t-dll-api.cc:864
//ivl_logic_attr_cnt()
unusedFunction:t-dll-api.cc:880
//ivl_logic_attr_val()
unusedFunction:t-dll-api.cc:886
//ivl_logic_basename()
unusedFunction:t-dll-api.cc:935
//ivl_logic_delay()
unusedFunction:t-dll-api.cc:974
//ivl_logic_drive0()
unusedFunction:t-dll-api.cc:894
//ivl_logic_drive1()
unusedFunction:t-dll-api.cc:911
//ivl_logic_file()
unusedFunction:t-dll-api.cc:846
//ivl_logic_is_cassign()
unusedFunction:t-dll-api.cc:858
//ivl_logic_lineno()
unusedFunction:t-dll-api.cc:852
//ivl_logic_name()
unusedFunction:t-dll-api.cc:928
//ivl_logic_pins()
unusedFunction:t-dll-api.cc:953
//ivl_logic_scope()
unusedFunction:t-dll-api.cc:941
//ivl_logic_type()
unusedFunction:t-dll-api.cc:947
//ivl_logic_udp()
unusedFunction:t-dll-api.cc:966
//ivl_logic_width()
unusedFunction:t-dll-api.cc:981
//ivl_lpm_array()
unusedFunction:t-dll-api.cc:1109
//ivl_lpm_aset_value()
unusedFunction:t-dll-api.cc:1160
//ivl_lpm_async_clr()
unusedFunction:t-dll-api.cc:1054
//ivl_lpm_async_set()
unusedFunction:t-dll-api.cc:1085
//ivl_lpm_base()
unusedFunction:t-dll-api.cc:1121
//ivl_lpm_basename()
unusedFunction:t-dll-api.cc:1048
//ivl_lpm_clk()
unusedFunction:t-dll-api.cc:1148
//ivl_lpm_data()
unusedFunction:t-dll-api.cc:1221
//ivl_lpm_datab()
unusedFunction:t-dll-api.cc:1321
//ivl_lpm_define()
unusedFunction:t-dll-api.cc:1183
//ivl_lpm_delay()
unusedFunction:t-dll-api.cc:1078
//ivl_lpm_drive0()
unusedFunction:t-dll-api.cc:1453
//ivl_lpm_drive1()
unusedFunction:t-dll-api.cc:1470
//ivl_lpm_enable()
unusedFunction:t-dll-api.cc:1195
//ivl_lpm_file()
unusedFunction:t-dll-api.cc:1209
//ivl_lpm_lineno()
unusedFunction:t-dll-api.cc:1215
//ivl_lpm_name()
unusedFunction:t-dll-api.cc:1355
//ivl_lpm_negedge()
unusedFunction:t-dll-api.cc:1136
//ivl_lpm_select()
unusedFunction:t-dll-api.cc:1493
//ivl_lpm_selects()
unusedFunction:t-dll-api.cc:1510
//ivl_lpm_signed()
unusedFunction:t-dll-api.cc:1528
//ivl_lpm_size()
unusedFunction:t-dll-api.cc:1587
//ivl_lpm_sset_value()
unusedFunction:t-dll-api.cc:1171
//ivl_lpm_string()
unusedFunction:t-dll-api.cc:1640
//ivl_lpm_sync_clr()
unusedFunction:t-dll-api.cc:1066
//ivl_lpm_sync_set()
unusedFunction:t-dll-api.cc:1097
//ivl_lpm_trigger()
unusedFunction:t-dll-api.cc:1659
//ivl_lpm_type()
unusedFunction:t-dll-api.cc:1647
//ivl_lpm_width()
unusedFunction:t-dll-api.cc:1653
//ivl_lval_idx()
unusedFunction:t-dll-api.cc:1681
//ivl_lval_mux()
unusedFunction:t-dll-api.cc:1676
//ivl_lval_nest()
unusedFunction:t-dll-api.cc:1726
//ivl_lval_part_off()
unusedFunction:t-dll-api.cc:1690
//ivl_lval_property_idx()
unusedFunction:t-dll-api.cc:1708
//ivl_lval_sel_type()
unusedFunction:t-dll-api.cc:1696
//ivl_lval_sig()
unusedFunction:t-dll-api.cc:1714
//ivl_nature_name()
unusedFunction:t-dll-api.cc:1735
//ivl_nexus_get_private()
unusedFunction:t-dll-api.cc:1756
//ivl_nexus_name()
unusedFunction:t-dll-api.cc:1745
//ivl_nexus_ptr_branch()
unusedFunction:t-dll-api.cc:1799
//ivl_nexus_ptr_con()
unusedFunction:t-dll-api.cc:1808
//ivl_nexus_ptr_sig()
unusedFunction:t-dll-api.cc:1835
//ivl_nexus_ptr_switch()
unusedFunction:t-dll-api.cc:1844
//ivl_nexus_set_private()
unusedFunction:t-dll-api.cc:1762
//ivl_parameter_basename()
unusedFunction:t-dll-api.cc:1853
//ivl_parameter_expr()
unusedFunction:t-dll-api.cc:1896
//ivl_parameter_file()
unusedFunction:t-dll-api.cc:1902
//ivl_parameter_lineno()
unusedFunction:t-dll-api.cc:1908
//ivl_parameter_local()
unusedFunction:t-dll-api.cc:1859
//ivl_parameter_lsb()
unusedFunction:t-dll-api.cc:1877
//ivl_parameter_msb()
unusedFunction:t-dll-api.cc:1871
//ivl_parameter_scope()
unusedFunction:t-dll-api.cc:1914
//ivl_parameter_signed()
unusedFunction:t-dll-api.cc:1865
//ivl_parameter_width()
unusedFunction:t-dll-api.cc:1887
//ivl_path_condit()
unusedFunction:t-dll-api.cc:1920
//ivl_path_delay()
unusedFunction:t-dll-api.cc:1932
//ivl_path_is_condit()
unusedFunction:t-dll-api.cc:1926
//ivl_path_scope()
unusedFunction:t-dll-api.cc:1938
//ivl_path_source()
unusedFunction:t-dll-api.cc:1945
//ivl_path_source_negedge()
unusedFunction:t-dll-api.cc:1957
//ivl_path_source_posedge()
unusedFunction:t-dll-api.cc:1951
//ivl_process_analog()
unusedFunction:t-dll-api.cc:1981
//ivl_process_attr_cnt()
unusedFunction:t-dll-api.cc:1999
//ivl_process_attr_val()
unusedFunction:t-dll-api.cc:2005
//ivl_process_file()
unusedFunction:t-dll-api.cc:1963
//ivl_process_lineno()
unusedFunction:t-dll-api.cc:1969
//ivl_process_scope()
unusedFunction:t-dll-api.cc:1987
//ivl_process_stmt()
unusedFunction:t-dll-api.cc:1993
//ivl_process_type()
unusedFunction:t-dll-api.cc:1975
//ivl_scope_attr_cnt()
unusedFunction:t-dll-api.cc:2013
//ivl_scope_attr_val()
unusedFunction:t-dll-api.cc:2019
//ivl_scope_basename()
unusedFunction:t-dll-api.cc:2027
//ivl_scope_child()
unusedFunction:t-dll-api.cc:2054
//ivl_scope_children()
unusedFunction:t-dll-api.cc:2033
//ivl_scope_childs()
unusedFunction:t-dll-api.cc:2047
//ivl_scope_class()
unusedFunction:t-dll-api.cc:2061
//ivl_scope_classes()
unusedFunction:t-dll-api.cc:2068
//ivl_scope_def()
unusedFunction:t-dll-api.cc:2075
//ivl_scope_def_file()
unusedFunction:t-dll-api.cc:2081
//ivl_scope_def_lineno()
unusedFunction:t-dll-api.cc:2087
//ivl_scope_enumerate()
unusedFunction:t-dll-api.cc:2099
//ivl_scope_enumerates()
unusedFunction:t-dll-api.cc:2093
//ivl_scope_event()
unusedFunction:t-dll-api.cc:2112
//ivl_scope_events()
unusedFunction:t-dll-api.cc:2106
//ivl_scope_file()
unusedFunction:t-dll-api.cc:2119
//ivl_scope_func_signed
unusedFunction:t-dll-api.cc:2132
//ivl_scope_func_type
unusedFunction:t-dll-api.cc:2125
//ivl_scope_func_width
unusedFunction:t-dll-api.cc:2140
//ivl_scope_is_auto()
unusedFunction:t-dll-api.cc:2148
//ivl_scope_is_cell()
unusedFunction:t-dll-api.cc:2154
//ivl_scope_lineno()
unusedFunction:t-dll-api.cc:2160
//ivl_scope_log()
unusedFunction:t-dll-api.cc:2172
//ivl_scope_logs()
unusedFunction:t-dll-api.cc:2166
//ivl_scope_lpm()
unusedFunction:t-dll-api.cc:2185
//ivl_scope_lpms()
unusedFunction:t-dll-api.cc:2179
//ivl_scope_mod_module_port_name()
unusedFunction:t-dll-api.cc:2264
//ivl_scope_mod_module_port_type()
unusedFunction:t-dll-api.cc:2273
//ivl_scope_mod_module_port_width()
unusedFunction:t-dll-api.cc:2285
//ivl_scope_mod_module_ports()
unusedFunction:t-dll-api.cc:2257
//ivl_scope_mod_port()
unusedFunction:t-dll-api.cc:2310
//ivl_scope_param()
unusedFunction:t-dll-api.cc:2243
//ivl_scope_params()
unusedFunction:t-dll-api.cc:2237
//ivl_scope_parent()
unusedFunction:t-dll-api.cc:2250
//ivl_scope_port()
unusedFunction:t-dll-api.cc:2301
//ivl_scope_ports()
unusedFunction:t-dll-api.cc:2292
//ivl_scope_sig()
unusedFunction:t-dll-api.cc:2324
//ivl_scope_sigs()
unusedFunction:t-dll-api.cc:2318
//ivl_scope_switch()
unusedFunction:t-dll-api.cc:2337
//ivl_scope_switches()
unusedFunction:t-dll-api.cc:2331
//ivl_scope_time_precision()
unusedFunction:t-dll-api.cc:2344
//ivl_scope_time_units()
unusedFunction:t-dll-api.cc:2350
//ivl_scope_tname()
unusedFunction:t-dll-api.cc:2362
//ivl_scope_type()
unusedFunction:t-dll-api.cc:2356
//ivl_signal_array_addr_swapped()
unusedFunction:t-dll-api.cc:2380
//ivl_signal_array_base()
unusedFunction:t-dll-api.cc:2368
//ivl_signal_array_count()
unusedFunction:t-dll-api.cc:2374
//ivl_signal_attr()
unusedFunction:t-dll-api.cc:2398
//ivl_signal_attr_cnt()
unusedFunction:t-dll-api.cc:2414
//ivl_signal_attr_val()
unusedFunction:t-dll-api.cc:2420
//ivl_signal_basename()
unusedFunction:t-dll-api.cc:2427
//ivl_signal_data_type()
unusedFunction:t-dll-api.cc:2578
//ivl_signal_dimensions()
unusedFunction:t-dll-api.cc:2386
//ivl_signal_discipline()
unusedFunction:t-dll-api.cc:2392
//ivl_signal_file()
unusedFunction:t-dll-api.cc:2555
//ivl_signal_forced_net()
unusedFunction:t-dll-api.cc:2549
//ivl_signal_integer()
unusedFunction:t-dll-api.cc:2567
//ivl_signal_lineno()
unusedFunction:t-dll-api.cc:2561
//ivl_signal_local()
unusedFunction:t-dll-api.cc:2536
//ivl_signal_lsb()
unusedFunction:t-dll-api.cc:2501
//ivl_signal_module_port_index()
unusedFunction:t-dll-api.cc:2530
//ivl_signal_msb()
unusedFunction:t-dll-api.cc:2491
//ivl_signal_name()
unusedFunction:t-dll-api.cc:2433
//ivl_signal_nex()
unusedFunction:t-dll-api.cc:2454
//ivl_signal_npath()
unusedFunction:t-dll-api.cc:2591
//ivl_signal_packed_dimensions()
unusedFunction:t-dll-api.cc:2471
//ivl_signal_packed_lsb()
unusedFunction:t-dll-api.cc:2484
//ivl_signal_packed_msb()
unusedFunction:t-dll-api.cc:2477
//ivl_signal_path()
unusedFunction:t-dll-api.cc:2597
//ivl_signal_port()
unusedFunction:t-dll-api.cc:2524
//ivl_signal_scope()
unusedFunction:t-dll-api.cc:2511
//ivl_signal_signed()
unusedFunction:t-dll-api.cc:2542
//ivl_signal_width()
unusedFunction:t-dll-api.cc:2517
//ivl_statement_type()
unusedFunction:t-dll-api.cc:2610
//ivl_stmt_block_count()
unusedFunction:t-dll-api.cc:2643
//ivl_stmt_block_scope()
unusedFunction:t-dll-api.cc:2628
//ivl_stmt_block_stmt()
unusedFunction:t-dll-api.cc:2658
//ivl_stmt_call()
unusedFunction:t-dll-api.cc:2674
//ivl_stmt_case_count()
unusedFunction:t-dll-api.cc:2695
//ivl_stmt_case_expr()
unusedFunction:t-dll-api.cc:2710
//ivl_stmt_case_stmt()
unusedFunction:t-dll-api.cc:2727
//ivl_stmt_cond_expr()
unusedFunction:t-dll-api.cc:2744
//ivl_stmt_cond_false()
unusedFunction:t-dll-api.cc:2771
//ivl_stmt_cond_true()
unusedFunction:t-dll-api.cc:2781
//ivl_stmt_delay_expr()
unusedFunction:t-dll-api.cc:2791
//ivl_stmt_delay_val()
unusedFunction:t-dll-api.cc:2808
//ivl_stmt_events()
unusedFunction:t-dll-api.cc:2834
//ivl_stmt_file()
unusedFunction:t-dll-api.cc:2616
//ivl_stmt_lexp()
unusedFunction:t-dll-api.cc:2862
//ivl_stmt_lineno()
unusedFunction:t-dll-api.cc:2622
//ivl_stmt_lval()
unusedFunction:t-dll-api.cc:2874
//ivl_stmt_lvals()
unusedFunction:t-dll-api.cc:2893
//ivl_stmt_lwidth()
unusedFunction:t-dll-api.cc:2911
//ivl_stmt_name()
unusedFunction:t-dll-api.cc:2944
//ivl_stmt_nevent()
unusedFunction:t-dll-api.cc:2815
//ivl_stmt_opcode()
unusedFunction:t-dll-api.cc:2957
//ivl_stmt_parm()
unusedFunction:t-dll-api.cc:2969
//ivl_stmt_parm_count()
unusedFunction:t-dll-api.cc:2983
//ivl_stmt_rval()
unusedFunction:t-dll-api.cc:2995
//ivl_stmt_sfunc_as_task()
unusedFunction:t-dll-api.cc:3013
//ivl_stmt_sub_stmt()
unusedFunction:t-dll-api.cc:3026
//ivl_switch_a()
unusedFunction:t-dll-api.cc:3067
//ivl_switch_b()
unusedFunction:t-dll-api.cc:3073
//ivl_switch_basename()
unusedFunction:t-dll-api.cc:3049
//ivl_switch_delay()
unusedFunction:t-dll-api.cc:3103
//ivl_switch_enable()
unusedFunction:t-dll-api.cc:3079
//ivl_switch_file()
unusedFunction:t-dll-api.cc:3110
//ivl_switch_island()
unusedFunction:t-dll-api.cc:3116
//ivl_switch_lineno()
unusedFunction:t-dll-api.cc:3122
//ivl_switch_offset()
unusedFunction:t-dll-api.cc:3097
//ivl_switch_part()
unusedFunction:t-dll-api.cc:3091
//ivl_switch_scope()
unusedFunction:t-dll-api.cc:3055
//ivl_switch_type()
unusedFunction:t-dll-api.cc:3061
//ivl_switch_width()
unusedFunction:t-dll-api.cc:3085
//ivl_type_base()
unusedFunction:t-dll-api.cc:3128
//ivl_type_element()
unusedFunction:t-dll-api.cc:3134
//ivl_type_name()
unusedFunction:t-dll-api.cc:3166
//ivl_type_packed_dimensions()
unusedFunction:t-dll-api.cc:3143
//ivl_type_packed_lsb()
unusedFunction:t-dll-api.cc:3150
//ivl_type_packed_msb()
unusedFunction:t-dll-api.cc:3158
//ivl_type_prop_type()
unusedFunction:t-dll-api.cc:3191
//ivl_type_properties()
unusedFunction:t-dll-api.cc:3174
//ivl_type_signed()
unusedFunction:t-dll-api.cc:3199
//ivl_udp_file()
unusedFunction:t-dll-api.cc:1036
//ivl_udp_init()
unusedFunction:t-dll-api.cc:999
//ivl_udp_lineno()
unusedFunction:t-dll-api.cc:1042
//ivl_udp_name()
unusedFunction:t-dll-api.cc:1029
//ivl_udp_nin()
unusedFunction:t-dll-api.cc:993
//ivl_udp_port()
unusedFunction:t-dll-api.cc:1005
//ivl_udp_row()
unusedFunction:t-dll-api.cc:1014
//ivl_udp_rows()
unusedFunction:t-dll-api.cc:1023
// ivl_udp_sequ()
unusedFunction:t-dll-api.cc:987
thisSubtraction:netlist.h:4976
thisSubtraction:netlist.h:4985
+23 -88
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2020 Stephen Williams ([email protected])
* Copyright (c) 1998-2015 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -187,14 +187,8 @@ ostream& operator << (ostream&fd, NetCaseCmp::kind_t that)
case NetCaseCmp::NEQ:
fd << "!==";
break;
case NetCaseCmp::WEQ:
fd << "==?";
break;
case NetCaseCmp::WNE:
fd << "!=?";
break;
case NetCaseCmp::XEQ:
fd << "==x?";
fd << "==?";
break;
case NetCaseCmp::ZEQ:
fd << "==z?";
@@ -232,15 +226,13 @@ ostream& netdarray_t::debug_dump(ostream&o) const
ostream& netqueue_t::debug_dump(ostream&fd) const
{
fd << "queue of ";
if (max_idx_ >= 0) fd << "(maximum of " << max_idx_+1 << " elements) ";
fd << *element_type();
fd << "queue of " << *element_type();
return fd;
}
ostream& netvector_t::debug_dump(ostream&o) const
{
o << "netvector_t:" << type_ << (signed_? " signed" : " unsigned") << packed_dims_;
o << type_ << (signed_? " signed" : " unsigned") << packed_dims_;
return o;
}
@@ -352,10 +344,6 @@ void NetDelaySrc::dump(ostream&o, unsigned ind) const
if (has_condit()) o << " if";
else o << " ifnone";
}
if (parallel_)
o << " parallel";
else
o << " full";
o << " src "
<< "(" << transition_delays_[IVL_PE_01]
<< "," << transition_delays_[IVL_PE_10]
@@ -700,14 +688,6 @@ void NetFF::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
void NetLatch::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_LATCH: " << name()
<< " scope=" << scope_path(scope()) << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetLiteral::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "constant real " << real_
@@ -741,12 +721,6 @@ void NetLogic::dump_node(ostream&o, unsigned ind) const
case CMOS:
o << "cmos";
break;
case EQUIV:
o << "<->";
break;
case IMPL:
o << "->";
break;
case NAND:
o << "nand";
break;
@@ -1002,18 +976,6 @@ void NetProcTop::dump(ostream&o, unsigned ind) const
o << "always /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
break;
case IVL_PR_ALWAYS_COMB:
o << "always_comb /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
break;
case IVL_PR_ALWAYS_FF:
o << "always_ff /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
break;
case IVL_PR_ALWAYS_LATCH:
o << "always_latch /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
break;
case IVL_PR_FINAL:
o << "final /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
@@ -1041,13 +1003,6 @@ void NetAnalogTop::dump(ostream&o, unsigned ind) const
<< scope_path(scope_) << " */" << endl;
break;
// These are not used in an analog context.
case IVL_PR_ALWAYS_COMB:
case IVL_PR_ALWAYS_FF:
case IVL_PR_ALWAYS_LATCH:
assert(0);
break;
case IVL_PR_FINAL:
o << "analog final /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
@@ -1065,11 +1020,7 @@ void NetAlloc::dump(ostream&o, unsigned ind) const
void NetAssign_::dump_lval(ostream&o) const
{
if (sig_) o << sig_->name();
else if (nest_) {
o << "(";
nest_->dump_lval(o);
o << ")";
}
else if (nest_) nest_->dump_lval(o);
else o << "<?>";
if (! member_.nil()) {
@@ -1162,29 +1113,15 @@ void NetBlock::dump(ostream&o, unsigned ind) const
void NetCase::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "";
switch (quality_) {
case IVL_CASE_QUALITY_BASIC:
break;
case IVL_CASE_QUALITY_UNIQUE:
o << "unique ";
break;
case IVL_CASE_QUALITY_UNIQUE0:
o << "unique0 ";
break;
case IVL_CASE_QUALITY_PRIORITY:
o << "priority ";
break;
}
switch (type_) {
case EQ:
o << "case (" << *expr_ << ")" << endl;
o << setw(ind) << "" << "case (" << *expr_ << ")" << endl;
break;
case EQX:
o << "casex (" << *expr_ << ")" << endl;
o << setw(ind) << "" << "casex (" << *expr_ << ")" << endl;
break;
case EQZ:
o << "casez (" << *expr_ << ")" << endl;
o << setw(ind) << "" << "casez (" << *expr_ << ")" << endl;
break;
}
@@ -1445,8 +1382,6 @@ void NetScope::dump(ostream&o) const
if (is_interface()) o << " (interface)";
o << " " << children_.size() << " children, "
<< classes_.size() << " classes" << endl;
if (unit() && !is_unit())
o << " in compilation unit " << unit()->basename() << endl;
for (unsigned idx = 0 ; idx < attr_cnt() ; idx += 1)
o << " (* " << attr_key(idx) << " = "
@@ -1686,14 +1621,11 @@ void NetEBinary::dump(ostream&o) const
case 'A':
o << "~&";
break;
case 'e':
o << "==";
break;
case 'E':
o << "===";
break;
case 'w':
o << "==?";
case 'e':
o << "==";
break;
case 'G':
o << ">=";
@@ -1710,9 +1642,6 @@ void NetEBinary::dump(ostream&o) const
case 'N':
o << "!==";
break;
case 'W':
o << "!=?";
break;
case 'o':
o << "||";
break;
@@ -1722,12 +1651,6 @@ void NetEBinary::dump(ostream&o) const
case 'p':
o << "**";
break;
case 'q':
o << "->";
break;
case 'Q':
o << "<->";
break;
case 'r':
o << ">>";
break;
@@ -1747,7 +1670,7 @@ void NetECast::dump(ostream&fd) const
{
if (op_=='2')
fd << "bool<" << expr_width() << ">(" << *expr_ << ")";
else if (op_=='v')
else if (op_=='4')
fd << "logic<" << expr_width() << ">(" << *expr_ << ")";
else
NetEUnary::dump(fd);
@@ -1971,6 +1894,18 @@ void Design::dump(ostream&o) const
cur->second->dump(o);
}
o << "$ROOT CLASSES:" << endl;
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
; cur != classes_.end() ; ++cur) {
cur->second->dump_scope(o);
}
o << "$ROOT TASKS/FUNCTIONS:" << endl;
for (map<NetScope*,PTaskFunc*>::const_iterator cur = root_tasks_.begin()
; cur != root_tasks_.end() ; ++ cur) {
cur->first->dump(o);
}
o << "SCOPES:" << endl;
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
scope != root_scopes_.end(); ++ scope ) {
+1 -1
View File
@@ -19,7 +19,7 @@
/*
* This is a simple program to make a dosified copy of the
* original. That is, it converts Unix style line ends to DOS
* original. That is, it converts unix style line ends to DOS
* style. This is useful for installing text files.
*
* The exact substitution is to replace \n with \r\n. If the line
+3 -13
View File
@@ -36,7 +36,6 @@ mandir = @mandir@
dllib=@DLLIB@
CC = @CC@
HOSTCC := @CC@
WINDRES = @WINDRES@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -66,7 +65,7 @@ distclean: clean
rm -f Makefile config.log
cppcheck: main.c
cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f $(INCLUDE_PATH) $^
cppcheck --enable=all -f $(INCLUDE_PATH) $^
Makefile: $(srcdir)/Makefile.in ../config.status
cd ..; ./config.status --file=driver-vpi/$@
@@ -94,19 +93,10 @@ res.o: res.rc
$(WINDRES) -i res.rc -o res.o
#
install: all installdirs installfiles
install: all installdirs $(bindir)/iverilog-vpi$(suffix)@EXEEXT@
F = ./iverilog-vpi@EXEEXT@
installfiles: $(F) | installdirs
$(bindir)/iverilog-vpi$(suffix)@EXEEXT@: ./iverilog-vpi@EXEEXT@
$(INSTALL_PROGRAM) ./iverilog-vpi@EXEEXT@ "$(bindir)/iverilog-vpi$(suffix)@EXEEXT@"
ifeq (@WIN32@,yes)
ifneq ($(HOSTCC),$(CC))
$(INSTALL_PROGRAM) $(shell $(HOSTCC) --print-file-name=libwinpthread-1.dll) "$(DESTDIR)$(bindir)"
$(INSTALL_PROGRAM) $(shell $(HOSTCC) --print-file-name=libgcc_s_sjlj-1.dll) "$(DESTDIR)$(bindir)"
$(INSTALL_PROGRAM) $(shell $(HOSTCC) --print-file-name=libstdc++-6.dll) "$(DESTDIR)$(bindir)"
endif
endif
installdirs: $(srcdir)/../mkinstalldirs
$(srcdir)/../mkinstalldirs "$(bindir)"
+14 -16
View File
@@ -67,7 +67,7 @@ distclean: clean
rm -f Makefile config.log
cppcheck: $(O:.o=.c)
cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \
cppcheck --enable=all -f \
-UYY_USER_INIT \
-UYYPARSE_PARAM -UYYPRINT -Ushort -Uyyoverflow \
-UYYTYPE_INT8 -UYYTYPE_INT16 -UYYTYPE_UINT8 -UYYTYPE_UINT16 \
@@ -85,9 +85,10 @@ iverilog@EXEEXT@: $O
cflexor.c: $(srcdir)/cflexor.lex
$(LEX) -s -t $< > $@
# Use pattern rules to avoid parallel build issues (see pr3462585)
cfparse%c cfparse%h: $(srcdir)/cfparse%y
$(YACC) --verbose -t -p cf -d -o cfparse.c $<
# Build this in two steps to avoid parallel build issues (see pr3462585)
cfparse.c: $(srcdir)/cfparse.y
$(YACC) --verbose -t -p cf -d -o $@ $<
cfparse.h: cfparse.c
%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o
@@ -111,35 +112,32 @@ iverilog.pdf: iverilog.ps
ifeq (@MINGW32@,yes)
ifeq ($(MAN),none)
INSTALL_DOC = installman
INSTALL_DOC = $(mandir)/man1/iverilog$(suffix).1
else
ifeq ($(PS2PDF),none)
INSTALL_DOC = installman
INSTALL_DOC = $(mandir)/man1/iverilog$(suffix).1
else
INSTALL_DOC = installpdf installman
INSTALL_DOC = $(prefix)/iverilog$(suffix).pdf $(mandir)/man1/iverilog$(suffix).1
all: iverilog.pdf
endif
endif
INSTALL_DOCDIR = $(mandir)/man1
else
INSTALL_DOC = installman
INSTALL_DOC = $(mandir)/man1/iverilog$(suffix).1
INSTALL_DOCDIR = $(mandir)/man1
endif
install: all installdirs installfiles
install: all installdirs $(bindir)/iverilog$(suffix)@EXEEXT@ $(INSTALL_DOC)
F = ./iverilog@EXEEXT@ \
$(INSTALL_DOC)
$(bindir)/iverilog$(suffix)@EXEEXT@: ./iverilog@EXEEXT@
$(INSTALL_PROGRAM) ./iverilog@EXEEXT@ "$(DESTDIR)$(bindir)/iverilog$(suffix)@EXEEXT@"
installman: iverilog.man installdirs
$(mandir)/man1/iverilog$(suffix).1: iverilog.man
$(INSTALL_DATA) iverilog.man "$(DESTDIR)$(mandir)/man1/iverilog$(suffix).1"
installpdf: iverilog.pdf installdirs
$(prefix)/iverilog$(suffix).pdf: iverilog.pdf
$(INSTALL_DATA) iverilog.pdf "$(DESTDIR)$(prefix)/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)"
+4 -7
View File
@@ -4,7 +4,7 @@
%{
/*
* Copyright (c) 2001-2017 Stephen Williams ([email protected])
* Copyright (c) 2001-2014 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -22,13 +22,11 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "cfparse_misc.h"
# include "cfparse.h"
# include "cfparse_misc.h"
# include "globals.h"
# include <string.h>
char *current_file = NULL;
static int comment_enter;
static char* trim_trailing_white(char*txt, int trim);
@@ -126,8 +124,7 @@ int cmdfile_stack_ptr = 0;
"-c" { return TOK_Dc; }
"-f" { return TOK_Dc; }
/* Notice the -l or -v flag. */
"-l" { return TOK_Dv; }
/* Notice the -v flag. */
"-v" { return TOK_Dv; }
/* Notice the -y flag. */
@@ -254,7 +251,7 @@ void destroy_lexor(void)
{
# ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy();
# endif
# endif
+1 -1
View File
@@ -39,6 +39,6 @@ int cferror(const char *);
int cfparse(void);
void switch_to_command_file(const char *);
void destroy_lexor(void);
extern char *current_file;
char *current_file;
#endif /* IVL_cfparse_misc_H */
+22 -123
View File
@@ -1,16 +1,14 @@
.TH iverilog 1 "Aug 10th, 2020" "" "Version %M.%n%E"
.TH iverilog 1 "Aug 7th, 2015" "" "Version %M.%n%E"
.SH NAME
iverilog - Icarus Verilog compiler
.SH SYNOPSIS
.B iverilog
[\-EiSuVv] [\-Bpath] [\-ccmdfile|\-fcmdfile] [\-Dmacro[=defn]]
[\-Pparameter=value] [\-pflag=value] [\-dname]
[\-g1995\:|\-g2001\:|\-g2005\:|\-g2005-sv\:|\-g2009\:|\-g2012\:|\-g<feature>]
[\-Iincludedir] [\-Lmoduledir] [\-mmodule] [\-M[mode=]file] [\-Nfile]
[\-ooutputfilename] [\-stopmodule] [\-ttype] [\-Tmin/typ/max] [\-Wclass]
[\-ypath] [\-lfile]
sourcefile
[\-ESVv] [\-Bpath] [\-ccmdfile|\-fcmdfile] [\-Dmacro[=defn]]
[\-Pparameter=value] [\-pflag=value]
[\-dname] [\-g1995|\-g2001|\-g2005|\-g2005-sv|\-g2009|\-g2012|\-g<feature>]
[\-Iincludedir] [\-mmodule] [\-M[mode=]file] [\-Nfile] [\-ooutputfilename]
[\-stopmodule] [\-ttype] [\-Tmin/typ/max] [\-Wclass] [\-ypath] sourcefile
.SH DESCRIPTION
.PP
@@ -81,12 +79,6 @@ use any of the new \fIIEEE1800\fP keywords.
Enable or disable (default) support for Verilog\-AMS.
Very little Verilog\-AMS specific functionality is currently supported.
.TP 8
.B -gassertions\fI|\fP-gsupported-assertions\fI|\fP-gno-assertions
Enable (default) or disable SystemVerilog assertions. When enabled,
assertion statements are elaborated. When disabled, assertion statements
are parsed but ignored. The \fB\-gsupported-assertions\fP option only
enables assertions that are currently supported by the compiler.
.TP 8
.B -gspecify\fI|\fP-gno-specify
Enable or disable (default) specify block support. When enabled,
specify block code is elaborated. When disabled, specify blocks are
@@ -131,7 +123,7 @@ default, parts of the expression that do not depend on the changed
input value(s) are not re-evaluated. If an expression contains a call
to a function that doesn't depend solely on its input values or that
has side effects, the resulting behavior will differ from that
required by the standard. Using \fB\-gstrict\-ca\-eval\fP will force
required by the standard. Using \fI\-gstrict\-ca\-eval\fP will force
standard compliant behavior (with some loss in performance).
.TP 8
.B -gstrict-expr-width\fI|\fP-gno-strict-expr-width
@@ -141,42 +133,12 @@ parameter assignment is evaluated as a lossless expression, as is any
expression containing an unsized constant number, and unsized constant
numbers are not truncated to integer width.
.TP 8
.B -gshared-loop-index\fI|\fP-gno-shared-loop-index
Enable (default) or disable the exclusion of for-loop control variables
from implicit event_expression lists. When enabled, if a for-loop control
variable (loop index) is only used inside the for-loop statement, the
compiler will not include it in an implicit event_expression list it
calculates for that statement or any enclosing statement. This allows
the same control variable to be used in multiple processes without risk
of entering an infinite loop caused by each process triggering all other
processes that use the same varaible. For strict compliance with the
standards, this behaviour should be disabled.
.TP 8
.B -I\fIincludedir\fP
Append directory \fIincludedir\fP to list of directories searched
for Verilog include files. The \fB\-I\fP switch may be used many times
to specify several directories to search, the directories are searched
in the order they appear on the command line.
.TP 8
.B -i
Ignore missing modules. Normally it is an error if a module instantiation
refers to an undefined module. This option causes the compiler to skip
over that instantiation. It will also stop the compiler returning an
error if there are no top level modules. This allows the compiler to be
used to check incomplete designs for errors.
.TP 8
.B -L\fIpath\fP
This flag adds a directory to the path list used to locate VPI
modules. The default path includes only the install directory for the
system.vpi module, but this flag can add other directories. Multiple
paths are allowed, and the paths will be searched in order.
.TP 8
.B -l\fIfile\fP
Add the specified file to the list of source files to be compiled,
but mark it as a library file. All modules contained within that
file will be treated as library modules, and only elaborated if
they are instantiated by other modules in the design.
.TP 8
.B -M\fIpath\fP
This is equivalent to \fB\-Mall=path\fP. Preserved for backwards
compatibility.
@@ -197,13 +159,9 @@ prefixed by "I " and other files are prefixed by "M ".
.B -m\fImodule\fP
Add this module to the list of VPI modules to be loaded by the
simulation. Many modules can be specified, and all will be loaded, in
the order specified. The system module is implicit and always included
(and loaded last).
If the specified name includes at least one directory character, it is
assumed to be prefixed by the path to the module, otherwise the module
is searched for in the paths specified by preceding \fB-L\fP options,
and if not found there, in the \fIiverilog\fP base directory.
the order specified. The system module is implicit and always included.
If a System Function Table file (<module>.sft) exists for the module it
will be loaded automatically.
.TP 8
.B -N\fIpath\fP
This is used for debugging the compiler proper. Dump the final netlist
@@ -246,12 +204,6 @@ will suppress the warning that the compiler is making a choice.
Use this switch to specify the target output format. See the
\fBTARGETS\fP section below for a list of valid output formats.
.TP 8
.B -u
Treat each source file as a separate compilation unit (as defined in
SystemVerilog). If compiling for an \fIIEEE1364\fP generation, this
will just reset all compiler directives (including macro definitions)
before each new file is processed.
.TP 8
.B -v
Turn on verbose messages. This will print the command lines that are
executed to perform the actual compilation, along with version
@@ -294,7 +246,7 @@ that contain Verilog source files. During elaboration, the compiler
notices the instantiation of undefined module types. If the user
specifies library search directories, the compiler will search the
directory for files with the name of the missing module type. If it
finds such a file, it loads it as a Verilog source file, then tries
finds such a file, it loads it as a Verilog source file, they tries
again to elaborate the module.
Library module files should contain only a single module, but this is
@@ -317,10 +269,7 @@ This is the default. The vvp target generates code for the vvp
runtime. The output is a complete program that simulates the design
but must be run by the \fBvvp\fP command. The -pfileline=1 option
can be used to add procedural statement debugging opcodes to the
generated code. These opcodes are also used to generate file and
line information for procedural warning/error messages. To enable
the debug command tracing us the trace command (trace on) from
the vvp interactive prompt.
generated code.
.TP 8
.B fpga
This is a synthesis target that supports a variety of fpga devices,
@@ -343,9 +292,8 @@ after a \fB\-Wall\fP argument to suppress isolated warning types.
.TP 8
.B all
This enables the anachronisms, implicit, macro-replacement, portbind,
select\-range, timescale, and sensitivity\-entire\-array warning
categories.
This enables the anachronisms, implicit, portbind, select\-range,
timescale, and sensitivity\-entire\-array warning categories.
.TP 8
.B anachronisms
@@ -358,13 +306,6 @@ This enables warnings for creation of implicit declarations. For
example, if a scalar wire X is used but not declared in the Verilog
source, this will print a warning at its first use.
.TP 8
.B macro-redefinition\fI | \fPmacro-replacement
This enables preprocessor warnings when a macro is being redefined.
The first variant prints a warning any time a macro is redefined.
The second variant only prints a warning if the macro text changes.
Use \fBno-macro-redefinition\fP to turn off all warnings of this type.
.TP 8
.B portbind
This enables warnings for ports of module instantiations that are not
@@ -416,23 +357,13 @@ sensitivity list. Although this behaviour is prescribed by the IEEE
standard, it is not what might be expected and can have performance
implications if the array is large.
.SH "VPI MODULES"
If the source file name has a \fB.vpi\fP or \fB.vpl\fP suffix, then it
is taken to be a VPI module. VPI modules supplied by the user are scanned
to determine the return types of any system functions they provide. This
.SH "SYSTEM FUNCTION TABLE FILES"
If the source file name as a \fB.sft\fP suffix, then it is taken to be
a system function table file. A System function table file is used to
describe to the compiler the return types for system functions. This
is necessary because the compiler needs this information to elaborate
expressions that contain these system functions. The module path/name is
passed on to the target to allow the VPI module to be automatically loaded
at the start of simulation.
VPI modules may also be supplied using the \fB-L\fP and \fB-m\fP options.
.SH "SYSTEM FUNCTION TABLE FILES [deprecated]"
If the source file name has a \fB.sft\fP suffix, then it is taken to be a
system function table file. A system function table file is the old method
used to describe to the compiler the return types for system functions.
Users are encouraged to switch to the new method of simply supplying the
VPI module.
expressions that contain these system functions, but cannot run the
sizetf functions since it has no run-time.
The format of the table is ASCII, one function per line. Empty lines
are ignored, and lines that start with the '\fI#\fP' character are
@@ -453,11 +384,6 @@ The function returns an integer.
The function returns a vector with the given width, and is signed or
unsigned according to the flag.
.TP 8
.B vpiSysFuncString
The function returns a string. This is an Icarus-specific extension, not
available in the VPI standard.
.SH "COMMAND FILES"
The command file allows the user to place source file names and
certain command line switches into a text file instead of on a long
@@ -476,15 +402,6 @@ A \fB\-c\fP or \fB\-f\fP token prefixes a command file, exactly like it
does on the command line. The cmdfile may be on the same line or the
next non-comment line.
.TP 8
.B -l\ \fIfile\fP -v\ \fIfile\fP
A \fB\-l\fP token prefixes a library file in the command file,
exactly like it does on the command line. The parameter to the \fB\-l\fP
flag may be on the same line or the next non-comment line. \fB\-v\fP is
an alias for \fB\-l\fP, provided for compatibility with other simulators.
Variables in the \fIfile\fP are substituted.
.TP 8
.B -y\ \fIlibdir\fP
A \fB\-y\fP token prefixes a library directory in the command file,
@@ -505,7 +422,7 @@ Variables in the \fIincludedir\fP are substituted.
.TP 8
.B +libext+\fIext\fP
The \fB+libext\fP token in command files lists file extensions to try
The \fB+libext\fP token in command files fives file extensions to try
when looking for a library file. This is useful in conjunction with
\fB\-y\fP flags to list suffixes to try in each directory before moving
on to the next library directory.
@@ -586,24 +503,6 @@ This is always defined when compiling with Icarus Verilog.
.B __VAMS_ENABLE__ = 1
This is defined if Verilog\-AMS is enabled.
.SH ENVIRONMENT
.PP
\fIiverilog\fP also accepts some environment variables that control
its behavior. These can be used to make semi-permanent changes.
.TP 8
.B IVERILOG_ICONFIG=\fIfile-name\fP
This sets the name used for the temporary file that passes parameters
to the compiler proper, and prevents that file being deleted after the
compiler has exited.
.TP 8
.B IVERILOG_VPI_MODULE_PATH=\fI/some/path:/some/other/path\fP
This adds additional components to the VPI module search path. Paths
specified in this way are searched after paths specified with \fB-L\fP,
but before the default search path. Multiple paths can be separated with
colons (semicolons if using Windows).
.SH EXAMPLES
These examples assume that you have a Verilog source file called hello.v in
the current directory
@@ -633,7 +532,7 @@ Tips on using, debugging, and developing the compiler can be found at
.SH COPYRIGHT
.nf
Copyright \(co 2002\-2020 Stephen Williams
Copyright \(co 2002\-2015 Stephen Williams
This document can be freely redistributed according to the terms of the
GNU General Public License version 2.0
+87 -346
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2020 Stephen Williams ([email protected])
* Copyright (c) 2000-2015 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -38,13 +38,13 @@ const char NOTICE[] =
;
const char HELP[] =
"Usage: iverilog [-EiSuvV] [-B base] [-c cmdfile|-f cmdfile]\n"
"Usage: iverilog [-ESvV] [-B base] [-c cmdfile|-f cmdfile]\n"
" [-g1995|-g2001|-g2005|-g2005-sv|-g2009|-g2012] [-g<feature>]\n"
" [-D macro[=defn]] [-I includedir] [-L moduledir]\n"
" [-D macro[=defn]] [-I includedir]\n"
" [-M [mode=]depfile] [-m module]\n"
" [-N file] [-o filename] [-p flag=value]\n"
" [-s topmodule] [-t target] [-T min|typ|max]\n"
" [-W class] [-y dir] [-Y suf] [-l file] source_file(s)\n"
" [-W class] [-y dir] [-Y suf] source_file(s)\n"
"\n"
"See the man page for details.";
@@ -99,16 +99,13 @@ extern const char*optarg;
#ifdef __MINGW32__
const char sep = '\\';
const char path_sep = ';';
#else
const char sep = '/';
const char path_sep = ':';
#endif
extern void cfreset(FILE*fd, const char*path);
const char*base = 0;
const char*vpi_dir = 0;
const char*ivlpp_dir = 0;
const char*vhdlpp_dir= 0;
const char*vhdlpp_work = 0;
@@ -131,7 +128,6 @@ const char*gen_icarus = "icarus-misc";
const char*gen_io_range_error = "io-range-error";
const char*gen_strict_ca_eval = "no-strict-ca-eval";
const char*gen_strict_expr_width = "no-strict-expr-width";
const char*gen_shared_loop_index = "shared-loop-index";
const char*gen_verilog_ams = "no-verilog-ams";
/* Boolean: true means use a default include dir, false means don't */
@@ -141,12 +137,7 @@ int gen_std_include = 1;
of the include list. */
int gen_relative_include = 0;
char warning_flags[17] = "n";
int separate_compilation_flag = 0;
/* Boolean: true means ignore errors about missing modules */
int ignore_missing_modules = 0;
char warning_flags[16] = "n";
unsigned integer_width = 32;
@@ -172,12 +163,6 @@ char*compiled_defines_path = 0;
static char iconfig_common_path[4096] = "";
static const char**vpi_path_list = 0;
static unsigned vpi_path_list_size = 0;
static const char**env_vpi_path_list = 0;
static unsigned env_vpi_path_list_size = 0;
int synth_flag = 0;
int verbose_flag = 0;
@@ -355,15 +340,10 @@ static int t_version_only(void)
static void build_preprocess_command(int e_flag)
{
snprintf(tmp, sizeof tmp, "%s%civlpp %s%s%s -F\"%s\" -f\"%s\" -p\"%s\"%s",
ivlpp_dir, sep,
verbose_flag ? " -v" : "",
e_flag ? "" : " -L",
strchr(warning_flags, 'r') ? " -Wredef-all " :
strchr(warning_flags, 'R') ? " -Wredef-chg " : "",
defines_path, source_path,
compiled_defines_path,
e_flag ? "" : " | ");
snprintf(tmp, sizeof tmp, "%s%civlpp %s%s -F\"%s\" -f\"%s\" -p\"%s\" ",
ivlpp_dir, sep, verbose_flag?" -v":"",
e_flag?"":" -L", defines_path, source_path,
compiled_defines_path);
}
static int t_preprocess_only(void)
@@ -426,12 +406,8 @@ static int t_compile(void)
{
unsigned rc;
/* Start by building the preprocess command line, if required.
This pipes into the main ivl command. */
if (!separate_compilation_flag)
build_preprocess_command(0);
else
strcpy(tmp, "");
/* Start by building the preprocess command line. */
build_preprocess_command(0);
size_t ncmd = strlen(tmp);
char*cmd = malloc(ncmd + 1);
@@ -441,8 +417,8 @@ static int t_compile(void)
int rtn;
#endif
/* Build the ivl command. */
snprintf(tmp, sizeof tmp, "%s%civl", base, sep);
/* Build the ivl command and pipe it to the preprocessor. */
snprintf(tmp, sizeof tmp, " | %s%civl", base, sep);
rc = strlen(tmp);
cmd = realloc(cmd, ncmd+rc+1);
strcpy(cmd+ncmd, tmp);
@@ -470,16 +446,7 @@ static int t_compile(void)
strcpy(cmd+ncmd, tmp);
ncmd += rc;
snprintf(tmp, sizeof tmp, " -C\"%s\"", iconfig_common_path);
rc = strlen(tmp);
cmd = realloc(cmd, ncmd+rc+1);
strcpy(cmd+ncmd, tmp);
ncmd += rc;
if (separate_compilation_flag)
snprintf(tmp, sizeof tmp, " -F\"%s\"", source_path);
else
snprintf(tmp, sizeof tmp, " -- -");
snprintf(tmp, sizeof tmp, " -C\"%s\" -- -", iconfig_common_path);
rc = strlen(tmp);
cmd = realloc(cmd, ncmd+rc+1);
strcpy(cmd+ncmd, tmp);
@@ -530,7 +497,6 @@ static void process_warning_switch(const char*name)
process_warning_switch("anachronisms");
process_warning_switch("implicit");
process_warning_switch("implicit-dimensions");
process_warning_switch("macro-replacement");
process_warning_switch("portbind");
process_warning_switch("select-range");
process_warning_switch("timescale");
@@ -538,21 +504,12 @@ static void process_warning_switch(const char*name)
} else if (strcmp(name,"anachronisms") == 0) {
if (! strchr(warning_flags, 'n'))
strcat(warning_flags, "n");
} else if (strcmp(name,"floating-nets") == 0) {
if (! strchr(warning_flags, 'f'))
strcat(warning_flags, "f");
} else if (strcmp(name,"implicit") == 0) {
if (! strchr(warning_flags, 'i'))
strcat(warning_flags, "i");
} else if (strcmp(name,"implicit-dimensions") == 0) {
if (! strchr(warning_flags, 'd'))
strcat(warning_flags, "d");
} else if (strcmp(name,"macro-redefinition") == 0) {
if (! strchr(warning_flags, 'r'))
strcat(warning_flags, "r");
} else if (strcmp(name,"macro-replacement") == 0) {
if (! strchr(warning_flags, 'R'))
strcat(warning_flags, "R");
} else if (strcmp(name,"portbind") == 0) {
if (! strchr(warning_flags, 'p'))
strcat(warning_flags, "p");
@@ -579,12 +536,6 @@ static void process_warning_switch(const char*name)
cp[0] = cp[1];
cp += 1;
}
} else if (strcmp(name,"no-floating-nets") == 0) {
char*cp = strchr(warning_flags, 'f');
if (cp) while (*cp) {
cp[0] = cp[1];
cp += 1;
}
} else if (strcmp(name,"no-implicit") == 0) {
char*cp = strchr(warning_flags, 'i');
if (cp) while (*cp) {
@@ -597,17 +548,6 @@ static void process_warning_switch(const char*name)
cp[0] = cp[1];
cp += 1;
}
} else if (strcmp(name,"no-macro-redefinition") == 0) {
char*cp = strchr(warning_flags, 'r');
if (cp) while (*cp) {
cp[0] = cp[1];
cp += 1;
}
cp = strchr(warning_flags, 'R');
if (cp) while (*cp) {
cp[0] = cp[1];
cp += 1;
}
} else if (strcmp(name,"no-portbind") == 0) {
char*cp = strchr(warning_flags, 'p');
if (cp) while (*cp) {
@@ -682,19 +622,14 @@ void process_timescale(const char*ts_string)
/*
* This function is called while processing a file name in a command
* file, or a file name on the command line. Look to see if there is a
* .sft or .vpi suffix, and if so pass that as a sys_func or module
* file. Otherwise, it is a Verilog source file to be written into the
* file list.
* .sft suffix, and if so pass that as a sys_func file. Otherwise, it
* is a Verilog source file to be written into the file list.
*/
void process_file_name(const char*name, int lib_flag)
{
if (strlen(name) > 4 && strcasecmp(".sft", name+strlen(name)-4) == 0) {
fprintf(stderr, "SFT files are deprecated. Please pass the VPI module instead.\n");
fprintf(iconfig_file,"sys_func:%s\n", name);
} else if (strlen(name) > 4 && strcasecmp(".vpi", name+strlen(name)-4) == 0) {
fprintf(iconfig_file,"module:%s\n", name);
} else {
fprintf(source_file, "%s\n", name);
source_count += 1;
@@ -762,9 +697,6 @@ static int process_generation(const char*name)
else if (strcmp(name,"assertions") == 0)
gen_assertions = "assertions";
else if (strcmp(name,"supported-assertions") == 0)
gen_assertions = "supported-assertions";
else if (strcmp(name,"no-assertions") == 0)
gen_assertions = "no-assertions";
@@ -798,12 +730,6 @@ static int process_generation(const char*name)
else if (strcmp(name,"no-strict-expr-width") == 0)
gen_strict_expr_width = "no-strict-expr-width";
else if (strcmp(name,"shared-loop-index") == 0)
gen_shared_loop_index = "shared-loop-index";
else if (strcmp(name,"no-shared-loop-index") == 0)
gen_shared_loop_index = "no-shared-loop-index";
else if (strcmp(name,"verilog-ams") == 0)
gen_verilog_ams = "verilog-ams";
@@ -821,7 +747,6 @@ static int process_generation(const char*name)
" 2009 -- IEEE1800-2009\n"
" 2012 -- IEEE1800-2012\n"
"Other generation flags:\n"
" assertions | supported-assertions | no-assertions\n"
" specify | no-specify\n"
" verilog-ams | no-verilog-ams\n"
" std-include | no-std-include\n"
@@ -830,8 +755,7 @@ static int process_generation(const char*name)
" icarus-misc | no-icarus-misc\n"
" io-range-error | no-io-range-error\n"
" strict-ca-eval | no-strict-ca-eval\n"
" strict-expr-width | no-strict-expr-width\n"
" shared-loop-index | no-shared-loop-index\n");
" strict-expr-width | no-strict-expr-width\n");
return 1;
}
@@ -870,217 +794,18 @@ static int process_depfile(const char*name)
return 0;
}
static void add_env_vpi_module_path(const char*path)
{
env_vpi_path_list_size += 1;
env_vpi_path_list = (const char**)realloc(env_vpi_path_list,
env_vpi_path_list_size*sizeof(char*));
env_vpi_path_list[env_vpi_path_list_size-1] = path;
}
static void get_env_vpi_module_paths(void)
{
char *var = getenv("IVERILOG_VPI_MODULE_PATH");
char *ptr, *end;
if (!var)
return;
var = strdup(var);
#ifdef __MINGW32__
convert_to_MS_path(var);
#endif
ptr = var;
end = var+strlen(var);
int len = 0;
while (ptr <= end) {
if (*ptr == 0 || *ptr == path_sep) {
*ptr = 0;
if (len > 0) {
add_env_vpi_module_path(var);
}
len = 0;
var = ptr+1;
} else {
len++;
}
ptr++;
}
}
static void add_vpi_module_path(const char*path)
{
#ifdef __MINGW32__
char*tmp_path = strdup(path);
convert_to_MS_path(tmp_path);
path = tmp_path;
#endif
vpi_path_list_size += 1;
vpi_path_list = (const char**)realloc(vpi_path_list,
vpi_path_list_size*sizeof(char*));
vpi_path_list[vpi_path_list_size-1] = path;
}
static int probe_for_vpi_module(const char*base_path, const char*name,
char*path, unsigned path_size)
{
snprintf(path, path_size, "%s%c%s.vpi", base_path, sep, name);
if (access(path, R_OK) == 0)
return 1;
snprintf(path, path_size, "%s%c%s.vpl", base_path, sep, name);
if (access(path, R_OK) == 0)
return 1;
return 0;
}
/*
* If it exists add the VPI file for the given module.
* If it exists add the SFT file for the given module.
*/
static void add_vpi_file(const char *name)
static void add_sft_file(const char *module)
{
const char*base_dir = vpi_dir ? vpi_dir : base;
char *file;
char path[4096];
#ifdef __MINGW32__
char*tmp_name = strdup(name);
convert_to_MS_path(tmp_name);
name = tmp_name;
#endif
int found = 0;
if (strchr(name, sep)) {
/* If the name has at least one directory character in it
then assume it is a complete name, maybe including any
possible .vpi or .vpl suffix. */
found = access(name, R_OK) == 0;
if (!found) {
snprintf(path, sizeof(path), "%s.vpi", name);
found = access(path, R_OK) == 0;
if (!found) {
snprintf(path, sizeof(path), "%s.vpl", name);
found = access(path, R_OK) == 0;
}
} else {
strncpy(path, name, sizeof(path) - 1);
}
} else {
for (unsigned idx = 0; !found && (idx < vpi_path_list_size); idx += 1) {
found = probe_for_vpi_module(vpi_path_list[idx], name,
path, sizeof(path));
}
for (unsigned idx = 0; !found && (idx < env_vpi_path_list_size); idx += 1) {
found = probe_for_vpi_module(env_vpi_path_list[idx], name,
path, sizeof(path));
}
if (!found) {
found = probe_for_vpi_module(base_dir, name,
path, sizeof(path));
}
}
if (found) {
fprintf(iconfig_file, "module:%s\n", path);
} else {
fprintf(stderr, "Unable to find VPI module '%s'\n", name);
}
#ifdef __MINGW32__
free(tmp_name);
#endif
}
static void find_ivl_root_failed(const char *reason)
{
fprintf(stderr, "Cannot locate IVL modules : %s\n", reason);
exit(1);
}
static void find_ivl_root(void)
{
#ifdef __MINGW32__
const char *ivl_lib_prefix = "\\lib";
const char *ivl_lib_suffix = "\\ivl" IVL_SUFFIX;
#else
const char *ivl_lib_prefix = IVL_LIB;
const char *ivl_lib_suffix = "/ivl" IVL_SUFFIX;
#endif
ssize_t len = 0;
char *s;
#ifndef __MINGW32__
/* First try the location specified in the build process. */
if (access(IVL_ROOT, F_OK) != -1) {
assert(strlen(IVL_ROOT) < sizeof ivl_root);
strcpy(ivl_root, IVL_ROOT);
return;
}
#endif
/* If that fails, calculate the ivl_root from the path to the
command. This is always necessary on Windows because of the
installation process, but may also be necessary on other OSs
if the package has been relocated.
On Windows we know the command path is formed like this:
$(prefix)\bin\iverilog.exe
The module path in a Windows installation is the path:
$(prefix)\lib\ivl$(suffix)
so we chop the file name and the last directory by
turning the last two \ characters to null. Then we append
the lib\ivl$(suffix) to finish.
On other OSs, we expect the command path to be:
$(prefix)/bin/iverilog
and the module path to be:
$(prefix)/$(lib)/ivl$(suffix)
so we extract the $(prefix) from the command location as for
Windows and the $(lib) from IVL_LIB. This will of course fail
if the user has overridden $(bindir) or $(libdir), but there's
not a lot we can do in that case.
*/
#ifdef __MINGW32__
char tmppath[MAXSIZE];
len = GetModuleFileName(NULL, tmppath, sizeof tmppath);
if (len >= (ssize_t) sizeof ivl_root) {
find_ivl_root_failed("command path exceeds size of string buffer.");
}
/* Convert to a short name to remove any embedded spaces. */
len = GetShortPathName(tmppath, ivl_root, sizeof ivl_root);
#else
len = readlink("/proc/self/exe", ivl_root, sizeof ivl_root);
#endif
if (len >= (ssize_t) sizeof ivl_root) {
find_ivl_root_failed("command path exceeds size of string buffer.");
}
if (len <= 0) {
find_ivl_root_failed("couldn't get command path from OS.");
}
s = strrchr(ivl_root, sep);
if (s == 0) {
find_ivl_root_failed("missing first separator in command path.");
}
*s = 0;
s = strrchr(ivl_root, sep);
if (s == 0) {
find_ivl_root_failed("missing second separator in command path.");
}
*s = 0;
len = s - ivl_root;
s = strrchr(ivl_lib_prefix, sep);
assert(s);
if (len + strlen(s) + strlen(ivl_lib_suffix) >= (ssize_t) sizeof ivl_root) {
find_ivl_root_failed("module path exceeds size of string buffer.");
}
strcat(ivl_root, s);
strcat(ivl_root, ivl_lib_suffix);
file = (char *) malloc(strlen(base)+1+strlen(module)+4+1);
sprintf(file, "%s%c%s.sft", base, sep, module);
if (access(file, R_OK) == 0)
fprintf(iconfig_file, "sys_func:%s\n", file);
free(file);
}
int main(int argc, char **argv)
@@ -1089,10 +814,51 @@ int main(int argc, char **argv)
int version_flag = 0;
int opt;
find_ivl_root();
#ifdef __MINGW32__
/* Calculate the ivl_root from the path to the command. This
is necessary because of the installation process on
Windows. Mostly, it is those darn drive letters, but oh
well. We know the command path is formed like this:
D:\iverilog\bin\iverilog.exe
The module path in a Windows installation is the path:
D:\iverilog\lib\ivl$(suffix)
so we chop the file name and the last directory by
turning the last two \ characters to null. Then we append
the lib\ivl$(suffix) to finish. */
char *s;
char tmppath[MAXSIZE];
GetModuleFileName(NULL, tmppath, sizeof tmppath);
/* Convert to a short name to remove any embedded spaces. */
GetShortPathName(tmppath, ivl_root, sizeof ivl_root);
s = strrchr(ivl_root, sep);
if (s) *s = 0;
else {
fprintf(stderr, "%s: Missing first %c in exe path!\n",
argv[0], sep);
exit(1);
}
s = strrchr(ivl_root, sep);
if (s) *s = 0;
else {
fprintf(stderr, "%s: Missing second %c in exe path!\n",
argv[0], sep);
exit(1);
}
strcat(ivl_root, "\\lib\\ivl" IVL_SUFFIX);
base = ivl_root;
get_env_vpi_module_paths();
#else
/* In a UNIX environment, the IVL_ROOT from the Makefile is
dependable. It points to the $prefix/lib/ivl directory,
where the sub-parts are installed. */
strcpy(ivl_root, IVL_ROOT);
base = ivl_root;
#endif
/* Create a temporary file for communicating input parameters
to the preprocessor. */
@@ -1154,7 +920,7 @@ int main(int argc, char **argv)
}
}
while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hl:I:iL:M:m:N:o:P:p:Ss:T:t:uvVW:y:Y:")) != EOF) {
while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hI:M:m:N:o:P:p:Ss:T:t:vVW:y:Y:")) != EOF) {
switch (opt) {
case 'B':
@@ -1163,9 +929,6 @@ int main(int argc, char **argv)
character of the path indicates which path the
user is specifying. */
switch (optarg[0]) {
case 'M': /* Path for the VPI modules */
vpi_dir = optarg+1;
break;
case 'P': /* Path for the ivlpp preprocessor */
ivlpp_dir = optarg+1;
break;
@@ -1212,25 +975,14 @@ int main(int argc, char **argv)
process_include_dir(optarg);
break;
case 'i':
ignore_missing_modules = 1;
break;
case 'L':
add_vpi_module_path(optarg);
break;
case 'l':
process_file_name(optarg, 1);
break;
case 'M':
if (process_depfile(optarg) != 0)
return -1;
break;
case 'm':
add_vpi_file(optarg);
fprintf(iconfig_file, "module:%s\n", optarg);
add_sft_file(optarg);
break;
case 'N':
@@ -1263,9 +1015,6 @@ int main(int argc, char **argv)
case 't':
targ = optarg;
break;
case 'u':
separate_compilation_flag = 1;
break;
case 'v':
verbose_flag = 1;
break;
@@ -1301,8 +1050,6 @@ int main(int argc, char **argv)
}
}
if (vpi_dir == 0)
vpi_dir = base;
if (ivlpp_dir == 0)
ivlpp_dir = base;
if (vhdlpp_dir == 0)
@@ -1310,7 +1057,7 @@ int main(int argc, char **argv)
if (version_flag || verbose_flag) {
printf("Icarus Verilog version " VERSION " (" VERSION_TAG ")\n\n");
printf("Copyright 1998-2020 Stephen Williams\n\n");
printf("Copyright 1998-2015 Stephen Williams\n\n");
puts(NOTICE);
}
@@ -1321,10 +1068,11 @@ int main(int argc, char **argv)
/* Write values to the iconfig file. */
fprintf(iconfig_file, "basedir:%s\n", base);
/* Tell the core where to find the system VPI modules. */
fprintf(iconfig_file, "module:%s%csystem.vpi\n", vpi_dir, sep);
fprintf(iconfig_file, "module:%s%cvhdl_sys.vpi\n", vpi_dir, sep);
fprintf(iconfig_file, "module:%s%cvhdl_textio.vpi\n", vpi_dir, sep);
/* Tell the core where to find the system.sft. This file
describes the system functions so that elaboration knows
how to handle them. */
fprintf(iconfig_file, "sys_func:%s%csystem.sft\n", base, sep);
fprintf(iconfig_file, "sys_func:%s%cvhdl_sys.sft\n", base, sep);
/* If verilog-2005/09/12 is enabled or icarus-misc or verilog-ams,
* then include the v2005_math library. */
@@ -1333,20 +1081,23 @@ int main(int argc, char **argv)
strcmp(generation, "2012") == 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);
fprintf(iconfig_file, "sys_func:%s%cv2005_math.sft\n", base, sep);
fprintf(iconfig_file, "module:v2005_math\n");
}
/* If verilog-ams or icarus_misc is enabled, then include the
* va_math module as well. */
if (strcmp(gen_verilog_ams,"verilog-ams") == 0 ||
strcmp(gen_icarus, "icarus-misc") == 0) {
fprintf(iconfig_file, "module:%s%cva_math.vpi\n", vpi_dir, sep);
fprintf(iconfig_file, "sys_func:%s%cva_math.sft\n", base, sep);
fprintf(iconfig_file, "module:va_math\n");
}
/* If verilog-2009 (SystemVerilog) is enabled, then include the
v2009 module. */
if (strcmp(generation, "2005-sv") == 0 ||
strcmp(generation, "2009") == 0 ||
strcmp(generation, "2012") == 0) {
fprintf(iconfig_file, "module:%s%cv2009.vpi\n", vpi_dir, sep);
fprintf(iconfig_file, "sys_func:%s%cv2009.sft\n", base, sep);
fprintf(iconfig_file, "module:v2009\n");
}
if (mtm != 0) fprintf(iconfig_file, "-T:%s\n", mtm);
@@ -1357,11 +1108,9 @@ int main(int argc, char **argv)
fprintf(iconfig_file, "generation:%s\n", gen_io_range_error);
fprintf(iconfig_file, "generation:%s\n", gen_strict_ca_eval);
fprintf(iconfig_file, "generation:%s\n", gen_strict_expr_width);
fprintf(iconfig_file, "generation:%s\n", gen_shared_loop_index);
fprintf(iconfig_file, "generation:%s\n", gen_verilog_ams);
fprintf(iconfig_file, "generation:%s\n", gen_icarus);
fprintf(iconfig_file, "warnings:%s\n", warning_flags);
fprintf(iconfig_file, "ignore_missing_modules:%s\n", ignore_missing_modules ? "true" : "false");
fprintf(iconfig_file, "out:%s\n", opath);
if (depfile) {
fprintf(iconfig_file, "depfile:%s\n", depfile);
@@ -1438,12 +1187,8 @@ int main(int argc, char **argv)
will append to the file, so this is necessary to make sure
it starts out empty. */
if (depfile) {
FILE *fd = fopen(depfile, "w");
if (!fd) {
fprintf(stderr, "%s: can't open %s file.\n\n%s\n", argv[0], depfile, HELP);
return 1;
}
fclose(fd);
FILE*fd = fopen(depfile, "w");
fclose(fd);
}
if (source_count == 0 && !version_flag) {
@@ -1458,12 +1203,8 @@ int main(int argc, char **argv)
/* Write the preprocessor command needed to preprocess a
single file. This may be used to preprocess library
files. */
fprintf(iconfig_file, "ivlpp:%s%civlpp %s -L -F\"%s\" -P\"%s\"\n",
ivlpp_dir, sep,
strchr(warning_flags, 'r') ? "-Wredef-all" :
strchr(warning_flags, 'R') ? "-Wredef-chg" : "",
defines_path, compiled_defines_path
);
fprintf(iconfig_file, "ivlpp:%s%civlpp -L -F\"%s\" -P\"%s\"\n",
ivlpp_dir, sep, defines_path, compiled_defines_path);
/* Done writing to the iconfig file. Close it now. */
fclose(iconfig_file);
+2 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2019 Stephen Williams ([email protected])
* Copyright (c) 1999-2013 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -233,7 +233,7 @@ NetESelect* NetESelect::dup_expr() const
NetESFunc* NetESFunc::dup_expr() const
{
NetESFunc*tmp = new NetESFunc(name_, type_, expr_width(), nparms(), is_overridden_);
NetESFunc*tmp = new NetESFunc(name_, type_, expr_width(), nparms());
ivl_assert(*this, tmp);
tmp->cast_signed(has_sign());
+397 -784
View File
File diff suppressed because it is too large Load Diff
+237 -454
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2019 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@@ -29,7 +29,6 @@
# include "netdarray.h"
# include "netparray.h"
# include "netvector.h"
# include "netenum.h"
# include "compiler.h"
# include <cstdlib>
# include <iostream>
@@ -76,8 +75,15 @@
*/
NetAssign_* PExpr::elaborate_lval(Design*, NetScope*, bool, bool) const
{
cerr << get_fileline() << ": Assignment l-value too complex." << endl;
return 0;
NetNet*ll = 0;
if (ll == 0) {
cerr << get_fileline() << ": Assignment l-value too complex."
<< endl;
return 0;
}
NetAssign_*lv = new NetAssign_(ll);
return lv;
}
/*
@@ -132,9 +138,6 @@ NetAssign_* PEConcat::elaborate_lval(Design*des,
continue;
}
/* A concatenation is always unsigned. */
tmp->set_signed(false);
/* Link the new l-value to the previous one. */
NetAssign_*last = tmp;
while (last->more)
@@ -147,6 +150,57 @@ NetAssign_* PEConcat::elaborate_lval(Design*des,
return res;
}
NetAssign_*PEIdent::scan_lname_for_nested_members_(Design*des, NetScope*scope,
const pform_name_t&cur_path) const
{
if (cur_path.size() == 1)
return 0;
pform_name_t use_path = cur_path;
name_component_t tail = use_path.back();
use_path.pop_back();
NetNet* reg = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
symbol_search(this, des, scope, use_path, reg, par, eve);
if (reg == 0) {
NetAssign_*tmp = scan_lname_for_nested_members_(des, scope, use_path);
if (tmp == 0)
return 0;
tmp = new NetAssign_(tmp);
tmp->set_property(tail.name);
return tmp;
}
if (reg->struct_type() && reg->struct_type()->packed()) {
NetAssign_*tmp = new NetAssign_(reg);
elaborate_lval_net_packed_member_(des, scope, tmp, tail);
return tmp;
}
#if 0
if (reg->struct_type() && reg->struct_type()->packed()) {
cerr << get_fileline() << ": sorry: "
<< "I don't know what to do with packed struct " << use_path
<< " with member " << tail << "." << endl;
return 0;
}
#endif
if (reg->struct_type() && !reg->struct_type()->packed()) {
cerr << get_fileline() << ": sorry: "
<< "I don't know what to do with unpacked struct " << use_path
<< " with member " << tail << "." << endl;
return 0;
}
if (reg->class_type()) {
return elaborate_lval_net_class_member_(des, scope, reg, tail.name);
}
return 0;
}
/*
* Handle the ident as an l-value. This includes bit and part selects
@@ -160,6 +214,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
NetNet* reg = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
perm_string method_name;
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval: "
@@ -180,31 +235,35 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
ivl_assert(*this, use_scope);
}
/* Try to find the base part of the path that names the
variable. The remainer is the member path. For example, if
the path is a.b.c.d, and a.b is the path to a variable,
then a.b becomes the base_path and c.d becomes the
member_path. If we cannot find the variable with any
prefix, then the base_path will be empty after this loop
and reg will remain nil. */
pform_name_t base_path = path_;
pform_name_t member_path;
while (reg == 0 && base_path.size() > 0) {
symbol_search(this, des, use_scope, base_path, reg, par, eve);
// Found it!
if (reg != 0) break;
// Not found. Try to pop another name off the base_path
// and push it to the front of the member_path.
member_path.push_front( base_path.back() );
base_path.pop_back();
symbol_search(this, des, use_scope, path_, reg, par, eve);
/* If the signal is not found, check to see if this is a
member of a struct. Take the name of the form "a.b.member",
remove the member and store it into method_name, and retry
the search with "a.b". */
if (reg == 0 && path_.size() >= 2) {
pform_name_t use_path = path_;
perm_string tmp_name = peek_tail_name(use_path);
use_path.pop_back();
symbol_search(this, des, use_scope, use_path, reg, par, eve);
if (reg && reg->struct_type()) {
method_name = tmp_name;
} else if (reg && reg->class_type()) {
method_name = tmp_name;
} else if (NetAssign_*subl = scan_lname_for_nested_members_(des, use_scope, path_)) {
return subl;
} else {
reg = 0;
}
}
/* The l-value must be a variable. If not, then give up and
print a useful error message. */
if (reg == 0) {
if (use_scope->type()==NetScope::FUNC
&& use_scope->func_def()->is_void()
&& use_scope->func_def()->return_sig()==0
&& use_scope->basename()==peek_tail_name(path_)) {
cerr << get_fileline() << ": error: "
<< "Cannot assign to " << path_
@@ -223,21 +282,18 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval: "
<< "Found l-value path_=" << path_
<< " as reg=" << reg->name()
<< " base_path=" << base_path
<< ", member_path=" << member_path
<< "Found l-value as reg."
<< " unpacked_dimensions()=" << reg->unpacked_dimensions() << endl;
}
// We are processing the tail of a string of names. For
// example, the Verilog may be "a.b.c", so we are processing
// example, the verilog may be "a.b.c", so we are processing
// "c" at this point. (Note that if method_name is not nil,
// then this is "a.b.c.method" and "a.b.c" is a struct or class.)
const name_component_t&name_tail = path_.back();
// Use the last index to determine what kind of select
// (bit/part/etc) we are processing. For example, the Verilog
// (bit/part/etc) we are processing. For example, the verilog
// may be "a.b.c[1][2][<index>]". All but the last index must
// be simple expressions, only the <index> may be a part
// select etc., so look at it to determine how we will be
@@ -272,27 +328,21 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
return 0;
}
// If we find that the matched variable is a packed struct,
// then we can handled it with the net_packed_member_ method.
if (reg->struct_type() && member_path.size() > 0) {
if (reg->struct_type() && !method_name.nil()) {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_packed_member_(des, use_scope, lv, member_path);
name_component_t tmp_name (method_name);
elaborate_lval_net_packed_member_(des, use_scope, lv, tmp_name);
return lv;
}
// If the variable is a class object, then handle it with the
// net_class_member_ method.
if (reg->class_type() && member_path.size() > 0 && gn_system_verilog()) {
NetAssign_*lv = elaborate_lval_net_class_member_(des, use_scope, reg, member_path);
if (reg->class_type() && !method_name.nil() && gn_system_verilog()) {
NetAssign_*lv = elaborate_lval_net_class_member_(des, use_scope, reg, method_name);
return lv;
}
// Past this point, we should have taken care of the cases
// where the name is a member/method of a struct/class.
// XXXX ivl_assert(*this, method_name.nil());
ivl_assert(*this, member_path.size() == 0);
ivl_assert(*this, method_name.nil());
bool need_const_idx = is_cassign || is_force || (reg->type()==NetNet::UNRESOLVED_WIRE);
@@ -349,7 +399,6 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
/* No select expressions. */
NetAssign_*lv = new NetAssign_(reg);
lv->set_signed(reg->get_signed());
return lv;
}
@@ -359,7 +408,7 @@ NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des,
{
if (!gn_system_verilog())
return 0;
if (scope->parent() == 0 || scope->type() == NetScope::CLASS)
if (scope->parent() == 0)
return 0;
if (path_.size() != 1)
return 0;
@@ -378,7 +427,7 @@ NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des,
NetScope*scope_method = find_method_containing_scope(*this, scope);
ivl_assert(*this, scope_method);
NetNet*this_net = scope_method->find_signal(perm_string::literal(THIS_TOKEN));
NetNet*this_net = scope_method->find_signal(perm_string::literal("@"));
if (this_net == 0) {
cerr << get_fileline() << ": internal error: "
<< "Unable to find 'this' port of " << scope_path(scope_method)
@@ -638,24 +687,20 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
unsigned long lwid;
bool rcl = reg->sb_to_slice(prefix_indices, lsb, loff, lwid);
ivl_assert(*this, rcl);
if (warn_ob_select) {
cerr << get_fileline()
<< ": warning: L-value packed array select of "
<< reg->name();
if (reg->unpacked_dimensions() > 0) cerr << "[]";
cerr << " has an undefined index." << endl;
}
cerr << get_fileline() << ": warning: L-value packed array "
<< "select of " << reg->name();
if (reg->unpacked_dimensions() > 0) cerr << "[]";
cerr << " has an undefined index." << endl;
lv->set_part(new NetEConst(verinum(verinum::Vx)), lwid);
return true;
// The index is undefined and this is a bit select.
} else {
if (warn_ob_select) {
cerr << get_fileline()
<< ": warning: L-value bit select of "
<< reg->name();
if (reg->unpacked_dimensions() > 0) cerr << "[]";
cerr << " has an undefined index." << endl;
}
cerr << get_fileline() << ": warning: L-value bit select of "
<< reg->name();
if (reg->unpacked_dimensions() > 0) cerr << "[]";
cerr << " has an undefined index." << endl;
lv->set_part(new NetEConst(verinum(verinum::Vx)), 1);
return true;
}
@@ -752,10 +797,12 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
// Constant bit select that does something useful.
long loff = reg->sb_to_idx(prefix_indices,lsb);
if (warn_ob_select && (loff < 0 || loff >= (long)reg->vector_width())) {
cerr << get_fileline() << ": warning: bit select "
if (loff < 0 || loff >= (long)reg->vector_width()) {
cerr << get_fileline() << ": error: bit select "
<< reg->name() << "[" <<lsb<<"]"
<< " is out of range." << endl;
des->errors += 1;
return 0;
}
if (reg->type()==NetNet::UNRESOLVED_WIRE) {
@@ -821,13 +868,10 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
ivl_assert(*this, reg);
if (! parts_defined_flag) {
if (warn_ob_select) {
cerr << get_fileline()
<< ": warning: L-value part select of "
<< reg->name();
if (reg->unpacked_dimensions() > 0) cerr << "[]";
cerr << " has an undefined index." << endl;
}
cerr << get_fileline() << ": warning: L-value part select of "
<< reg->name();
if (reg->unpacked_dimensions() > 0) cerr << "[]";
cerr << " has an undefined index." << endl;
// Use a width of two here so we can distinguish between an
// undefined bit or part select.
lv->set_part(new NetEConst(verinum(verinum::Vx)), 2);
@@ -890,11 +934,11 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
}
/* If the part select extends beyond the extremes of the
variable, then output a warning. Note that loff is
variable, then report an error. Note that loff is
converted to normalized form so is relative the
variable pins. */
if (warn_ob_select && (loff < 0 || moff >= (long)reg->vector_width())) {
if (loff < 0 || moff >= (long)reg->vector_width()) {
cerr << get_fileline() << ": warning: Part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is out of range." << endl;
@@ -1017,140 +1061,87 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
return true;
}
/*
* When the l-value turns out to be a class object, this method is
* called with the bound variable, and the method path. For example,
* if path_=a.b.c and a.b binds to the variable, then sig is b, and
* member_path=c. if path_=obj.base.x, and base_path=obj, then sig is
* obj, and member_path=base.x.
*/
NetAssign_* PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*scope,
NetNet*sig, pform_name_t member_path) const
NetNet*sig, const perm_string&method_name) const
{
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_class_member_: "
<< "l-value is property " << member_path
cerr << get_fileline() << ": elaborate_lval_net_class_member_: "
<< "l-value is property " << method_name
<< " of " << sig->name() << "." << endl;
}
const netclass_t*class_type = sig->class_type();
ivl_assert(*this, class_type);
// Iterate over the member_path. This handles nested class
// object, by generating nested NetAssign_ object. We start
// with lv==0, so the front of the member_path is the member
// of the outermost class. This generates an lv from sig. Then
// iterate over the remaining of the member_path, replacing
// the outer lv with an lv that nests the lv from the previous
// iteration.
NetAssign_*lv = 0;
do {
// Start with the first component of the member path...
perm_string method_name = peek_head_name(member_path);
// Pull that component from the member_path. We need to
// know the current member being worked on, and will
// need to know if there are more members to be worked on.
name_component_t member_cur = member_path.front();
member_path.pop_front();
/* Make sure the property is really present in the class. If
not, then generate an error message and return an error. */
int pidx = class_type->property_idx_from_name(method_name);
if (pidx < 0) {
cerr << get_fileline() << ": error: Class " << class_type->get_name()
<< " does not have a property " << method_name << "." << endl;
des->errors += 1;
return 0;
}
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_class_member_: "
<< "Processing member_cur=" << member_cur
property_qualifier_t qual = class_type->get_prop_qual(pidx);
if (qual.test_local() && ! class_type->test_scope_is_method(scope)) {
cerr << get_fileline() << ": error: "
<< "Local property " << class_type->get_prop_name(pidx)
<< " is not accessible (l-value) in this context."
<< " (scope=" << scope_path(scope) << ")" << endl;
des->errors += 1;
} else if (qual.test_static()) {
// Special case: this is a static property. Ignore the
// "this" sig and use the property itself, which is not
// part of the sig, as the l-value.
NetNet*psig = class_type->find_static_property(method_name);
ivl_assert(*this, psig);
NetAssign_*lv = new NetAssign_(psig);
return lv;
} else if (qual.test_const()) {
cerr << get_fileline() << ": error: "
<< "Property " << class_type->get_prop_name(pidx)
<< " is constant in this context." << endl;
des->errors += 1;
}
NetAssign_*lv = new NetAssign_(sig);
lv->set_property(method_name);
ivl_type_t ptype = class_type->get_prop_type(pidx);
const netdarray_t*mtype = dynamic_cast<const netdarray_t*> (ptype);
if (mtype) {
const name_component_t&name_tail = path_.back();
if (! name_tail.index.empty()) {
cerr << get_fileline() << ": sorry: "
<< "Array index of array properties not supported."
<< endl;
}
// Make sure the property is really present in the class. If
// not, then generate an error message and return an error.
int pidx = class_type->property_idx_from_name(method_name);
if (pidx < 0) {
cerr << get_fileline() << ": error: Class " << class_type->get_name()
<< " does not have a property " << method_name << "." << endl;
des->errors += 1;
return 0;
}
property_qualifier_t qual = class_type->get_prop_qual(pidx);
if (qual.test_local() && ! class_type->test_scope_is_method(scope)) {
cerr << get_fileline() << ": error: "
<< "Local property " << class_type->get_prop_name(pidx)
<< " is not accessible (l-value) in this context."
<< " (scope=" << scope_path(scope) << ")" << endl;
des->errors += 1;
} else if (qual.test_static()) {
// Special case: this is a static property. Ignore the
// "this" sig and use the property itself, which is not
// part of the sig, as the l-value.
NetNet*psig = class_type->find_static_property(method_name);
ivl_assert(*this, psig);
lv = new NetAssign_(psig);
return lv;
} else if (qual.test_const()) {
cerr << get_fileline() << ": error: "
<< "Property " << class_type->get_prop_name(pidx)
<< " is constant in this context." << endl;
des->errors += 1;
}
lv = lv? new NetAssign_(lv) : new NetAssign_(sig);
lv->set_property(method_name);
// Now get the type of the property.
ivl_type_t ptype = class_type->get_prop_type(pidx);
const netdarray_t*mtype = dynamic_cast<const netdarray_t*> (ptype);
if (mtype) {
if (! member_cur.index.empty()) {
cerr << get_fileline() << ": sorry: "
<< "Array index of array properties not supported."
<< endl;
des->errors += 1;
}
}
// If the current member is a class object, then get the
// type. We may wind up iterating, and need the proper
// class type.
class_type = dynamic_cast<const netclass_t*>(ptype);
} while (member_path.size() > 0);
}
return lv;
}
/*
* This method is caled to handle l-value identifiers that are packed
* structs. The lv is already attached to the variable, so this method
* calculates the part select that is defined by the member_path. For
* example, if the path_ is main.sub.sub_local, and the variable is
* main, then we know at this point that main is a packed struct, and
* lv contains the reference to the bound variable (main). In this
* case member_path==sub.sub_local, and it is up to this method to
* work out the part select that the member_path represents.
*/
bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
NetAssign_*lv,
pform_name_t member_path) const
const name_component_t&member_comp) const
{
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_packed_member_: "
<< "path_=" << path_
<< " member_path=" << member_path
<< endl;
}
const perm_string&member_name = member_comp.name;
NetNet*reg = lv->sig();
ivl_assert(*this, reg);
const netstruct_t*struct_type = reg->struct_type();
ivl_assert(*this, struct_type);
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_packed_member_: "
<< "Type=" << *struct_type
<< endl;
cerr << get_fileline() << ": debug: elaborate lval packed member: "
<< "path_=" << path_ << endl;
}
if (! struct_type->packed()) {
@@ -1160,302 +1151,94 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
return false;
}
// Looking for the base name. We need that to know about
// indices we may need to apply. This is to handle the case
// that the base is an array of structs, and not just a
// struct.
pform_name_t::const_reverse_iterator name_idx = path_.rbegin();
for (size_t idx = 1 ; idx < member_path.size() ; idx += 1)
++ name_idx;
if (name_idx->name != peek_head_name(member_path)) {
cerr << get_fileline() << ": internal error: "
<< "name_idx=" << name_idx->name
<< ", expecting member_name=" << peek_head_name(member_path)
<< endl;
des->errors += 1;
return false;
}
ivl_assert(*this, name_idx->name == peek_head_name(member_path));
++ name_idx;
const name_component_t&name_base = *name_idx;
// Shouldn't be seeing unpacked arrays of packed structs...
ivl_assert(*this, reg->unpacked_dimensions() == 0);
// These make up the "part" select that is the equivilent of
// following the member path through the nested structs. To
// start with, the off[set] is zero, and use_width is the
// width of the entire variable. The first member_comp is at
// some offset within the variable, and will have a reduced
// width. As we step through the member_path the off
// increases, and use_width shrinks.
unsigned long off = 0;
unsigned long use_width = struct_type->packed_width();
// This is a packed member, so the name is of the form
// "a.b[...].c[...]" which means that the path_ must have at
// least 2 components. We are processing "c[...]" at that
// point (otherwise known as member_name) so we'll save a
// reference to it in name_tail. We are also processing "b[]"
// so save that as name_base.
pform_name_t completed_path;
do {
const name_component_t member_comp = member_path.front();
const perm_string&member_name = member_comp.name;
ivl_assert(*this, path_.size() >= 2);
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_packed_member_: "
<< "Processing member_comp=" << member_comp
<< " (completed_path=" << completed_path << ")"
<< endl;
}
pform_name_t::const_reverse_iterator name_idx = path_.rbegin();
ivl_assert(*this, name_idx->name == member_name);
const name_component_t&name_tail = *name_idx;
++ name_idx;
const name_component_t&name_base = *name_idx;
// This is a packed member, so the name is of the form
// "a.b[...].c[...]" which means that the path_ must have at
// least 2 components. We are processing "c[...]" at that
// point (otherwise known as member_name) and we have a
// reference to it in member_comp.
// Calculate the offset within the packed structure of the
// member, and any indices. We will add in the offset of the
// struct into the packed array later. Note that this works
// for packed unions as well (although the offset will be 0
// for union members).
unsigned long off;
const netstruct_t::member_t* member = struct_type->packed_member(member_name, off);
// The member_path is the members we want to follow for the
// variable. For example, main[N].a.b may have main[N] as the
// base_name, and member_path=a.b. The member_name is the
// start of the member_path, and is "a". The member_name
// should be a member of the struct_type type.
if (member == 0) {
cerr << get_fileline() << ": error: Member " << member_name
<< " is not a member of variable " << reg->name() << endl;
des->errors += 1;
return false;
}
// Calculate the offset within the packed structure of the
// member, and any indices. We will add in the offset of the
// struct into the packed array later. Note that this works
// for packed unions as well (although the offset will be 0
// for union members).
unsigned long tmp_off;
const netstruct_t::member_t* member = struct_type->packed_member(member_name, tmp_off);
unsigned long use_width = member->net_type->packed_width();
if (member == 0) {
cerr << get_fileline() << ": error: Member " << member_name
<< " is not a member of struct type of "
<< reg->name()
<< "." << completed_path << endl;
des->errors += 1;
return false;
}
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_packed_member_: "
<< "Member type: " << *(member->net_type)
<< endl;
}
// Get the index component type. At this point, we only
// support bit select or none.
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
if (!name_tail.index.empty())
use_sel = name_tail.index.back().sel;
off += tmp_off;
ivl_assert(*this, use_width >= (unsigned long)member->net_type->packed_width());
use_width = member->net_type->packed_width();
ivl_assert(*this, use_sel == index_component_t::SEL_NONE || use_sel == index_component_t::SEL_BIT);
// At this point, off and use_width are the part select
// expressed by the member_comp, which is a member of the
// struct. We can further refine the part select with any
// indices that might be present.
if (! name_tail.index.empty()) {
// Get the index component type. At this point, we only
// support bit select or none.
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
if (!member_comp.index.empty())
use_sel = member_comp.index.back().sel;
// If there are index expressions in this l-value
// expression, then the implicit assumption is that the
// member is a vector type with packed dimensions. For
// example, if the l-value expression is "foo.member[1][2]",
// then the member should be something like:
// ... logic [h:l][m:n] foo;
// Get the dimensions from the netvector_t that this implies.
const netvector_t*mem_vec = dynamic_cast<const netvector_t*>(member->net_type);
ivl_assert(*this, mem_vec);
const vector<netrange_t>&mem_packed_dims = mem_vec->packed_dims();
if (use_sel != index_component_t::SEL_NONE
&& use_sel != index_component_t::SEL_BIT
&& use_sel != index_component_t::SEL_PART) {
cerr << get_fileline() << ": sorry: Assignments to part selects of "
"a struct member are not yet supported." << endl;
if (name_tail.index.size() > mem_packed_dims.size()) {
cerr << get_fileline() << ": error: "
<< "Too many index expressions for member." << endl;
des->errors += 1;
return false;
}
if (const netvector_t*mem_vec = dynamic_cast<const netvector_t*>(member->net_type)) {
// If the member type is a netvector_t, then it is a
// vector of atom or scaler objects. For example, if the
// l-value expression is "foo.member[1][2]",
// then the member should be something like:
// ... logic [h:l][m:n] member;
// There should be index expressions index the vector
// down, but there doesn't need to be all of them. We
// can, for example, be selecting a part of the vector.
// Evaluate all but the last index expression, into prefix_indices.
list<long>prefix_indices;
bool rc = evaluate_index_prefix(des, scope, prefix_indices, name_tail.index);
ivl_assert(*this, rc);
// We only need to process this if there are any
// index expressions. If not, then the packed
// vector can be handled atomically.
// In any case, this should be the tail of the
// member_path, because the array element of this
// kind of array cannot be a struct.
if (member_comp.index.size() > 0) {
// These are the dimensions defined by the type
const vector<netrange_t>&mem_packed_dims = mem_vec->packed_dims();
if (member_comp.index.size() > mem_packed_dims.size()) {
cerr << get_fileline() << ": error: "
<< "Too many index expressions for member." << endl;
des->errors += 1;
return false;
}
// Evaluate all but the last index expression, into prefix_indices.
list<long>prefix_indices;
bool rc = evaluate_index_prefix(des, scope, prefix_indices, member_comp.index);
ivl_assert(*this, rc);
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_packed_member_: "
<< "prefix_indices.size()==" << prefix_indices.size()
<< ", mem_packed_dims.size()==" << mem_packed_dims.size()
<< " (netvector_t context)"
<< endl;
}
long tail_off = 0;
unsigned long tail_wid = 0;
rc = calculate_part(this, des, scope, member_comp.index.back(), tail_off, tail_wid);
ivl_assert(*this, rc);
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_packed_member_: "
<< "calculate_part for tail returns tail_off=" << tail_off
<< ", tail_wid=" << tail_wid
<< endl;
}
// Now use the prefix_to_slice function to calculate the
// offset and width of the addressed slice of the member.
long loff;
unsigned long lwid;
prefix_to_slice(mem_packed_dims, prefix_indices, tail_off, loff, lwid);
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_packed_member_: "
<< "Calculate loff=" << loff << " lwid=" << lwid
<< " tail_off=" << tail_off << " tail_wid=" << tail_wid
<< " off=" << off << " use_width=" << use_width
<< endl;
}
off += loff;
use_width = lwid * tail_wid;
}
// The netvector_t only has atom elements, to
// there is no next struct type.
struct_type = 0;
} else if (const netparray_t*array = dynamic_cast<const netparray_t*> (member->net_type)) {
// If the member is a parray, then the elements
// are themselves packed object, including
// possibly a struct. Handle this by taking the
// part select of the current part of the
// variable, then stepping to the element type to
// possibly iterate through more of the member_path.
ivl_assert(*this, array->packed());
ivl_assert(*this, member_comp.index.size() > 0);
// These are the dimensions defined by the type
const vector<netrange_t>&mem_packed_dims = array->static_dimensions();
if (member_comp.index.size() != mem_packed_dims.size()) {
cerr << get_fileline() << ": error: "
<< "Incorrect number of index expressions for member "
<< member_name << "." << endl;
des->errors += 1;
return false;
}
// Evaluate all but the last index expression, into prefix_indices.
list<long>prefix_indices;
bool rc = evaluate_index_prefix(des, scope, prefix_indices, member_comp.index);
ivl_assert(*this, rc);
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_packed_member_: "
<< "prefix_indices.size()==" << prefix_indices.size()
<< ", mem_packed_dims.size()==" << mem_packed_dims.size()
<< " (netparray_t context)"
<< endl;
}
// Evaluate the last index expression into a constant long.
NetExpr*texpr = elab_and_eval(des, scope, member_comp.index.back().msb, -1, true);
long tmp;
if (texpr == 0 || !eval_as_long(tmp, texpr)) {
cerr << get_fileline() << ": error: "
<< "Array index expressions for member " << member_name
<< " must be constant here." << endl;
des->errors += 1;
return false;
}
delete texpr;
// Now use the prefix_to_slice function to calculate the
// offset and width of the addressed slice of the member.
long loff;
unsigned long lwid;
prefix_to_slice(mem_packed_dims, prefix_indices, tmp, loff, lwid);
ivl_type_t element_type = array->element_type();
long element_width = element_type->packed_width();
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_packed_member_: "
<< "parray subselection loff=" << loff
<< ", lwid=" << lwid
<< ", element_width=" << element_width
<< endl;
}
// The width and offset calculated from the
// indices is actually in elements, and not
// bits. In fact, in this context, the lwid should
// come down to 1 (one element).
off += loff * element_width;
ivl_assert(*this, lwid==1);
use_width = element_width;
// To move on to the next component in the member
// path, get the element type. For example, for
// the path a.b[1].c, we are processing b[1] here,
// and the element type should be a netstruct_t
// that will wind up containing the member c.
struct_type = dynamic_cast<const netstruct_t*> (element_type);
} else if (const netstruct_t*tmp_struct = dynamic_cast<const netstruct_t*> (member->net_type)) {
// If the member is itself a struct, then get
// ready to go on to the next iteration.
struct_type = tmp_struct;
} else if (const netenum_t*tmp_enum = dynamic_cast<const netenum_t*> (member->net_type)) {
// If the element is an enum, then we don't have
// anything special to do.
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_packed_member_: "
<< "Tail element is an enum: " << *tmp_enum
<< endl;
}
struct_type = 0;
} else {
// Unknown type?
cerr << get_fileline() << ": internal error: "
<< "Unexpected member type? " << *(member->net_type)
<< endl;
// Evaluate the last index expression into a constant long.
NetExpr*texpr = elab_and_eval(des, scope, name_tail.index.back().msb, -1, true);
long tmp;
if (texpr == 0 || !eval_as_long(tmp, texpr)) {
cerr << get_fileline() << ": error: "
"Array index expressions must be constant here." << endl;
des->errors += 1;
return false;
struct_type = 0;
}
// Complete this component of the path, mark it
// completed, and set up for the next component.
completed_path .push_back(member_comp);
member_path.pop_front();
delete texpr;
} while (member_path.size() > 0 && struct_type != 0);
// Now use the prefix_to_slice function to calculate the
// offset and width of the addressed slice of the member.
long loff;
unsigned long lwid;
prefix_to_slice(mem_packed_dims, prefix_indices, tmp, loff, lwid);
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_net_packed_member_: "
<< "After processing member_path, "
<< "off=" << off
<< ", use_width=" << use_width
<< ", completed_path=" << completed_path
<< ", member_path=" << member_path
<< endl;
off += loff;
use_width = lwid;
}
// The dimensions in the expression must match the packed
+30 -57
View File
@@ -328,66 +328,39 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
return false;
}
if (prefix_indices.size()+1 < sig->packed_dims().size()) {
// Here we have a slice that doesn't have enough indices
// to get to a single slice. For example:
// wire [9:0][5:1] foo
// ... foo[4:3] ...
// Make this work by finding the indexed slices and
// creating a generated slice that spans the whole
// range.
long loff, moff;
unsigned long lwid, mwid;
bool lrc;
lrc = sig->sb_to_slice(prefix_indices, lsb, loff, lwid);
ivl_assert(*this, lrc);
lrc = sig->sb_to_slice(prefix_indices, msb, moff, mwid);
ivl_assert(*this, lrc);
ivl_assert(*this, lwid == mwid);
if (moff > loff) {
lidx = loff;
midx = moff + mwid - 1;
} else {
lidx = moff;
midx = loff + lwid - 1;
}
} else {
long lidx_tmp = sig->sb_to_idx(prefix_indices, lsb);
long midx_tmp = sig->sb_to_idx(prefix_indices, msb);
/* Detect reversed indices of a part select. */
if (lidx_tmp > midx_tmp) {
cerr << get_fileline() << ": error: Part select "
<< sig->name() << "[" << msb << ":"
<< lsb << "] indices reversed." << endl;
cerr << get_fileline() << ": : Did you mean "
<< sig->name() << "[" << lsb << ":"
<< msb << "]?" << endl;
long tmp = midx_tmp;
midx_tmp = lidx_tmp;
lidx_tmp = tmp;
des->errors += 1;
}
/* Warn about a part select that is out of range. */
if (midx_tmp >= (long)sig->vector_width() || lidx_tmp < 0) {
cerr << get_fileline() << ": warning: Part select "
<< sig->name();
if (sig->unpacked_dimensions() > 0) {
cerr << "[]";
}
cerr << "[" << msb << ":" << lsb
<< "] is out of range." << endl;
long lidx_tmp = sig->sb_to_idx(prefix_indices, lsb);
long midx_tmp = sig->sb_to_idx(prefix_indices, msb);
/* Detect reversed indices of a part select. */
if (lidx_tmp > midx_tmp) {
cerr << get_fileline() << ": error: Part select "
<< sig->name() << "[" << msb << ":"
<< lsb << "] indices reversed." << endl;
cerr << get_fileline() << ": : Did you mean "
<< sig->name() << "[" << lsb << ":"
<< msb << "]?" << endl;
long tmp = midx_tmp;
midx_tmp = lidx_tmp;
lidx_tmp = tmp;
des->errors += 1;
}
/* This is completely out side the signal so just skip it. */
if (lidx_tmp >= (long)sig->vector_width() || midx_tmp < 0) {
return false;
}
midx = midx_tmp;
lidx = lidx_tmp;
/* Warn about a part select that is out of range. */
if (midx_tmp >= (long)sig->vector_width() || lidx_tmp < 0) {
cerr << get_fileline() << ": warning: Part select "
<< sig->name();
if (sig->unpacked_dimensions() > 0) {
cerr << "[]";
}
cerr << "[" << msb << ":" << lsb
<< "] is out of range." << endl;
}
/* This is completely out side the signal so just skip it. */
if (lidx_tmp >= (long)sig->vector_width() || midx_tmp < 0) {
return false;
}
midx = midx_tmp;
lidx = lidx_tmp;
break;
}
+450 -109
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2020 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@@ -54,16 +54,7 @@
# include <cassert>
# include "ivl_assert.h"
void set_scope_timescale(Design*des, NetScope*scope, PScope*pscope)
{
scope->time_unit(pscope->time_unit);
scope->time_precision(pscope->time_precision);
scope->time_from_timescale(pscope->has_explicit_timescale());
des->set_precision(pscope->time_precision);
}
typedef map<perm_string,LexicalScope::param_expr_t*>::const_iterator mparm_it_t;
typedef map<perm_string,LexicalScope::param_expr_t>::const_iterator mparm_it_t;
static void collect_parm_item_(Design*des, NetScope*scope, perm_string name,
const LexicalScope::param_expr_t&cur,
@@ -110,37 +101,65 @@ static void collect_parm_item_(Design*des, NetScope*scope, perm_string name,
}
static void collect_scope_parameters_(Design*des, NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t*>&parameters)
const map<perm_string,LexicalScope::param_expr_t>&parameters)
{
for (mparm_it_t cur = parameters.begin()
; cur != parameters.end() ; ++ cur ) {
collect_parm_item_(des, scope, cur->first, *(cur->second), false, false);
// A parameter can not have the same name as a genvar.
if (scope->find_genvar((*cur).first)) {
cerr << cur->second.get_fileline()
<< ": error: parameter and genvar in '"
<< scope->fullname() << "' have the same name '"
<< (*cur).first << "'." << endl;
des->errors += 1;
}
collect_parm_item_(des, scope, (*cur).first, (*cur).second, false, false);
}
}
static void collect_scope_localparams_(Design*des, NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t*>&localparams)
const map<perm_string,LexicalScope::param_expr_t>&localparams)
{
for (mparm_it_t cur = localparams.begin()
; cur != localparams.end() ; ++ cur ) {
collect_parm_item_(des, scope, cur->first, *(cur->second), false, true);
// A localparam can not have the same name as a genvar.
if (scope->find_genvar((*cur).first)) {
cerr << cur->second.get_fileline()
<< ": error: localparam and genvar in '"
<< scope->fullname() << "' have the same name '"
<< (*cur).first << "'." << endl;
des->errors += 1;
}
collect_parm_item_(des, scope, (*cur).first, (*cur).second, false, true);
}
}
static void collect_scope_specparams_(Design*des, NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t*>&specparams)
const map<perm_string,LexicalScope::param_expr_t>&specparams)
{
for (mparm_it_t cur = specparams.begin()
; cur != specparams.end() ; ++ cur ) {
collect_parm_item_(des, scope, cur->first, *(cur->second), true, false);
// A specparam can not have the same name as a genvar.
if (scope->find_genvar((*cur).first)) {
cerr << cur->second.get_fileline()
<< ": error: specparam and genvar in '"
<< scope->fullname() << "' have the same name '"
<< (*cur).first << "'." << endl;
des->errors += 1;
}
collect_parm_item_(des, scope, (*cur).first, (*cur).second, true, false);
}
}
/*
* Elaborate the enumeration into the given scope.
* Elaborate the enumeration into the given scope. If scope==0, then
* the enumeration goes into $root instead of a scope.
*/
static void elaborate_scope_enumeration(Design*des, NetScope*scope,
enum_type_t*enum_type)
@@ -165,7 +184,10 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
enum_type);
use_enum->set_line(enum_type->li);
scope->add_enumeration_set(enum_type, use_enum);
if (scope)
scope->add_enumeration_set(enum_type, use_enum);
else
des->add_enumeration_set(enum_type, use_enum);
size_t name_idx = 0;
// Find the enumeration width.
@@ -333,7 +355,10 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
}
rc_flag = use_enum->insert_name(name_idx, cur->name, cur_value);
rc_flag &= scope->add_enumeration_name(use_enum, cur->name);
if (scope)
rc_flag &= scope->add_enumeration_name(use_enum, cur->name);
else
rc_flag &= des->add_enumeration_name(use_enum, cur->name);
if (! rc_flag) {
cerr << use_enum->get_fileline()
@@ -363,6 +388,15 @@ static void elaborate_scope_enumerations(Design*des, NetScope*scope,
}
}
void elaborate_rootscope_enumerations(Design*des)
{
for (set<enum_type_t*>::const_iterator cur = pform_enum_sets.begin()
; cur != pform_enum_sets.end() ; ++ cur) {
enum_type_t*curp = *cur;
elaborate_scope_enumeration(des, 0, curp);
}
}
/*
* If the pclass includes an implicit and explicit constructor, then
* merge the implicit constructor into the explicit constructor as
@@ -453,9 +487,7 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
if (debug_scopes) {
cerr << pclass->get_fileline() <<": elaborate_scope_class: "
<< "Elaborate scope class " << pclass->pscope_name()
<< " within scope " << scope_path(scope)
<< endl;
<< "Elaborate scope class " << pclass->pscope_name() << endl;
}
class_type_t*base_class = dynamic_cast<class_type_t*> (use_type->base_type);
@@ -468,6 +500,7 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
netclass_t*use_base_class = 0;
if (base_class) {
ivl_assert(*pclass, scope);
use_base_class = scope->find_class(base_class->name);
if (use_base_class == 0) {
cerr << pclass->get_fileline() << ": error: "
@@ -482,34 +515,21 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
ivl_assert(*pclass, use_type->save_elaborated_type == 0);
use_type->save_elaborated_type = use_class;
NetScope*class_scope = new NetScope(scope, hname_t(pclass->pscope_name()),
NetScope::CLASS, scope->unit());
// Class scopes have no parent scope, because references are
// not allowed to escape a class method.
NetScope*class_scope = new NetScope(0, hname_t(pclass->pscope_name()),
NetScope::CLASS);
class_scope->set_line(pclass);
class_scope->set_class_def(use_class);
use_class->set_class_scope(class_scope);
use_class->set_definition_scope(scope);
set_scope_timescale(des, class_scope, pclass);
class_scope->add_typedefs(&pclass->typedefs);
// Elaborate enum types declared in the class. We need these
// now because enumeration constants can be used during scope
// elaboration.
if (debug_scopes) {
cerr << pclass->get_fileline() << ": elaborate_scope_class: "
<< "Elaborate " << pclass->enum_sets.size() << " enumerations"
<< " in class " << scope_path(class_scope)
<< ", scope=" << scope_path(scope) << "."
<< endl;
}
elaborate_scope_enumerations(des, class_scope, pclass->enum_sets);
// Collect the properties, elaborate them, and add them to the
// elaborated class definition.
for (map<perm_string, class_type_t::prop_info_t>::iterator cur = use_type->properties.begin()
; cur != use_type->properties.end() ; ++ cur) {
ivl_type_s*tmp = cur->second.type->elaborate_type(des, class_scope);
ivl_type_s*tmp = cur->second.type->elaborate_type(des, scope);
ivl_assert(*pclass, tmp);
if (debug_scopes) {
cerr << pclass->get_fileline() << ": elaborate_scope_class: "
@@ -528,7 +548,6 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
// Task methods are always automatic...
method_scope->is_auto(true);
method_scope->set_line(cur->second);
method_scope->add_imports(&cur->second->explicit_imports);
if (debug_scopes) {
cerr << cur->second->get_fileline() << ": elaborate_scope_class: "
@@ -547,7 +566,6 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
// Function methods are always automatic...
method_scope->is_auto(true);
method_scope->set_line(cur->second);
method_scope->add_imports(&cur->second->explicit_imports);
if (debug_scopes) {
cerr << cur->second->get_fileline() << ": elaborate_scope_class: "
@@ -558,7 +576,12 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
cur->second->elaborate_scope(des, method_scope);
}
scope->add_class(use_class);
if (scope) {
scope->add_class(use_class);
} else {
des->add_class(use_class, pclass);
}
}
static void elaborate_scope_classes(Design*des, NetScope*scope,
@@ -570,6 +593,18 @@ static void elaborate_scope_classes(Design*des, NetScope*scope,
}
}
void elaborate_rootscope_classes(Design*des)
{
if (pform_classes.empty())
return;
for (map<perm_string,PClass*>::iterator cur = pform_classes.begin()
; cur != pform_classes.end() ; ++ cur) {
blend_class_constructors(cur->second);
elaborate_scope_class(des, 0, cur->second);
}
}
static void replace_scope_parameters_(NetScope*scope, const LineInfo&loc,
const Module::replace_t&replacements)
{
@@ -618,7 +653,9 @@ static void elaborate_scope_task(Design*des, NetScope*scope, PTask*task)
NetScope*task_scope = new NetScope(scope, use_name, NetScope::TASK);
task_scope->is_auto(task->is_auto());
task_scope->set_line(task);
task_scope->add_imports(&task->explicit_imports);
if (scope==0)
des->add_root_task(task_scope, task);
if (debug_scopes) {
cerr << task->get_fileline() << ": elaborate_scope_task: "
@@ -636,6 +673,39 @@ static void elaborate_scope_tasks(Design*des, NetScope*scope,
for (tasks_it_t cur = tasks.begin()
; cur != tasks.end() ; ++ cur ) {
hname_t use_name( (*cur).first );
// A task can not have the same name as another scope object.
const NetScope *child = scope->child(use_name);
if (child) {
cerr << cur->second->get_fileline() << ": error: task and ";
child->print_type(cerr);
cerr << " in '" << scope->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
continue;
}
// A task can not have the same name as a genvar.
if (scope->find_genvar((*cur).first)) {
cerr << cur->second->get_fileline()
<< ": error: task and genvar in '"
<< scope->fullname() << "' have the same name '"
<< (*cur).first << "'." << endl;
des->errors += 1;
}
// A task can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter(des, (*cur).first,
ex_msb, ex_lsb);
if (parm) {
cerr << cur->second->get_fileline()
<< ": error: task and parameter in '"
<< scope->fullname() << "' have the same name '"
<< (*cur).first << "'." << endl;
des->errors += 1;
}
elaborate_scope_task(des, scope, cur->second);
}
@@ -648,7 +718,9 @@ static void elaborate_scope_func(Design*des, NetScope*scope, PFunction*task)
NetScope*task_scope = new NetScope(scope, use_name, NetScope::FUNC);
task_scope->is_auto(task->is_auto());
task_scope->set_line(task);
task_scope->add_imports(&task->explicit_imports);
if (scope==0)
des->add_root_task(task_scope, task);
if (debug_scopes) {
cerr << task->get_fileline() << ": elaborate_scope_func: "
@@ -666,11 +738,67 @@ static void elaborate_scope_funcs(Design*des, NetScope*scope,
for (funcs_it_t cur = funcs.begin()
; cur != funcs.end() ; ++ cur ) {
hname_t use_name( (*cur).first );
// A function can not have the same name as another scope object.
const NetScope *child = scope->child(use_name);
if (child) {
cerr << cur->second->get_fileline()
<< ": error: function and ";
child->print_type(cerr);
cerr << " in '" << scope->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
continue;
}
// A function can not have the same name as a genvar.
if (scope->find_genvar((*cur).first)) {
cerr << cur->second->get_fileline()
<< ": error: function and genvar in '"
<< scope->fullname() << "' have the same name '"
<< (*cur).first << "'." << endl;
des->errors += 1;
}
// A function can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter(des, (*cur).first,
ex_msb, ex_lsb);
if (parm) {
cerr << cur->second->get_fileline()
<< ": error: function and parameter in '"
<< scope->fullname() << "' have the same name '"
<< (*cur).first << "'." << endl;
des->errors += 1;
}
elaborate_scope_func(des, scope, cur->second);
}
}
void elaborate_rootscope_tasks(Design*des)
{
for (map<perm_string,PTaskFunc*>::iterator cur = pform_tasks.begin()
; cur != pform_tasks.end() ; ++ cur) {
if (PTask*task = dynamic_cast<PTask*> (cur->second)) {
elaborate_scope_task(des, 0, task);
continue;
}
if (PFunction*func = dynamic_cast<PFunction*>(cur->second)) {
elaborate_scope_func(des, 0, func);
continue;
}
cerr << cur->second->get_fileline() << ": internal error: "
<< "elaborate_rootscope_tasks does not understand "
<< "this object," << endl;
des->errors += 1;
}
}
class generate_schemes_work_item_t : public elaborator_work_item_t {
public:
generate_schemes_work_item_t(Design*des__, NetScope*scope, Module*mod)
@@ -710,23 +838,12 @@ bool PPackage::elaborate_scope(Design*des, NetScope*scope)
<< "Elaborate package " << scope_path(scope) << "." << endl;
}
scope->add_typedefs(&typedefs);
collect_scope_parameters_(des, scope, parameters);
collect_scope_localparams_(des, scope, localparams);
if (debug_scopes) {
cerr << get_fileline() << ": PPackage::elaborate_scope: "
<< "Elaborate " << enum_sets.size() << " enumerations"
<< " in package scope " << scope_path(scope) << "."
<< endl;
}
elaborate_scope_enumerations(des, scope, enum_sets);
elaborate_scope_classes(des, scope, classes_lexical);
elaborate_scope_funcs(des, scope, funcs);
elaborate_scope_tasks(des, scope, tasks);
elaborate_scope_events_(des, scope, events);
return true;
}
@@ -738,8 +855,6 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
<< "Elaborate " << scope_path(scope) << "." << endl;
}
scope->add_typedefs(&typedefs);
// Add the genvars to the scope.
typedef map<perm_string,LineInfo*>::const_iterator genvar_it_t;
for (genvar_it_t cur = genvars.begin(); cur != genvars.end(); ++ cur ) {
@@ -762,12 +877,6 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
replace_scope_parameters_(scope, *this, replacements);
if (debug_scopes) {
cerr << get_fileline() << ": Module::elaborate_scope: "
<< "Elaborate " << enum_sets.size() << " enumerations"
<< " in scope " << scope_path(scope) << "."
<< endl;
}
elaborate_scope_enumerations(des, scope, enum_sets);
assert(classes.size() == classes_lexical.size());
@@ -899,19 +1008,17 @@ bool PGenerate::generate_scope(Design*des, NetScope*container)
*/
bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
{
if (!local_index) {
// Check that the loop_index variable was declared in a
// genvar statement.
NetScope*cscope = container;
while (cscope && !cscope->find_genvar(loop_index))
cscope = cscope->parent();
if (!cscope) {
cerr << get_fileline() << ": error: genvar is missing for "
"generate \"loop\" variable '" << loop_index << "'."
<< endl;
des->errors += 1;
return false;
}
// Check that the loop_index variable was declared in a
// genvar statement.
NetScope*cscope = container;
while (cscope && !cscope->find_genvar(loop_index))
cscope = cscope->parent();
if (!cscope) {
cerr << get_fileline() << ": error: genvar is missing for "
"generate \"loop\" variable '" << loop_index << "'."
<< endl;
des->errors += 1;
return false;
}
// We're going to need a genvar...
@@ -929,6 +1036,56 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
return false;
}
// Check the generate block name.
// A generate "loop" can not have the same name as another
// scope object. Find any scope with this name, not just an
// exact match scope.
const NetScope *child = container->child_byname(scope_name);
if (child) {
cerr << get_fileline() << ": error: generate \"loop\" and ";
child->print_type(cerr);
cerr << " in '" << container->fullname()
<< "' have the same name '" << scope_name << "'." << endl;
des->errors += 1;
return false;
}
// A generate "loop" can not have the same name as a genvar.
if (container->find_genvar(scope_name)) {
cerr << get_fileline() << ": error: generate \"loop\" and "
"genvar in '" << container->fullname()
<< "' have the same name '" << scope_name << "'." << endl;
des->errors += 1;
}
// A generate "loop" can not have the same name as a named event.
const NetEvent *event = container->find_event(scope_name);
if (event) {
cerr << get_fileline() << ": error: generate \"loop\" and "
"named event in '" << container->fullname()
<< "' have the same name '" << scope_name << "'." << endl;
des->errors += 1;
}
// A generate "loop" can not have the same name as a parameter.
const NetExpr*tmsb;
const NetExpr*tlsb;
const NetExpr*texpr = container->get_parameter(des, scope_name,
tmsb, tlsb);
if (texpr != 0) {
cerr << get_fileline() << ": error: generate \"loop\" and "
"parameter in '" << container->fullname()
<< "' have the same name '" << scope_name << "'." << endl;
des->errors += 1;
}
// These have all been checked so we just need to skip the actual
// generation for these name conflicts. Not skipping these two will
// cause the compiler to have problems (assert, inf. loop, etc.).
if (container->get_parameter(des, loop_index, tmsb, tlsb)) return false;
if (container->find_event(loop_index)) return false;
genvar = init->value().as_long();
delete init_ex;
@@ -959,18 +1116,13 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
scope->add_imports(&explicit_imports);
// Set in the scope a localparam for the value of the
// genvar within this instance of the generate
// block. Code within this scope thus has access to the
// genvar as a constant.
{
verinum genvar_verinum;
if (gn_strict_expr_width_flag)
genvar_verinum = verinum(genvar, integer_width);
else
genvar_verinum = verinum(genvar);
verinum genvar_verinum(genvar);
genvar_verinum.has_sign(true);
NetEConstParam*gp = new NetEConstParam(scope,
loop_index,
@@ -1003,7 +1155,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
container->genvar_tmp_val = genvar;
delete step;
delete test_ex;
test_ex = elab_and_eval(des, container, loop_test, -1, true);
test_ex = elab_and_eval(des, container, loop_test, -1);
test = dynamic_cast<NetEConst*>(test_ex);
assert(test);
}
@@ -1040,6 +1192,45 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
}
hname_t use_name (scope_name);
// A generate "if" can not have the same name as another scope object.
const NetScope *child = container->child(use_name);
if (child) {
cerr << get_fileline() << ": error: generate \"if\" and ";
child->print_type(cerr);
cerr << " in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
return false;
}
// A generate "if" can not have the same name as a genvar.
if (container->find_genvar(scope_name)) {
cerr << get_fileline() << ": error: generate \"if\" and "
"genvar in '" << container->fullname()
<< "' have the same name '" << scope_name << "'." << endl;
des->errors += 1;
}
// A generate "if" can not have the same name as a named event.
const NetEvent *event = container->find_event(scope_name);
if (event) {
cerr << get_fileline() << ": error: generate \"if\" and "
"named event in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
// A generate "if" can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = container->get_parameter(des, scope_name,
ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: generate \"if\" and "
"parameter in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
if (debug_scopes)
cerr << get_fileline() << ": debug: Generate condition "
<< (else_flag? "(else)" : "(if)")
@@ -1060,7 +1251,6 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
// for myself. That is what I will pass to the subscope.
NetScope*scope = new NetScope(container, use_name, NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
scope->add_imports(&explicit_imports);
elaborate_subscope_(des, scope);
@@ -1144,6 +1334,44 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
// The name of the scope to generate, whatever that item is.
hname_t use_name (item->scope_name);
// A generate "case" can not have the same name as another scope object.
const NetScope *child = container->child(use_name);
if (child) {
cerr << get_fileline() << ": error: generate \"case\" and ";
child->print_type(cerr);
cerr << " in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
return false;
}
// A generate "case" can not have the same name as a genvar.
if (container->find_genvar(item->scope_name)) {
cerr << get_fileline() << ": error: generate \"case\" and "
"genvar in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
// A generate "case" can not have the same name as a named event.
const NetEvent *event = container->find_event(item->scope_name);
if (event) {
cerr << get_fileline() << ": error: generate \"case\" and "
"named event in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
// A generate "case" can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = container->get_parameter(des, item->scope_name,
ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: generate \"case\" and "
"parameter in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
item->probe_for_direct_nesting_();
if (item->direct_nested_) {
@@ -1163,8 +1391,6 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
scope->add_imports(&explicit_imports);
item->elaborate_subscope_(des, scope);
return true;
@@ -1173,6 +1399,46 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
bool PGenerate::generate_scope_nblock_(Design*des, NetScope*container)
{
hname_t use_name (scope_name);
// A generate "block" can not have the same name as another scope
// object.
const NetScope *child = container->child(use_name);
if (child) {
cerr << get_fileline() << ": error: generate \"block\" and ";
child->print_type(cerr);
cerr << " in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
return false;
}
// A generate "block" can not have the same name as a genvar.
if (container->find_genvar(scope_name)) {
cerr << get_fileline() << ": error: generate \"block\" and "
"genvar in '" << container->fullname()
<< "' have the same name '" << scope_name << "'." << endl;
des->errors += 1;
}
// A generate "block" can not have the same name as a named event.
const NetEvent *event = container->find_event(scope_name);
if (event) {
cerr << get_fileline() << ": error: generate \"block\" and "
"named event in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
// A generate "block" can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = container->get_parameter(des, scope_name,
ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: generate \"block\" and "
"parameter in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
if (debug_scopes)
cerr << get_fileline() << ": debug: Generate named block "
<< ": Generate scope=" << use_name << endl;
@@ -1180,7 +1446,6 @@ bool PGenerate::generate_scope_nblock_(Design*des, NetScope*container)
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
scope->add_imports(&explicit_imports);
elaborate_subscope_(des, scope);
@@ -1204,8 +1469,6 @@ void PGenerate::elaborate_subscope_direct_(Design*des, NetScope*scope)
void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
{
scope->add_typedefs(&typedefs);
// Add the genvars to this scope.
typedef map<perm_string,LineInfo*>::const_iterator genvar_it_t;
for (genvar_it_t cur = genvars.begin(); cur != genvars.end(); ++ cur ) {
@@ -1314,6 +1577,36 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
// Missing module instance names have already been rejected.
assert(get_name() != "");
// A module instance can not have the same name as another scope object.
const NetScope *child = sc->child(hname_t(get_name()));
if (child) {
cerr << get_fileline() << ": error: module <" << mod->mod_name()
<< "> instance and ";
child->print_type(cerr);
cerr << " in '" << sc->fullname()
<< "' have the same name '" << get_name() << "'." << endl;
des->errors += 1;
return;
}
// A module instance can not have the same name as a genvar.
if (sc->find_genvar(get_name())) {
cerr << get_fileline() << ": error: module <" << mod->mod_name()
<< "> instance and genvar in '" << sc->fullname()
<< "' have the same name '" << get_name() << "'." << endl;
des->errors += 1;
}
// A module instance can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = sc->get_parameter(des, get_name(), ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: module <" << mod->mod_name()
<< "> instance and parameter in '" << sc->fullname()
<< "' have the same name '" << get_name() << "'." << endl;
des->errors += 1;
}
// check for recursive instantiation by scanning the current
// scope and its parents. Look for a module instantiation of
// the same module, but farther up in the scope.
@@ -1421,10 +1714,6 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
<< "." << endl;
}
struct attrib_list_t*attrib_list;
unsigned attrib_list_n = 0;
attrib_list = evaluate_attributes(attributes, attrib_list_n, des, sc);
// Run through the module instances, and make scopes out of
// them. Also do parameter overrides that are done on the
// instantiation line.
@@ -1451,21 +1740,21 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
// Create the new scope as a MODULE with my name. Note
// that if this is a nested module, mark it thus so that
// scope searches will continue into the parent scope.
NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE, 0,
NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE,
bound_type_? true : false,
mod->program_block,
mod->is_interface);
my_scope->set_line(get_file(), mod->get_file(),
get_lineno(), mod->get_lineno());
my_scope->set_module_name(mod->mod_name());
my_scope->add_imports(&mod->explicit_imports);
for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1)
my_scope->attribute(attrib_list[adx].key, attrib_list[adx].val);
instances[idx] = my_scope;
set_scope_timescale(des, my_scope, mod);
// Set time units and precision.
my_scope->time_unit(mod->time_unit);
my_scope->time_precision(mod->time_precision);
my_scope->time_from_timescale(mod->time_from_timescale);
des->set_precision(mod->time_precision);
// Look for module parameter replacements. The "replace" map
// maps parameter name to replacement expression that is
@@ -1521,7 +1810,6 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
mod->elaborate_scope(des, my_scope, replace);
}
delete[]attrib_list;
/* Stash the instance array of scopes into the parent
scope. Later elaboration passes will use this vector to
@@ -1540,8 +1828,36 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
* no hierarchy, but neither does the NetEvent, until it is stored in
* the NetScope object.
*/
void PEvent::elaborate_scope(Design*, NetScope*scope) const
void PEvent::elaborate_scope(Design*des, NetScope*scope) const
{
// A named event can not have the same name as another scope object.
const NetScope *child = scope->child(hname_t(name_));
if (child) {
cerr << get_fileline() << ": error: named event and ";
child->print_type(cerr);
cerr << " in '" << scope->fullname()
<< "' have the same name '" << name_ << "'." << endl;
des->errors += 1;
}
// A named event can not have the same name as a genvar.
if (scope->find_genvar(name_)) {
cerr << get_fileline() << ": error: named event and "
<< "genvar in '" << scope->fullname()
<< "' have the same name '" << name_ << "'." << endl;
des->errors += 1;
}
// A named event can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter(des, name_, ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: named event and "
<< "parameter in '" << scope->fullname()
<< "' have the same name '" << name_ << "'." << endl;
des->errors += 1;
}
NetEvent*ev = new NetEvent(name_);
ev->set_line(*this);
scope->add_event(ev);
@@ -1559,8 +1875,6 @@ void PFunction::elaborate_scope(Design*des, NetScope*scope) const
// find otherwise.
scope->is_const_func(true);
scope->add_typedefs(&typedefs);
// Scan the parameters in the function, and store the information
// needed to evaluate the parameter expressions.
@@ -1579,8 +1893,6 @@ void PTask::elaborate_scope(Design*des, NetScope*scope) const
{
assert(scope->type() == NetScope::TASK);
scope->add_typedefs(&typedefs);
// Scan the parameters in the task, and store the information
// needed to evaluate the parameter expressions.
@@ -1616,6 +1928,37 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
if (pscope_name() != 0) {
hname_t use_name(pscope_name());
// A named block can not have the same name as another scope
// object.
const NetScope *child = scope->child(use_name);
if (child) {
cerr << get_fileline() << ": error: named block and ";
child->print_type(cerr);
cerr << " in '" << scope->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
return;
}
// A named block can not have the same name as a genvar.
if (scope->find_genvar(pscope_name())) {
cerr << get_fileline() << ": error: named block and "
"genvar in '" << scope->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
// A named block can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter(des, pscope_name(),
ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: named block and "
"parameter in '" << scope->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
if (debug_scopes)
cerr << get_fileline() << ": debug: "
<< "Elaborate block scope " << use_name
@@ -1628,8 +1971,6 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
: NetScope::BEGIN_END);
my_scope->set_line(get_file(), get_lineno());
my_scope->is_auto(scope->is_auto());
my_scope->add_imports(&explicit_imports);
my_scope->add_typedefs(&typedefs);
// Scan the parameters in the scope, and store the information
// needed to evaluate the parameter expressions.
+121 -87
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2020 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@@ -47,8 +47,6 @@
using namespace std;
#if 0
/* These functions are not currently used. */
static bool get_const_argument(NetExpr*exp, verinum&res)
{
switch (exp->expr_type()) {
@@ -75,6 +73,8 @@ static bool get_const_argument(NetExpr*exp, verinum&res)
return true;
}
#if 0
/* This function is not currently used. */
static bool get_const_argument(NetExpr*exp, long&res)
{
verinum tmp;
@@ -578,10 +578,10 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
// source code for the definition may be:
// function new(...);
// endfunction
// In this case, the "@" port (THIS_TOKEN) is the synthetic
// "this" argument and we also use it as a return value at
// the same time.
ret_sig = scope->find_signal(perm_string::literal(THIS_TOKEN));
// In this case, the "@" port is the synthetic "this"
// argument and we also use it as a return value at the
// same time.
ret_sig = scope->find_signal(perm_string::literal("@"));
ivl_assert(*this, ret_sig);
if (debug_elaborate)
@@ -757,11 +757,6 @@ void PTaskFunc::elaborate_sig_ports_(Design*des, NetScope*scope,
<< "Function arguments must be input ports." << endl;
des->errors += 1;
}
if (tmp->unpacked_dimensions() != 0) {
cerr << get_fileline() << ": sorry: Subroutine ports with "
"unpacked dimensions are not yet supported." << endl;
des->errors += 1;
}
}
}
@@ -876,13 +871,13 @@ static ivl_type_s*elaborate_type(Design*des, NetScope*scope,
return 0;
}
static netparray_t* elaborate_parray_type(Design*des, NetScope*scope, const LineInfo*li,
static netparray_t* elaborate_parray_type(Design*des, NetScope*scope,
parray_type_t*data_type)
{
vector<netrange_t>packed_dimensions;
bool dimensions_ok = evaluate_ranges(des, scope, li, packed_dimensions, * data_type->dims);
ivl_assert(*data_type, dimensions_ok);
bool bad_range = evaluate_ranges(des, scope, packed_dimensions, * data_type->dims);
ivl_assert(*data_type, !bad_range);
ivl_type_s*element_type = elaborate_type(des, scope, data_type->base_type);
@@ -932,35 +927,54 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
wtype = NetNet::WIRE;
is_implicit_scalar = true;
}
// Certain contexts, such as arguments to functions, presume
// "reg" instead of "wire". The parser reports these as
// IMPLICIT_REG. Also, certain cases, such as:
// fun(string arg1) ...
// are implicitly NOT scalar, so detect that case here.
if (wtype == NetNet::IMPLICIT_REG) {
wtype = NetNet::REG;
if (data_type_!=IVL_VT_STRING)
is_implicit_scalar = true;
}
if (debug_elaborate) {
cerr << get_fileline() << ": PWire::elaborate_sig: "
<< "Signal " << basename()
<< ", wtype=" << wtype
<< ", data_type_=" << data_type_
<< ", is_implicit_scalar=" << (is_implicit_scalar?"true":"false")
<< endl;
is_implicit_scalar = true;
}
unsigned wid = 1;
vector<netrange_t>packed_dimensions;
NetScope*base_type_scope = scope;
if (set_data_type_ && !set_data_type_->name.nil())
base_type_scope = scope->find_typedef_scope(des, set_data_type_);
des->errors += error_cnt_;
// A signal can not have the same name as a scope object.
const NetScope *child = scope->child_byname(name_);
if (child) {
cerr << get_fileline() << ": error: signal and ";
child->print_type(cerr);
cerr << " in '" << scope->fullname()
<< "' have the same name '" << name_ << "'." << endl;
des->errors += 1;
}
// A signal can not have the same name as a genvar.
const LineInfo *genvar = scope->find_genvar(name_);
if (genvar) {
cerr << get_fileline() << ": error: signal and genvar in '"
<< scope->fullname() << "' have the same name '" << name_
<< "'." << endl;
des->errors += 1;
}
// A signal can not have the same name as a parameter. Note
// that we treat enumeration literals similar to parameters,
// so if the name matches an enumeration literal, it will be
// caught here.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter(des, name_, ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: signal and parameter in '"
<< scope->fullname() << "' have the same name '" << name_
<< "'." << endl;
des->errors += 1;
}
// A signal can not have the same name as a named event.
const NetEvent *event = scope->find_event(name_);
if (event) {
cerr << get_fileline() << ": error: signal and named event in '"
<< scope->fullname() << "' have the same name '" << name_
<< "'." << endl;
des->errors += 1;
}
if (port_set_ || net_set_) {
if (warn_implicit_dimensions
@@ -979,7 +993,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
<< " inherits dimensions from var/net." << endl;
}
bool dimensions_ok = true;
bool bad_range = false;
vector<netrange_t> plist, nlist;
/* If they exist get the port definition MSB and LSB */
if (port_set_ && !port_.empty()) {
@@ -987,7 +1001,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
cerr << get_fileline() << ": PWire::elaborate_sig: "
<< "Evaluate ranges for port " << basename() << endl;
}
dimensions_ok &= evaluate_ranges(des, scope, this, plist, port_);
bad_range |= evaluate_ranges(des, scope, plist, port_);
nlist = plist;
/* An implicit port can have a range so note that here. */
is_implicit_scalar = false;
@@ -995,13 +1009,13 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
assert(port_set_ || port_.empty());
/* If they exist get the net/etc. definition MSB and LSB */
if (net_set_ && !net_.empty() && dimensions_ok) {
if (net_set_ && !net_.empty() && !bad_range) {
nlist.clear();
if (debug_elaborate) {
cerr << get_fileline() << ": PWire::elaborate_sig: "
<< "Evaluate ranges for net " << basename() << endl;
}
dimensions_ok &= evaluate_ranges(des, base_type_scope, this, nlist, net_);
bad_range |= evaluate_ranges(des, scope, nlist, net_);
}
assert(net_set_ || net_.empty());
@@ -1072,10 +1086,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
list<netrange_t>unpacked_dimensions;
netdarray_t*netdarray = 0;
NetScope*array_type_scope = scope;
if (uarray_type_ && !uarray_type_->name.nil())
array_type_scope = scope->find_typedef_scope(des, uarray_type_);
for (list<pform_range_t>::const_iterator cur = unpacked_.begin()
; cur != unpacked_.end() ; ++cur) {
PExpr*use_lidx = cur->first;
@@ -1094,51 +1104,51 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
}
// Special case: Detect the mark for a QUEUE
// declaration, which is the dimensions [null:max_idx].
if (dynamic_cast<PENull*>(use_lidx)) {
// declaration, which is the dimensions [null:<nil>].
if (use_ridx==0 && dynamic_cast<PENull*>(use_lidx)) {
netvector_t*vec = new netvector_t(packed_dimensions, data_type_);
vec->set_signed(get_signed());
packed_dimensions.clear();
ivl_assert(*this, netdarray==0);
long max_idx;
if (use_ridx) {
NetExpr*tmp = elab_and_eval(des, array_type_scope, use_ridx,
-1, true);
NetEConst*cv = dynamic_cast<NetEConst*>(tmp);
if (cv == 0) {
cerr << get_fileline() << ": error: queue '" << name_
<< "' bound must be a constant!" << endl;
des->errors += 1;
max_idx = -1;
} else {
verinum res = cv->value();
if (res.is_defined()) {
max_idx = res.as_long();
if (max_idx < 0) {
cerr << get_fileline() << ": error: queue '"
<< name_ << "' bound must be positive ("
<< max_idx << ")!" << endl;
des->errors += 1;
max_idx = -1;
}
} else {
cerr << get_fileline() << ": error: queue '" << name_
<< "' bound is undefined!" << endl;
des->errors += 1;
max_idx = -1;
}
}
} else max_idx = -1;
netdarray = new netqueue_t(vec, max_idx);
netdarray = new netqueue_t(vec);
continue;
}
// Cannot handle dynamic arrays of arrays yet.
ivl_assert(*this, netdarray==0);
ivl_assert(*this, use_lidx && use_ridx);
NetExpr*lexp = elab_and_eval(des, scope, use_lidx, -1, true);
NetExpr*rexp = elab_and_eval(des, scope, use_ridx, -1, true);
if ((lexp == 0) || (rexp == 0)) {
cerr << get_fileline() << ": internal error: There is "
<< "a problem evaluating indices for ``"
<< name_ << "''." << endl;
des->errors += 1;
return 0;
}
bool const_flag = true;
verinum lval, rval;
const_flag &= get_const_argument(lexp, lval);
const_flag &= get_const_argument(rexp, rval);
delete rexp;
delete lexp;
long index_l, index_r;
evaluate_range(des, array_type_scope, this, *cur, index_l, index_r);
if (! const_flag) {
cerr << get_fileline() << ": error: The indices "
<< "are not constant for array ``"
<< name_ << "''." << endl;
des->errors += 1;
/* Attempt to recover from error, */
index_l = 0;
index_r = 0;
} else {
index_l = lval.as_long();
index_r = rval.as_long();
}
if (abs(index_r - index_l) > warn_dimension_size) {
cerr << get_fileline() << ": warning: Array dimension "
"is greater than " << warn_dimension_size
@@ -1175,14 +1185,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
NetLogic*pull = 0;
if (wtype == NetNet::SUPPLY0 || wtype == NetNet::SUPPLY1) {
if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
<< "Generate a SUPPLY pull for the ";
if (wtype == NetNet::SUPPLY0) cerr << "supply0";
else cerr << "supply1";
cerr << " net." << endl;
}
NetLogic::TYPE pull_type = (wtype==NetNet::SUPPLY1)
? NetLogic::PULLUP
: NetLogic::PULLDOWN;
@@ -1193,6 +1195,14 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
pull->pin(0).drive1(IVL_DR_SUPPLY);
des->add_node(pull);
wtype = NetNet::WIRE;
if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
<< "Generate a SUPPLY pull for the ";
if (wtype == NetNet::SUPPLY0) cerr << "supply0";
else cerr << "supply1";
cerr << " net." << endl;
}
}
@@ -1228,7 +1238,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
} else if (enum_type_t*enum_type = dynamic_cast<enum_type_t*>(set_data_type_)) {
list<named_pexpr_t>::const_iterator sample_name = enum_type->names->begin();
const netenum_t*use_enum = base_type_scope->find_enumeration_for_name(des, sample_name->name);
const netenum_t*use_enum = scope->find_enumeration_for_name(sample_name->name);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal " << wtype
@@ -1261,7 +1271,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
// The trick here is that the parray type has an
// arbitrary sub-type, and not just a scalar bit...
netparray_t*use_type = elaborate_parray_type(des, scope, this, parray_type);
netparray_t*use_type = elaborate_parray_type(des, scope, parray_type);
// Should not be getting packed dimensions other than
// through the parray type declaration.
ivl_assert(*this, packed_dimensions.empty());
@@ -1323,3 +1333,27 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
return sig;
}
void Design::root_elaborate_sig(void)
{
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
; cur != classes_.end() ; ++ cur) {
netclass_t*cur_class = cur->second;
PClass*cur_pclass = class_to_pclass_[cur_class];
cur_class->elaborate_sig(this, cur_pclass);
}
for (map<NetScope*,PTaskFunc*>::iterator cur = root_tasks_.begin()
; cur != root_tasks_.end() ; ++ cur) {
if (debug_elaborate) {
cerr << cur->second->get_fileline() << ": root_elaborate_sig: "
<< "Elaborate_sig for root task/func " << scope_path(cur->first) << endl;
}
cur->second->elaborate_sig(this, cur->first);
}
}
+12 -29
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2020 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-2014 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
@@ -17,13 +17,11 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "PExpr.h"
# include "pform_types.h"
# include "netlist.h"
# include "netclass.h"
# include "netdarray.h"
# include "netenum.h"
# include "netqueue.h"
# include "netparray.h"
# include "netscalar.h"
# include "netstruct.h"
@@ -78,13 +76,9 @@ static void elaborate_array_ranges(Design*des, NetScope*scope,
*/
ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*scope)
{
// User-defined types must be elaborated in the context
// where they were defined.
if (!name.nil())
scope = scope->find_typedef_scope(des, this);
ivl_assert(*this, scope);
Definitions*use_definitions = scope;
if (use_definitions == 0)
use_definitions = des;
map<Definitions*,ivl_type_s*>::iterator pos = cache_type_elaborate_.lower_bound(use_definitions);
if (pos != cache_type_elaborate_.end() && pos->first == use_definitions)
@@ -151,13 +145,13 @@ ivl_type_s* class_type_t::elaborate_type_raw(Design*, NetScope*) const
* available at the right time. At that time, the netenum_t* object is
* stashed in the scope so that I can retrieve it here.
*/
ivl_type_s* enum_type_t::elaborate_type_raw(Design*, NetScope*scope) const
ivl_type_s* enum_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
{
ivl_assert(*this, scope);
ivl_type_s*tmp = scope->enumeration_for_key(this);
if (tmp == 0 && scope->unit()) {
tmp = scope->unit()->enumeration_for_key(this);
}
if (tmp) return tmp;
tmp = des->enumeration_for_key(this);
return tmp;
}
@@ -220,9 +214,9 @@ netstruct_t* struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
// There may be several names that are the same type:
// <data_type> name1, name2, ...;
// Process all the member, and give them a type.
for (list<decl_assignment_t*>::iterator cur_name = curp->names->begin()
; cur_name != curp->names->end() ; ++ cur_name) {
decl_assignment_t*namep = *cur_name;
for (list<decl_assignment_t*>::iterator name = curp->names->begin()
; name != curp->names->end() ; ++ name) {
decl_assignment_t*namep = *name;
netstruct_t::member_t memb;
memb.name = namep->name;
@@ -251,21 +245,10 @@ ivl_type_s* uarray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
return res;
}
// Special case: if the dimension is null:nil. this is a queue.
if (dynamic_cast<PENull*>(cur->first)) {
cerr << get_fileline() << ": sorry: "
<< "SV queues inside classes are not yet supported." << endl;
des->errors += 1;
// FIXME: Need to set the max size if cur->second is defined
ivl_type_s*res = new netqueue_t(btype, -1);
return res;
}
vector<netrange_t> dimensions;
bool dimensions_ok = evaluate_ranges(des, scope, this, dimensions, *dims);
bool bad_range = evaluate_ranges(des, scope, dimensions, *dims);
if (!dimensions_ok) {
if (bad_range) {
cerr << get_fileline() << " : warning: "
<< "Bad dimensions for type here." << endl;
}
+191 -933
View File
File diff suppressed because it is too large Load Diff
+15 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2013 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
@@ -123,12 +123,6 @@ bool NetFF::emit_node(struct target_t*tgt) const
return true;
}
bool NetLatch::emit_node(struct target_t*tgt) const
{
tgt->lpm_latch(this);
return true;
}
bool NetLiteral::emit_node(struct target_t*tgt) const
{
return tgt->net_literal(this);
@@ -510,12 +504,26 @@ int Design::emit(struct target_t*tgt) const
if (tgt->start_design(this) == false)
return -2;
for (map<NetScope*,PTaskFunc*>::const_iterator scope = root_tasks_.begin()
; scope != root_tasks_.end() ; ++ scope) {
scope->first->emit_scope(tgt);
scope->first->emit_defs(tgt);
}
// enumerate package scopes
for (map<perm_string,NetScope*>::const_iterator scope = packages_.begin()
; scope != packages_.end() ; ++ scope) {
scope->second->emit_scope(tgt);
}
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
; cur != classes_.end() ; ++cur) {
const NetScope*use_scope = cur->second->class_scope();
cur->second->emit_scope(tgt);
tgt->class_type(use_scope, cur->second);
cur->second->emit_defs(tgt);
}
// enumerate root scopes
for (list<NetScope*>::const_iterator scope = root_scopes_.begin()
; scope != root_scopes_.end(); ++ scope ) {
+154 -297
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2020 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2014 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
@@ -545,7 +545,7 @@ NetEConst* NetEBComp::eval_eqeq_real_(bool ne_flag, const NetExpr*le, const NetE
bool flag = get_real_arguments(le, re, lval, rval);
if (! flag) return 0;
verinum result(((lval == rval) != ne_flag) ?
verinum result(((lval == rval) ^ ne_flag) ?
verinum::V1 : verinum::V0, 1);
NetEConst*res = new NetEConst(result);
ivl_assert(*this, res);
@@ -570,11 +570,11 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag, const NetExpr*le, const NetExpr*r
const verinum::V ne_res = ne_flag? verinum::V1 : verinum::V0;
verinum::V res = eq_res;
unsigned top = lv.len();
if (rv.len() < top)
top = rv.len();
// The two expressions should already be padded to the same size.
ivl_assert(*this, lv.len() == rv.len());
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1) {
for (unsigned idx = 0 ; idx < top ; idx += 1) {
bool x_bit_present = false;
@@ -611,6 +611,60 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag, const NetExpr*le, const NetExpr*r
}
}
if (res != verinum::Vx) {
verinum::V lpad = verinum::V0;
verinum::V rpad = verinum::V0;
if (lv.has_sign() && lv.get(lv.len()-1) == verinum::V1)
lpad = verinum::V1;
if (rv.has_sign() && rv.get(rv.len()-1) == verinum::V1)
rpad = verinum::V1;
for (unsigned idx = top ; idx < lv.len() ; idx += 1)
switch (lv.get(idx)) {
case verinum::Vx:
case verinum::Vz:
res = verinum::Vx;
break;
case verinum::V0:
if (res != verinum::Vx && rpad != verinum::V0)
res = ne_res;
break;
case verinum::V1:
if (res != verinum::Vx && rpad != verinum::V1)
res = ne_res;
break;
default:
break;
}
for (unsigned idx = top ; idx < rv.len() ; idx += 1)
switch (rv.get(idx)) {
case verinum::Vx:
case verinum::Vz:
res = verinum::Vx;
break;
case verinum::V0:
if (res != verinum::Vx && lpad != verinum::V0)
res = ne_res;
break;
case verinum::V1:
if (res != verinum::Vx && lpad != verinum::V1)
res = ne_res;
break;
default:
break;
}
}
NetEConst*result = new NetEConst(verinum(res, 1));
ivl_assert(*this, result);
return result;
@@ -627,15 +681,41 @@ NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr
verinum::V res = verinum::V1;
// The two expressions should already be padded to the same size.
ivl_assert(*this, lv.len() == rv.len());
// Find the smallest argument length.
unsigned cnt = lv.len();
if (cnt > rv.len()) cnt = rv.len();
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1)
// Check the common bits.
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
if (lv.get(idx) != rv.get(idx)) {
res = verinum::V0;
break;
}
bool is_signed = lv.has_sign() && rv.has_sign();
// If the left value is longer check it against the pad bit.
if (res == verinum::V1) {
verinum::V pad = verinum::V0;
if (is_signed) pad = rv.get(rv.len()-1);
for (unsigned idx = cnt ; idx < lv.len() ; idx += 1)
if (lv.get(idx) != pad) {
res = verinum::V0;
break;
}
}
// If the right value is longer check it against the pad bit.
if (res == verinum::V1) {
verinum::V pad = verinum::V0;
if (is_signed) pad = lv.get(lv.len()-1);
for (unsigned idx = cnt ; idx < rv.len() ; idx += 1) {
if (rv.get(idx) != pad)
res = verinum::V0;
break;
}
}
if (ne_flag) {
if (res == verinum::V0) res = verinum::V1;
else res = verinum::V0;
@@ -646,55 +726,6 @@ NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr
return result;
}
NetEConst* NetEBComp::eval_weqeq_(bool ne_flag, const NetExpr*le, const NetExpr*re) const
{
const NetEConst*lc = dynamic_cast<const NetEConst*>(le);
const NetEConst*rc = dynamic_cast<const NetEConst*>(re);
if (lc == 0 || rc == 0) return 0;
const verinum&lv = lc->value();
const verinum&rv = rc->value();
const verinum::V eq_res = ne_flag ? verinum::V0 : verinum::V1;
const verinum::V ne_res = ne_flag ? verinum::V1 : verinum::V0;
verinum::V res = eq_res;
// The two expressions should already be padded to the same size.
ivl_assert(*this, lv.len() == rv.len());
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1) {
// An X or Z in the R-value matches any L-value.
switch (rv.get(idx)) {
case verinum::Vx:
case verinum::Vz:
continue;
default:
break;
}
// An X or Z in the L-value that is not matches by an R-value X/Z returns undefined.
switch (lv.get(idx)) {
case verinum::Vx:
case verinum::Vz:
res = verinum::Vx;
continue;
default:
break;
}
// A hard (0/1) mismatch gives a not-equal result.
if (rv.get(idx) != lv.get(idx)) {
res = ne_res;
break;
}
}
NetEConst*result = new NetEConst(verinum(res, 1));
ivl_assert(*this, result);
return result;
}
NetEConst* NetEBComp::eval_arguments_(const NetExpr*l, const NetExpr*r) const
{
NetEConst*res = 0;
@@ -708,10 +739,6 @@ NetEConst* NetEBComp::eval_arguments_(const NetExpr*l, const NetExpr*r) const
res = eval_eqeq_(false, l, r);
break;
case 'w': // Wild equality (==?)
res = eval_weqeq_(false, l, r);
break;
case 'G': // >=
res = eval_gteq_(l, r);
break;
@@ -728,10 +755,6 @@ NetEConst* NetEBComp::eval_arguments_(const NetExpr*l, const NetExpr*r) const
res = eval_eqeq_(true, l, r);
break;
case 'W': // Wild not-equal (!=?)
res = eval_weqeq_(true, l, r);
break;
case '<': // Less than
res = eval_less_(l, r);
break;
@@ -808,10 +831,44 @@ NetExpr* NetEBDiv::eval_arguments_(const NetExpr*l, const NetExpr*r) const
return tmp;
}
NetEConst* NetEBLogic::eval_tree_real_(const NetExpr*l, const NetExpr*r) const
{
double lval;
double rval;
bool flag = get_real_arguments(l, r, lval, rval);
if (! flag) return 0;
verinum::V res;
switch (op_) {
case 'a': // Logical AND (&&)
if ((lval != 0.0) && (rval != 0.0))
res = verinum::V1;
else
res = verinum::V0;
break;
case 'o': // Logical OR (||)
if ((lval != 0.0) || (rval != 0.0))
res = verinum::V1;
else
res = verinum::V0;
break;
default:
return 0;
}
NetEConst*tmp = new NetEConst(verinum(res, 1));
ivl_assert(*this, tmp);
eval_debug(this, tmp, true);
return tmp;
}
NetEConst* NetEBLogic::eval_arguments_(const NetExpr*l, const NetExpr*r) const
{
// NetEBLogic arguments should have already been reduced so real is not possible.
ivl_assert(*this, (l->expr_type() != IVL_VT_REAL) && (r->expr_type() != IVL_VT_REAL));
if (l->expr_type() == IVL_VT_REAL || r->expr_type() == IVL_VT_REAL)
return eval_tree_real_(l,r);
assert(expr_type() == IVL_VT_LOGIC);
const NetEConst*lc = dynamic_cast<const NetEConst*>(l);
@@ -844,39 +901,25 @@ NetEConst* NetEBLogic::eval_arguments_(const NetExpr*l, const NetExpr*r) const
case 'a': // Logical AND (&&)
if ((lv == verinum::V0) || (rv == verinum::V0))
res = verinum::V0;
else if ((lv == verinum::V1) && (rv == verinum::V1))
res = verinum::V1;
else
res = verinum::Vx;
break;
case 'o': // Logical OR (||)
if ((lv == verinum::V1) || (rv == verinum::V1))
res = verinum::V1;
else if ((lv == verinum::V0) && (rv == verinum::V0))
res = verinum::V0;
else
res = verinum::Vx;
break;
case 'q': // Logical implication (->)
if ((lv == verinum::V0) || (rv == verinum::V1))
res = verinum::V1;
else if ((lv == verinum::V1) && (rv == verinum::V0))
res = verinum::V0;
else
res = verinum::Vx;
break;
case 'Q': // Logical equivalence (<->)
if (((lv == verinum::V0) && (rv == verinum::V0)) ||
((lv == verinum::V1) && (rv == verinum::V1)))
res = verinum::V1;
else if (((lv == verinum::V0) && (rv == verinum::V1)) ||
((lv == verinum::V1) && (rv == verinum::V0)))
res = verinum::V0;
else
res = verinum::Vx;
break;
default:
@@ -1054,7 +1097,6 @@ NetEConst* NetEBShift::eval_arguments_(const NetExpr*l, const NetExpr*r) const
break;
case 'r':
lv.has_sign(false);
// fallthrough
case 'R':
val = cast_to_width(lv >> shift, wid);
break;
@@ -1506,7 +1548,6 @@ NetEConst* NetEUReduce::eval_arguments_(const NetExpr*ex) const
case 'A':
invert = true;
// fallthrough
case '&': {
res = verinum::V1;
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
@@ -1516,7 +1557,6 @@ NetEConst* NetEUReduce::eval_arguments_(const NetExpr*ex) const
case 'N':
invert = true;
// fallthrough
case '|': {
res = verinum::V0;
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
@@ -1526,7 +1566,6 @@ NetEConst* NetEUReduce::eval_arguments_(const NetExpr*ex) const
case 'X':
invert = true;
// fallthrough
case '^': {
/* Reduction XOR. */
unsigned ones = 0, unknown = 0;
@@ -1578,7 +1617,6 @@ NetExpr* NetECast::eval_arguments_(const NetExpr*ex) const
res_val = cast_to_width(res_val, expr_width());
res = new NetEConst(res_val);
}
// fallthrough
case 'v':
if (const NetECReal*val = dynamic_cast<const NetECReal*>(ex)) {
verinum res_val(val->value().as_double(), false);
@@ -1893,111 +1931,15 @@ NetExpr* NetESFunc::evaluate_min_max_(ID id, const NetExpr*arg0_,
return res;
}
static void no_string_arg(const NetESFunc*info, unsigned arg_num)
NetEConst* NetESFunc::evaluate_countbits_(const NetExpr* /*arg0*/,
const NetExpr* /*arg1*/) const
{
cerr << info->get_fileline() << ": error: constant function "
<< info->name() << "() does not support a string argument ("
<< arg_num+1 << ")." << endl;
return 0;
}
NetEConst* NetESFunc::evaluate_countbits_() const
NetEConst* NetESFunc::evaluate_countones_(const NetExpr* /*arg*/) const
{
const NetEConst*tmpi = dynamic_cast<const NetEConst*>(parms_[0]);
NetEConst*res = 0;
if (tmpi) {
verinum value = tmpi->value();
if (value.is_string()) {
no_string_arg(this, 0);
return 0;
}
/* Find which values need to be counted. */
bool count_0 = false;
bool count_1 = false;
bool count_z = false;
bool count_x = false;
for (unsigned arg=1; arg < parms_.size(); ++arg) {
const NetEConst*argi = dynamic_cast<const NetEConst*>(parms_[arg]);
if (! argi) return 0;
verinum check_for = argi->value();
if (check_for.is_string()) {
no_string_arg(this, arg);
return 0;
}
switch (check_for[0]) {
case verinum::V0:
count_0 = true;
break;
case verinum::V1:
count_1 = true;
break;
case verinum::Vz:
count_z = true;
break;
case verinum::Vx:
count_x = true;
break;
}
}
/* Search each bit of the vector looking for the values to
* be counted. */
int count = 0;
for (unsigned bit=0; bit < value.len(); ++bit) {
switch (value[bit]) {
case verinum::V0:
if (count_0) ++count;
break;
case verinum::V1:
if (count_1) ++count;
break;
case verinum::Vz:
if (count_z) ++count;
break;
case verinum::Vx:
if (count_x) ++count;
break;
}
}
verinum tmp (count, integer_width);
tmp.has_sign(true);
res = new NetEConst(tmp);
ivl_assert(*this, res);
}
return res;
}
NetEConst* NetESFunc::evaluate_countones_(const NetExpr* arg) const
{
const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg);
NetEConst*res = 0;
if (tmpi) {
verinum value = tmpi->value();
int count = 0;
if (value.is_string()) {
no_string_arg(this, 0);
return 0;
}
for (unsigned bit=0; bit < value.len(); ++bit) {
if (value[bit] == verinum::V1) ++count;
}
verinum tmp (count, integer_width);
tmp.has_sign(true);
res = new NetEConst(tmp);
ivl_assert(*this, res);
}
return res;
return 0;
}
/* Get the total number of dimensions for the given expression. */
@@ -2020,92 +1962,19 @@ NetEConst* NetESFunc::evaluate_dimensions_(const NetExpr*arg) const
return new NetEConst(verinum(verinum(res), integer_width));
}
NetEConst* NetESFunc::evaluate_isunknown_(const NetExpr* arg) const
NetEConst* NetESFunc::evaluate_isunknown_(const NetExpr* /*arg*/) const
{
const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg);
NetEConst*res = 0;
if (tmpi) {
verinum value = tmpi->value();
unsigned is_unknown = 1;
if (value.is_string()) {
no_string_arg(this, 0);
return 0;
}
if (value.is_defined()) is_unknown = 0;
verinum tmp (is_unknown, 1U);
tmp.has_sign(false);
res = new NetEConst(tmp);
ivl_assert(*this, res);
}
return res;
return 0;
}
static bool is_onehot(verinum&value, bool zero_is_okay)
NetEConst* NetESFunc::evaluate_onehot_(const NetExpr* /*arg*/) const
{
bool found_a_one = false;
for (unsigned bit=0; bit < value.len(); ++bit) {
if (value[bit] == verinum::V1) {
if (found_a_one) return false;
found_a_one = true;
}
}
/* If no one bit was found return true if zero is okay. */
if (zero_is_okay) found_a_one = true;
return found_a_one;
return 0;
}
NetEConst* NetESFunc::evaluate_onehot_(const NetExpr* arg) const
NetEConst* NetESFunc::evaluate_onehot0_(const NetExpr* /*arg*/) const
{
const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg);
NetEConst*res = 0;
if (tmpi) {
verinum value = tmpi->value();
if (value.is_string()) {
no_string_arg(this, 0);
return 0;
}
verinum tmp (is_onehot(value, false), 1U);
tmp.has_sign(false);
res = new NetEConst(tmp);
ivl_assert(*this, res);
}
return res;
}
NetEConst* NetESFunc::evaluate_onehot0_(const NetExpr* arg) const
{
const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg);
NetEConst*res = 0;
if (tmpi) {
verinum value = tmpi->value();
if (value.is_string()) {
no_string_arg(this, 0);
return 0;
}
verinum tmp (is_onehot(value, true), 1U);
tmp.has_sign(false);
res = new NetEConst(tmp);
ivl_assert(*this, res);
}
return res;
return 0;
}
/* Get the number of unpacked dimensions for the given expression. */
@@ -2277,7 +2146,7 @@ NetExpr* NetESFunc::evaluate_two_arg_(ID id, const NetExpr*arg0,
{
switch (id) {
case CTBITS:
return evaluate_countbits_();
return evaluate_countbits_(arg0, arg1);
/* The array functions are handled together. */
case HIGH:
case INCR:
@@ -2348,12 +2217,12 @@ NetESFunc::ID NetESFunc::built_in_id_() const
built_in_func["$unpacked_dimensions" ] = UPDIMS;
}
/* This is available in 1800-2009 and later. */
/* These are available in 1800-2009 and later. */
if (funcs_need_init && (generation_flag >= GN_VER2009)) {
built_in_func["$countones" ] = CTONES;
}
/* This is available in 1800-2012 and later. */
/* These are available in 1800-2012 and later. */
if (funcs_need_init && (generation_flag >= GN_VER2012)) {
built_in_func["$countbits" ] = CTBITS;
}
@@ -2380,11 +2249,7 @@ NetESFunc::ID NetESFunc::built_in_id_() const
NetExpr* NetESFunc::eval_tree()
{
/* We don't support evaluating overridden functions. */
if (is_overridden_)
return 0;
/* Get the ID for this system function if it can be used as a
/* Get the ID for this system function if it is can be used as a
* constant function. */
ID id = built_in_id_();
if (id == NOT_BUILT_IN) return 0;
@@ -2392,9 +2257,8 @@ NetExpr* NetESFunc::eval_tree()
switch (parms_.size()) {
case 1:
if (! takes_nargs_(id, 1)) {
cerr << get_fileline() << ": error: constant function "
<< name_ << "() does not support a single argument."
<< endl;
cerr << get_fileline() << ": error: " << name_
<< "() does not support a single argument." << endl;
return 0;
}
eval_expr(parms_[0]);
@@ -2402,9 +2266,8 @@ NetExpr* NetESFunc::eval_tree()
case 2:
if (! takes_nargs_(id, 2)) {
cerr << get_fileline() << ": error: constant function "
<< name_ << "() does not support two arguments."
<< endl;
cerr << get_fileline() << ": error: " << name_
<< "() does not support two arguments." << endl;
return 0;
}
eval_expr(parms_[0]);
@@ -2414,21 +2277,15 @@ NetExpr* NetESFunc::eval_tree()
default:
/* Check to see if the function was called correctly. */
if (! takes_nargs_(id, parms_.size())) {
cerr << get_fileline() << ": error: constant function "
<< name_ << "() does not support " << parms_.size()
cerr << get_fileline() << ": error: " << name_
<< "() does not support " << parms_.size()
<< " arguments." << endl;
return 0;
}
if (id == CTBITS) {
for (unsigned bit = 0; bit < parms_.size(); ++bit) {
eval_expr(parms_[bit]);
}
return evaluate_countbits_();
} else {
cerr << get_fileline() << ": sorry: constant functions with "
<< parms_.size() << " arguments are not supported: "
<< name_ << "()." << endl;
}
// HERE: Need to add support for a multi argument $countbits().
cerr << get_fileline() << ": sorry: functions with "
<< parms_.size() << " arguments are not supported: "
<< name_ << "()." << endl;
return 0;
}
}
-128
View File
@@ -1,128 +0,0 @@
/*
* Copyright (c) 2016 Martin Whitaker (icarus@martin-whitaker.me.uk)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
# include <cstdlib>
# include <sstream>
# include "netlist.h"
# include "functor.h"
# include "compiler.h"
# include "ivl_assert.h"
/*
* The exposenodes functor is primarily provided for use by the vlog95
* target. To implement some LPM objects, it needs to take a bit or part
* of one of the LPM inputs. If that input is not connected to a real
* net in the design, we need to create a net at that point so that
* there is something to which we can apply a bit or part select. This
* has the effect of splitting the synthesised structure at that point.
* Rather than creating a new net, we just look for a temporary net
* created by the synthesis process (there should be at least one) and
* reset its "local" flag. We also prepend another '_' to the synthetic
* name to avoid name collisions when we recompile the vlog95 output
* (because NetScope::local_symbol() doesn't actually check that the
* name it generates is unique).
*/
struct exposenodes_functor : public functor_t {
unsigned count;
virtual void lpm_mux(Design*des, NetMux*obj);
virtual void lpm_part_select(Design*des, NetPartSelect*obj);
virtual void lpm_substitute(Design*des, NetSubstitute*obj);
};
static bool expose_nexus(Nexus*nex)
{
NetNet*sig = 0;
for (Link*cur = nex->first_nlink() ; cur ; cur = cur->next_nlink()) {
// Don't expose nodes that are attached to constants
if (dynamic_cast<NetConst*> (cur->get_obj()))
return false;
if (dynamic_cast<NetLiteral*> (cur->get_obj()))
return false;
NetNet*cur_sig = dynamic_cast<NetNet*> (cur->get_obj());
if (cur_sig == 0)
continue;
if (!cur_sig->local_flag())
return false;
sig = cur_sig;
}
assert(sig);
ostringstream res;
res << "_" << sig->name();
sig->rename(lex_strings.make(res.str()));
sig->local_flag(false);
return true;
}
/*
* The vlog95 target implements a wide mux as a hierarchy of 2:1 muxes,
* picking off one bit of the select input at each level of the hierarchy.
*/
void exposenodes_functor::lpm_mux(Design*, NetMux*obj)
{
if (obj->sel_width() == 1)
return;
if (expose_nexus(obj->pin_Sel().nexus()))
count += 1;
}
/*
* A VP part select is going to select a part from its input.
*/
void exposenodes_functor::lpm_part_select(Design*, NetPartSelect*obj)
{
if (obj->dir() != NetPartSelect::VP)
return;
if (expose_nexus(obj->pin(1).nexus()))
count += 1;
}
/*
* A substitute is going to select one or two parts from the wider input signal.
*/
void exposenodes_functor::lpm_substitute(Design*, NetSubstitute*obj)
{
if (expose_nexus(obj->pin(1).nexus()))
count += 1;
}
void exposenodes(Design*des)
{
exposenodes_functor exposenodes;
exposenodes.count = 0;
if (verbose_flag) {
cout << " ... Look for intermediate nodes" << endl << flush;
}
des->functor(&exposenodes);
if (verbose_flag) {
cout << " ... Exposed " << exposenodes.count
<< " intermediate signals." << endl << flush;
}
}
+20 -54
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2020 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2015 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -274,18 +274,7 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope, NetExpr*root)
if (op_ == 'E' || op_ == 'N') {
NetCaseCmp*gate = new NetCaseCmp(scope, scope->local_symbol(),
width, op_=='E' ? NetCaseCmp::EEQ : NetCaseCmp::NEQ);
gate->set_line(*this);
connect(gate->pin(0), osig->pin(0));
connect(gate->pin(1), lsig->pin(0));
connect(gate->pin(2), rsig->pin(0));
des->add_node(gate);
return osig;
}
if (op_ == 'w' || op_ == 'W') {
NetCaseCmp*gate = new NetCaseCmp(scope, scope->local_symbol(),
width, op_=='w' ? NetCaseCmp::WEQ : NetCaseCmp::WNE);
width, op_=='E'?NetCaseCmp::EEQ:NetCaseCmp::NEQ);
gate->set_line(*this);
connect(gate->pin(0), osig->pin(0));
connect(gate->pin(1), lsig->pin(0));
@@ -346,7 +335,6 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope, NetExpr*root)
des->errors += 1;
return 0;
}
// fallthrough
case 'e': // ==
connect(dev->pin_AEB(), osig->pin(0));
break;
@@ -365,7 +353,6 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope, NetExpr*root)
des->errors += 1;
return 0;
}
// fallthrough
case 'n': // !=
connect(dev->pin_ANEB(), osig->pin(0));
break;
@@ -399,8 +386,7 @@ NetNet* NetEBPow::synthesize(Design*des, NetScope*scope, NetExpr*root)
powr->set_line(*this);
des->add_node(powr);
// The lpm_pwr object only cares about the signedness of the exponent.
powr->set_signed( right_->has_sign() );
powr->set_signed( has_sign() );
connect(powr->pin_DataA(), lsig->pin(0));
connect(powr->pin_DataB(), rsig->pin(0));
@@ -545,40 +531,27 @@ NetNet* NetEBLogic::synthesize(Design*des, NetScope*scope, NetExpr*root)
return 0;
}
NetLogic*olog;
perm_string oname = scope->local_symbol();
/* Create the logic OR/AND gate. This has a single bit output,
* with single bit inputs for the two operands. */
switch (op()) {
case 'a':
olog = new NetLogic(scope, oname, 3, NetLogic::AND, 1, true);
break;
case 'o':
olog = new NetLogic(scope, oname, 3, NetLogic::OR, 1, true);
break;
case 'q':
olog = new NetLogic(scope, oname, 3, NetLogic::IMPL, 1, true);
break;
case 'Q':
olog = new NetLogic(scope, oname, 3, NetLogic::EQUIV, 1, true);
break;
default:
cerr << get_fileline() << ": sorry: "
<< human_readable_op(op_)
<< " is not currently supported." << endl;
des->errors += 1;
return 0;
}
olog->set_line(*this);
des->add_node(olog);
netvector_t*osig_tmp = new netvector_t(expr_type());
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, osig_tmp);
osig->set_line(*this);
osig->local_flag(true);
NetLogic*olog;
perm_string oname = scope->local_symbol();
/* Create the logic OR/AND gate. This has a single bit output,
* with single bit inputs for the two operands. */
if (op() == 'o') {
olog = new NetLogic(scope, oname, 3, NetLogic::OR, 1, true);
} else {
assert(op() == 'a');
olog = new NetLogic(scope, oname, 3, NetLogic::AND, 1, true);
}
olog->set_line(*this);
des->add_node(olog);
connect(osig->pin(0), olog->pin(0));
/* The left and right operands have already been reduced to a
@@ -760,18 +733,12 @@ NetNet* NetEConcat::synthesize(Design*des, NetScope*scope, NetExpr*root)
}
}
if (flag == false) {
delete[]tmp;
return 0;
}
if (flag == false) return 0;
ivl_assert(*this, data_type != IVL_VT_NO_TYPE);
/* If this is a replication of zero just return 0. */
if (expr_width() == 0) {
delete[]tmp;
return 0;
}
if (expr_width() == 0) return 0;
/* Make a NetNet object to carry the output vector. */
perm_string path = scope->local_symbol();
@@ -1374,7 +1341,6 @@ static NetEvWait* make_func_trigger(Design*des, NetScope*scope, NetExpr*root)
if (nset && (nset->size() > 0)) {
NetEvent*ev = new NetEvent(scope->local_symbol());
ev->set_line(*root);
ev->local_flag(true);
NetEvProbe*pr = new NetEvProbe(scope, scope->local_symbol(),
ev, NetEvProbe::ANYEDGE,
+1 -19
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2012 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
@@ -78,10 +78,6 @@ void functor_t::lpm_ff(Design*, NetFF*)
{
}
void functor_t::lpm_latch(Design*, NetLatch*)
{
}
void functor_t::lpm_logic(Design*, NetLogic*)
{
}
@@ -106,10 +102,6 @@ void functor_t::sign_extend(Design*, NetSignExtend*)
{
}
void functor_t::lpm_substitute(Design*, NetSubstitute*)
{
}
void functor_t::lpm_ureduce(Design*, NetUReduce*)
{
}
@@ -223,11 +215,6 @@ void NetFF::functor_node(Design*des, functor_t*fun)
fun->lpm_ff(des, this);
}
void NetLatch::functor_node(Design*des, functor_t*fun)
{
fun->lpm_latch(des, this);
}
void NetLiteral::functor_node(Design*des, functor_t*fun)
{
fun->lpm_literal(des, this);
@@ -268,11 +255,6 @@ void NetSignExtend::functor_node(Design*des, functor_t*fun)
fun->sign_extend(des, this);
}
void NetSubstitute::functor_node(Design*des, functor_t*fun)
{
fun->lpm_substitute(des, this);
}
void NetUReduce::functor_node(Design*des, functor_t*fun)
{
fun->lpm_ureduce(des, this);
+1 -7
View File
@@ -1,7 +1,7 @@
#ifndef IVL_functor_H
#define IVL_functor_H
/*
* Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2014 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
@@ -75,9 +75,6 @@ struct functor_t {
/* This method is called for each FF in the design. */
virtual void lpm_ff(class Design*des, class NetFF*);
/* This method is called for each LATCH in the design. */
virtual void lpm_latch(class Design*des, class NetLatch*);
/* Handle LPM combinational logic devices. */
virtual void lpm_logic(class Design*des, class NetLogic*);
@@ -92,9 +89,6 @@ struct functor_t {
/* This method is called for each power. */
virtual void lpm_pow(class Design*des, class NetPow*);
/* This method is called for each part substitute. */
virtual void lpm_substitute(class Design*des, class NetSubstitute*);
/* This method is called for each unary reduction gate. */
virtual void lpm_ureduce(class Design*des, class NetUReduce*);
+2 -7
View File
@@ -1,4 +1,4 @@
.TH iverilog-vpi 1 "Jan 29th, 2017" "" "Version %M.%n%E"
.TH iverilog-vpi 1 "May 10th, 2015" "" "Version %M.%n%E"
.SH NAME
iverilog-vpi - Compile front end for VPI modules
@@ -26,11 +26,6 @@ becomes \fIfoo.vpi\fP.
Include the named library in the link of the VPI module. This allows
VPI modules to further reference external libraries.
.TP 8
.B -L\fIdirectory\fP
Add \fIdirectory\fP to the list of directories that will be searched
for library files.
.TP 8
.B -I\fIdirectory\fP
Add \fIdirectory\fP to the list of directories that will be searched
@@ -120,7 +115,7 @@ iverilog(1), vvp(1),
.SH COPYRIGHT
.nf
Copyright \(co 2002\-2017 Stephen Williams
Copyright \(co 2002\-2015 Stephen Williams
This document can be freely redistributed according to the terms of the
GNU General Public License version 2.0
+1 -10
View File
@@ -35,7 +35,6 @@ CCSRC=
CXSRC=
OBJ=
LIB=
LIBDIR=
OUT=
INCOPT=
DEFS=
@@ -82,9 +81,6 @@ do
-l*) LIB="$LIB $parm"
;;
-L*) LIBDIR="$LIBDIR $parm"
;;
-I*) INCOPT="$INCOPT $parm"
;;
@@ -96,11 +92,6 @@ do
exit;
;;
--ccflags)
echo "$CXXFLAGS"
exit;
;;
--ldflags)
echo "$LDFLAGS"
exit;
@@ -157,4 +148,4 @@ then
fi
echo "Making $OUT from $OBJ..."
exec $LD -o $OUT $LDFLAGS $LIBDIR $OBJ $LIB $LDLIBS
exec $LD -o $OUT $LDFLAGS $OBJ $LIB $LDLIBS
-6
View File
@@ -181,7 +181,6 @@ ivl_parameter_width
ivl_path_condit
ivl_path_delay
ivl_path_is_condit
ivl_path_is_parallel
ivl_path_scope
ivl_path_source
ivl_path_source_negedge
@@ -212,9 +211,6 @@ ivl_scope_enumerates
ivl_scope_event
ivl_scope_events
ivl_scope_file
ivl_scope_func_type
ivl_scope_func_signed
ivl_scope_func_width
ivl_scope_is_auto
ivl_scope_is_cell
ivl_scope_lineno
@@ -281,7 +277,6 @@ ivl_stmt_block_stmt
ivl_stmt_call
ivl_stmt_case_count
ivl_stmt_case_expr
ivl_stmt_case_quality
ivl_stmt_case_stmt
ivl_stmt_cond_expr
ivl_stmt_cond_false
@@ -296,7 +291,6 @@ ivl_stmt_lval
ivl_stmt_lvals
ivl_stmt_lwidth
ivl_stmt_name
ivl_stmt_needs_t0_trigger
ivl_stmt_nevent
ivl_stmt_opcode
ivl_stmt_parm
+14 -56
View File
@@ -1,7 +1,7 @@
#ifndef IVL_ivl_target_H
#define IVL_ivl_target_H
/*
* Copyright (c) 2000-2020 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -265,8 +265,6 @@ typedef enum ivl_logic_e {
IVL_LO_BUFT = 24, /* transparent bufz. (NOT "tri-state") */
IVL_LO_BUFZ = 5,
IVL_LO_CMOS = 22,
IVL_LO_EQUIV = 25,
IVL_LO_IMPL = 26,
IVL_LO_NAND = 6,
IVL_LO_NMOS = 7,
IVL_LO_NOR = 8,
@@ -282,6 +280,7 @@ typedef enum ivl_logic_e {
IVL_LO_RPMOS = 16,
IVL_LO_XNOR = 18,
IVL_LO_XOR = 19,
IVL_LO_UDP = 21
} ivl_logic_t;
@@ -307,10 +306,8 @@ typedef enum ivl_lpm_type_e {
IVL_LPM_CONCAT = 16,
IVL_LPM_CONCATZ = 36, /* Transparent concat */
IVL_LPM_CMP_EEQ= 18, /* Case EQ (===) */
IVL_LPM_CMP_EQX= 37, /* Wildcard EQ (casex) */
IVL_LPM_CMP_EQX= 37, /* Wildcard EQ (==?) */
IVL_LPM_CMP_EQZ= 38, /* casez EQ */
IVL_LPM_CMP_WEQ= 41,
IVL_LPM_CMP_WNE= 42,
IVL_LPM_CMP_EQ = 10,
IVL_LPM_CMP_GE = 1,
IVL_LPM_CMP_GT = 2,
@@ -318,7 +315,6 @@ typedef enum ivl_lpm_type_e {
IVL_LPM_CMP_NEE= 19, /* Case NE (!==) */
IVL_LPM_DIVIDE = 12,
IVL_LPM_FF = 3,
IVL_LPM_LATCH = 40,
IVL_LPM_MOD = 13,
IVL_LPM_MULT = 4,
IVL_LPM_MUX = 5,
@@ -356,12 +352,9 @@ typedef enum ivl_path_edge_e {
/* Processes are initial, always, or final blocks with a statement. This is
the type of the ivl_process_t object. */
typedef enum ivl_process_type_e ENUM_UNSIGNED_INT {
IVL_PR_INITIAL = 0,
IVL_PR_ALWAYS = 1,
IVL_PR_ALWAYS_COMB = 3,
IVL_PR_ALWAYS_FF = 4,
IVL_PR_ALWAYS_LATCH = 5,
IVL_PR_FINAL = 2
IVL_PR_INITIAL = 0,
IVL_PR_ALWAYS = 1,
IVL_PR_FINAL = 2
} ivl_process_type_t;
/* These are the sorts of reasons a scope may come to be. These types
@@ -435,14 +428,6 @@ typedef enum ivl_statement_type_e {
IVL_ST_WHILE = 23
} ivl_statement_type_t;
/* Case statements can be tagged as unique/unique0/priority. */
typedef enum ivl_case_quality_t {
IVL_CASE_QUALITY_BASIC = 0, /* no quality flags */
IVL_CASE_QUALITY_UNIQUE = 1,
IVL_CASE_QUALITY_UNIQUE0 = 2,
IVL_CASE_QUALITY_PRIORITY = 3
} ivl_case_quality_t;
/* SystemVerilog allows a system function to be called as a task. */
typedef enum ivl_sfunc_as_task_e {
IVL_SFUNC_AS_TASK_ERROR = 0,
@@ -525,10 +510,6 @@ extern ivl_island_t ivl_branch_island(ivl_branch_t obj);
* ivl_path_is_condit
* Is this a conditional structure? Needed for ifnone.
*
* ivl_path_is_parallel
* This returns true if the path is a parallel connection and
* false if the path is a full connection.
*
* ivl_path_source_posedge
* ivl_path_source_negedge
* These functions return true if the source is edge sensitive.
@@ -539,8 +520,6 @@ extern uint64_t ivl_path_delay(ivl_delaypath_t obj, ivl_path_edge_t pt);
extern ivl_nexus_t ivl_path_condit(ivl_delaypath_t obj);
extern int ivl_path_is_condit(ivl_delaypath_t obj);
extern int ivl_path_is_parallel(ivl_delaypath_t obj);
extern int ivl_path_source_posedge(ivl_delaypath_t obj);
extern int ivl_path_source_negedge(ivl_delaypath_t obj);
@@ -1266,10 +1245,8 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
* width of a general power is the XXXX of the widths of the
* inputs.
*
* Power may be signed. This indicates the type of the exponent. The
* base will always be treated as unsigned. The compiler must ensure
* the width of the base is equal to the width of the output to
* obtain the correct result when the base is really a signed value.
* Power may be signed. If so, the output should be sign extended
* to fill in its result.
*
* - Part Select (IVL_LPM_PART_VP and IVL_LPM_PART_PV)
* There are two part select devices, one that extracts a part from a
@@ -1332,13 +1309,8 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
* inputs and the Q. All the types must be exactly the same.
*
* - D-FlipFlop (IVL_LPM_FF)
* This device is an edge sensitive register. The ivl_lpm_q output and
* single ivl_lpm_data input are the same width, ivl_lpm_width. This
* device carries a vector like other LPM devices.
*
* - Latch (IVL_LPM_LATCH)
* This device is an asynchronous latch. The ivl_lpm_q output and
* single ivl_lpm_data input are the same width, ivl_lpm_width. This
* This data is an edge sensitive register. The ivl_lpm_q output and
* single ivl_lpm_data input are the same with, ivl_lpm_width. This
* device carries a vector like other LPM devices.
*
* - Memory port (IVL_LPM_RAM) (deprecated in favor of IVL_LPM_ARRAY)
@@ -1456,18 +1428,18 @@ extern unsigned ivl_lpm_negedge(ivl_lpm_t net);
extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net);
/* IVL_LPM_UFUNC */
extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
/* IVL_LPM_FF IVL_LPM_LATCH*/
/* IVL_LPM_FF */
extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
/* IVL_LPM_ADD IVL_LPM_CONCAT IVL_LPM_FF IVL_LPM_PART IVL_LPM_MULT
IVL_LPM_MUX IVL_LPM_POW IVL_LPM_SHIFTL IVL_LPM_SHIFTR IVL_LPM_SUB
IVL_LPM_UFUNC IVL_LPM_SUBSTITUTE IVL_LPM_LATCH */
IVL_LPM_UFUNC IVL_LPM_SUBSTITUTE */
extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_POW IVL_LPM_SUB IVL_LPM_CMP_EQ
IVL_LPM_CMP_EEQ IVL_LPM_CMP_EQX IVL_LPM_CMP_EQZ IVL_LPM_CMP_NEE */
extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART IVL_LPM_POW
IVL_LPM_SUB IVL_LPM_UFUNC IVL_LPM_CMP_EEQ IVL_LPM_CMP_EQX
IVL_LPM_CMP_EQZ IVL_LPM_CMP_NEE IVL_LPM_SUBSTITUTE IVL_LPM_LATCH */
IVL_LPM_CMP_EQZ IVL_LPM_CMP_NEE IVL_LPM_SUBSTITUTE */
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net);
extern ivl_drive_t ivl_lpm_drive0(ivl_lpm_t net);
extern ivl_drive_t ivl_lpm_drive1(ivl_lpm_t net);
@@ -1773,13 +1745,6 @@ extern unsigned ivl_parameter_lineno(ivl_parameter_t net);
* ivl_scope_lineno
* Returns the instantiation file and line for this scope.
*
* ivl_scope_func_type
* ivl_scope_func_signed
* ivl_scope_func_width
*
* If the scope is a function, these function can be used to get
* the type of the return value.
*
* ivl_scope_is_auto
* Is the task or function declared to be automatic?
*
@@ -1898,9 +1863,6 @@ extern const char* ivl_scope_tname(ivl_scope_t net);
extern int ivl_scope_time_precision(ivl_scope_t net);
extern int ivl_scope_time_units(ivl_scope_t net);
extern ivl_variable_type_t ivl_scope_func_type(ivl_scope_t net);
extern int ivl_scope_func_signed(ivl_scope_t net);
extern unsigned ivl_scope_func_width(ivl_scope_t net);
/* SIGNALS
* Signals are named things in the Verilog source, like wires and
@@ -2122,7 +2084,6 @@ extern unsigned ivl_stmt_lineno(ivl_statement_t net);
* handle disable statements.
*
* ivl_stmt_events
* ivl_stmt_needs_t0_trigger
* ivl_stmt_nevent
* Statements that have event arguments (TRIGGER and WAIT) make
* those event objects available through these methods.
@@ -2237,8 +2198,6 @@ extern ivl_scope_t ivl_stmt_call(ivl_statement_t net);
extern unsigned ivl_stmt_case_count(ivl_statement_t net);
/* IVL_ST_CASE,IVL_ST_CASER,IVL_ST_CASEX,IVL_ST_CASEZ */
extern ivl_expr_t ivl_stmt_case_expr(ivl_statement_t net, unsigned i);
/* IVL+ST_CASE,IVL_ST_CASER,IVL_ST_CASEX,IVL_ST_CASEZ */
extern ivl_case_quality_t ivl_stmt_case_quality(ivl_statement_t net);
/* IVL_ST_CASE,IVL_ST_CASER,IVL_ST_CASEX,IVL_ST_CASEZ */
extern ivl_statement_t ivl_stmt_case_stmt(ivl_statement_t net, unsigned i);
/* IVL_ST_CONDIT IVL_ST_CASE IVL_ST_REPEAT IVL_ST_WHILE */
@@ -2252,7 +2211,6 @@ extern ivl_expr_t ivl_stmt_delay_expr(ivl_statement_t net);
/* IVL_ST_DELAY */
extern uint64_t ivl_stmt_delay_val(ivl_statement_t net);
/* IVL_ST_WAIT IVL_ST_TRIGGER */
extern unsigned ivl_stmt_needs_t0_trigger(ivl_statement_t net);
extern unsigned ivl_stmt_nevent(ivl_statement_t net);
extern ivl_event_t ivl_stmt_events(ivl_statement_t net, unsigned idx);
/* IVL_ST_CONTRIB */
@@ -2361,7 +2319,7 @@ extern const char* ivl_type_prop_name(ivl_type_t net, int idx);
extern ivl_type_t ivl_type_prop_type(ivl_type_t net, int idx);
#if defined(__MINGW32__) || defined (__CYGWIN__)
#if defined(__MINGW32__) || defined (__CYGWIN32__)
# define DLLEXPORT __declspec(dllexport)
#else
# define DLLEXPORT
+3 -1
View File
@@ -1,7 +1,7 @@
#ifndef IVL_ivl_target_priv_H
#define IVL_ivl_target_priv_H
/*
* Copyright (c) 2008-2019 Stephen Williams (steve@icarus.com)
* Copyright (c) 2008-2014 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
@@ -51,6 +51,8 @@ struct ivl_design_s {
ivl_process_t threads_;
// Keep arrays of root scopes.
std::map<const NetScope*,ivl_scope_t> classes;
std::map<const NetScope*,ivl_scope_t> root_tasks;
std::vector<ivl_scope_t> packages;
std::vector<ivl_scope_t> roots;
+3 -5
View File
@@ -60,7 +60,7 @@ distclean: clean
rm -f Makefile config.log
cppcheck: $(O:.o=.c)
cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f $(INCLUDE_PATH) $^
cppcheck --enable=all -f $(INCLUDE_PATH) $^
Makefile: $(srcdir)/Makefile.in ../config.status
cd ..; ./config.status --file=ivlpp/$@
@@ -71,11 +71,9 @@ ivlpp@EXEEXT@: $O
lexor.c: $(srcdir)/lexor.lex
$(LEX) -t $< > $@
install: all installdirs installfiles
install: all installdirs $(libdir)/ivl$(suffix)/ivlpp@EXEEXT@
F = ivlpp@EXEEXT@
installfiles: $(F) | installdirs
$(libdir)/ivl$(suffix)/ivlpp@EXEEXT@: ivlpp@EXEEXT@
$(INSTALL_PROGRAM) ./ivlpp@EXEEXT@ "$(DESTDIR)$(libdir)/ivl$(suffix)/ivlpp@EXEEXT@"
installdirs: $(srcdir)/../mkinstalldirs
+1 -4
View File
@@ -1,7 +1,7 @@
#ifndef IVL_globals_H
#define IVL_globals_H
/*
* Copyright (c) 1999-2017 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2014 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
@@ -53,9 +53,6 @@ extern char dep_mode;
extern int verbose_flag;
extern int warn_redef;
extern int warn_redef_all;
/* This is the entry to the lexer. */
extern int yylex(void);
+87 -165
View File
@@ -1,7 +1,7 @@
%option prefix="yy"
%{
/*
* Copyright (c) 1999-2020 Stephen Williams ([email protected])
* Copyright (c) 1999-2015 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -148,49 +148,38 @@ static void ifdef_leave(void)
free(cur);
}
#define YY_INPUT(buf,result,max_size) do { \
if (istack->file) { \
size_t rc = fread(buf, 1, max_size, istack->file); \
result = (rc == 0) ? YY_NULL : rc; \
} else { \
/* We are expanding a macro. Handle the SV `` delimiter. \
If the delimiter terminates a defined macro usage, leave \
it in place, otherwise remove it now. */ \
if (!(yytext[0] == '`' && is_defined(yytext+1))) { \
while ((istack->str[0] == '`') && \
(istack->str[1] == '`')) { \
istack->str += 2; \
} \
} \
if (*istack->str == 0) { \
result = YY_NULL; \
} else { \
buf[0] = *istack->str++; \
result = 1; \
} \
} \
#define YY_INPUT(buf,result,max_size) do { \
if (istack->file) { \
size_t rc = fread(buf, 1, max_size, istack->file); \
result = (rc == 0) ? YY_NULL : rc; \
} else { \
if (*istack->str == 0) \
result = YY_NULL; \
else { \
buf[0] = *istack->str++; \
result = 1; \
} \
} \
} while (0)
static int comment_enter = 0;
static int pragma_enter = 0;
static int string_enter = 0;
static int prev_state = 0;
static int ma_parenthesis_level = 0;
%}
%option stack
%option nounput
%option noinput
%option noyy_top_state
%option noyywrap
%x PPINCLUDE
%x DEF_NAME
%x DEF_ESC
%x DEF_ARG
%x DEF_SEP
%x DEF_TXT
%x MN_ESC
%x MA_START
%x MA_ADD
%x CCOMMENT
@@ -199,11 +188,6 @@ static int ma_parenthesis_level = 0;
%x CSTRING
%x ERROR_LINE
%x IFDEF_NAME
%x IFNDEF_NAME
%x ELSIF_NAME
%x ELSIF_SUPR
%x IFDEF_FALSE
%s IFDEF_TRUE
%x IFDEF_SUPR
@@ -258,7 +242,15 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
if (macro_needs_args(yytext+1)) yy_push_state(MA_START); else do_expand(0);
}
/* Strings do not contain preprocessor directives or macro expansions.
/* `" overrides the usual lexical meaning of " and `\`" indicates
that the expansion should include the escape sequence \".
*/
`\" { fputc('"', yyout); }
`\\`\" { fprintf(yyout, "\\\""); }
/* Strings do not contain preprocessor directives, but can expand
* macros. If that happens, they get expanded in the context of the
* string.
*/
\" { string_enter = YY_START; BEGIN(CSTRING); ECHO; }
<CSTRING>\\\\ |
@@ -340,11 +332,6 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
<DEF_NAME>[a-zA-Z_][a-zA-Z0-9_$]*"("{W}? { BEGIN(DEF_ARG); def_start(); }
<DEF_NAME>[a-zA-Z_][a-zA-Z0-9_$]*{W}? { BEGIN(DEF_TXT); def_start(); }
<DEF_NAME>\\ { BEGIN(DEF_ESC); }
<DEF_ESC>[^ \t\b\f\n\r]+{W}"("{W}? { BEGIN(DEF_ARG); def_start(); }
<DEF_ESC>[^ \t\b\f\n\r]+{W} { BEGIN(DEF_TXT); def_start(); }
/* define arg: <name> = <text> */
<DEF_ARG>[a-zA-Z_][a-zA-Z0-9_$]*{W}*"="[^,\)]*{W}? { BEGIN(DEF_SEP); def_add_arg(); }
/* define arg: <name> */
@@ -359,7 +346,7 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
<DEF_ARG,DEF_SEP>(\n|"\r\n"|"\n\r"|\r){W}? { istack->lineno += 1; fputc('\n', yyout); }
<DEF_NAME,DEF_ESC,DEF_ARG,DEF_SEP>. {
<DEF_NAME,DEF_ARG,DEF_SEP>. {
emit_pathline(istack);
fprintf(stderr, "error: malformed `define directive.\n");
error_count += 1;
@@ -406,52 +393,57 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
* condition that stacks on top of the IFDEF_FALSE so that output is
* not accidentally turned on within nested ifdefs.
*/
`ifdef{W} {
`ifdef{W}[a-zA-Z_][a-zA-Z0-9_$]* {
char* name = strchr(yytext, '`'); assert(name);
name += 6;
name += strspn(name, " \t\b\f");
ifdef_enter();
yy_push_state(IFDEF_NAME);
if (is_defined(name))
yy_push_state(IFDEF_TRUE);
else
yy_push_state(IFDEF_FALSE);
}
`ifndef{W} {
`ifndef{W}[a-zA-Z_][a-zA-Z0-9_$]* {
char* name = strchr(yytext, '`'); assert(name);
name += 7;
name += strspn(name, " \t\b\f");
ifdef_enter();
yy_push_state(IFNDEF_NAME);
if (!is_defined(name))
yy_push_state(IFDEF_TRUE);
else
yy_push_state(IFDEF_FALSE);
}
<IFDEF_FALSE,IFDEF_SUPR>`ifdef{W} |
<IFDEF_FALSE,IFDEF_SUPR>`ifndef{W} { ifdef_enter(); yy_push_state(IFDEF_SUPR); }
<IFDEF_TRUE>`elsif{W} { prev_state = YYSTATE; BEGIN(ELSIF_SUPR); }
<IFDEF_FALSE>`elsif{W} { prev_state = YYSTATE; BEGIN(ELSIF_NAME); }
<IFDEF_SUPR>`elsif{W} { prev_state = YYSTATE; BEGIN(ELSIF_SUPR); }
<IFDEF_TRUE>`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* { BEGIN(IFDEF_SUPR); }
<IFDEF_FALSE>`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* {
char* name = strchr(yytext, '`'); assert(name);
name += 6;
name += strspn(name, " \t\b\f");
if (is_defined(name))
BEGIN(IFDEF_TRUE);
else
BEGIN(IFDEF_FALSE);
}
<IFDEF_SUPR>`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* { }
<IFDEF_TRUE>`else { BEGIN(IFDEF_SUPR); }
<IFDEF_FALSE>`else { BEGIN(IFDEF_TRUE); }
<IFDEF_SUPR>`else {}
<IFDEF_NAME>[a-zA-Z_][a-zA-Z0-9_$]* {
if (is_defined(yytext))
BEGIN(IFDEF_TRUE);
else
BEGIN(IFDEF_FALSE);
}
<IFNDEF_NAME>[a-zA-Z_][a-zA-Z0-9_$]* {
if (!is_defined(yytext))
BEGIN(IFDEF_TRUE);
else
BEGIN(IFDEF_FALSE);
}
<ELSIF_NAME>[a-zA-Z_][a-zA-Z0-9_$]* {
if (is_defined(yytext))
BEGIN(IFDEF_TRUE);
else
BEGIN(IFDEF_FALSE);
}
<ELSIF_SUPR>[a-zA-Z_][a-zA-Z0-9_$]* {
BEGIN(IFDEF_SUPR);
}
<IFDEF_FALSE,IFDEF_SUPR>"//"[^\r\n]* {}
<IFDEF_FALSE,IFDEF_SUPR>"/*" { comment_enter = YY_START; BEGIN(IFCCOMMENT); }
@@ -471,45 +463,25 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
<IFDEF_FALSE,IFDEF_TRUE,IFDEF_SUPR>`endif { ifdef_leave(); yy_pop_state(); }
<IFDEF_NAME>(\n|\r) |
<IFDEF_NAME>. |
`ifdef {
error_count += 1;
fprintf(stderr, "%s:%u: `ifdef without a macro name - ignored.\n",
istack->path, istack->lineno+1);
if (YY_START == IFDEF_NAME) {
ifdef_leave();
yy_pop_state();
unput(yytext[0]);
}
}
<IFNDEF_NAME>(\n|\r) |
<IFNDEF_NAME>. |
`ifndef {
error_count += 1;
fprintf(stderr, "%s:%u: `ifndef without a macro name - ignored.\n",
istack->path, istack->lineno+1);
if (YY_START == IFNDEF_NAME) {
ifdef_leave();
yy_pop_state();
unput(yytext[0]);
}
}
<ELSIF_NAME,ELSIF_SUPR>(\n|\r) |
<ELSIF_NAME,ELSIF_SUPR>. |
`elsif {
error_count += 1;
fprintf(stderr, "%s:%u: `elsif without a macro name - ignored.\n",
istack->path, istack->lineno+1);
if (YY_START != INITIAL) {
BEGIN(prev_state);
unput(yytext[0]);
}
}
<INITIAL>`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* {
`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* {
error_count += 1;
fprintf(stderr, "%s:%u: `elsif without a matching `ifdef - ignored.\n",
istack->path, istack->lineno+1);
@@ -542,53 +514,28 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
do_expand(0);
}
`\\ { yy_push_state(MN_ESC); }
<MN_ESC>[^ \t\b\f\n\r]+ {
yy_pop_state();
if (macro_needs_args(yytext))
yy_push_state(MA_START);
else
do_expand(0);
}
<MN_ESC>. {
yy_pop_state();
unput(yytext[0]);
emit_pathline(istack);
fprintf(stderr, "error: malformed macro name.\n");
error_count += 1;
}
/* Stringified version of macro expansion. This is an Icarus extension.
When expanding macro text, the SV usage of `` takes precedence. */
/* Stringified version of macro expansion. If the sequence `` is
* encountered inside a macro definition, we use the SystemVerilog
* handling of ignoring it so that identifiers can be constructed
* from arguments. If istack->file is NULL, we are reading text
* produced from a macro, so use SystemVerilog's handling;
* otherwise, use the special Icarus handling.
*/
``[a-zA-Z_][a-zA-Z0-9_$]* {
if (istack->file) {
assert(do_expand_stringify_flag == 0);
do_expand_stringify_flag = 1;
fputc('"', yyout);
if (macro_needs_args(yytext+2))
yy_push_state(MA_START);
else
do_expand(0);
} else {
REJECT;
}
if (istack->file == NULL)
fprintf(yyout, "%s", yytext+2);
else {
assert(do_expand_stringify_flag == 0);
do_expand_stringify_flag = 1;
fputc('"', yyout);
if (macro_needs_args(yytext+2))
yy_push_state(MA_START);
else
do_expand(0);
}
}
/* If we are expanding a macro, remove the SV `` delimiter, otherwise
* leave it to be handled by the normal rules.
*/
`` { if (istack->file) REJECT; }
/* If we are expanding a macro, handle the SV `" override. This avoids
* entering CSTRING state, thus allowing nested macro expansions.
*/
`\" { if (!istack->file) fputc('"', yyout); else REJECT; }
/* If we are expanding a macro, handle the SV `\`" escape sequence.
*/
`\\`\" { if (!istack->file) fputs("\\\"", yyout); else REJECT; }
`` { if (istack->file != NULL) ECHO; }
<MA_START>\( { BEGIN(MA_ADD); macro_start_args(); }
@@ -624,7 +571,7 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
<MA_ADD>{W} { macro_add_to_arg(1); }
<MA_ADD>[({] { macro_add_to_arg(0); ma_parenthesis_level++; }
<MA_ADD>"(" { macro_add_to_arg(0); ma_parenthesis_level++; }
<MA_ADD>"," {
if (ma_parenthesis_level > 0)
@@ -633,7 +580,7 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
macro_finish_arg();
}
<MA_ADD>[)}] {
<MA_ADD>")" {
if (ma_parenthesis_level > 0) {
macro_add_to_arg(0);
ma_parenthesis_level--;
@@ -850,13 +797,8 @@ static void def_add_arg(void)
/* This can happen because we are also processing "argv[0]", the
macro name, as a pseudo-argument. The lexor will match that
as name(, so chop off the ( here. If we have an escaped name,
we also need to strip off the white space that terminates the
name. */
if (yytext[length - 1] == '(') {
length--;
while (isspace((int)yytext[length - 1])) length--;
}
as name(, so chop off the ( here. */
if (yytext[length - 1] == '(') length--;
yytext[length] = 0;
@@ -912,25 +854,6 @@ void define_macro(const char* name, const char* value, int keyword, int argc)
{
int idx;
struct define_t* def;
struct define_t* prev;
/* Verilog has a very nasty system of macros jumping from
* file to file, resulting in a global macro scope. Here
* we optionally warn about any redefinitions.
*
* If istack is empty, we are processing a configuration
* or precompiled macro file, so don't want to check for
* redefinitions - when a precompiled macro file is used,
* it will contain copies of any predefined macros.
*/
if (warn_redef && istack) {
prev = def_lookup(name);
if (prev && (warn_redef_all || (strcmp(prev->value, value) != 0))) {
emit_pathline(istack);
fprintf(stderr, "warning: redefinition of macro %s from value '%s' to '%s'\n",
name, prev->value, value);
}
}
def = malloc(sizeof(struct define_t));
def->name = strdup(name);
@@ -1735,8 +1658,7 @@ static void do_include(void)
}
for (idx = start ; idx < include_cnt ; idx += 1) {
snprintf(path, sizeof(path), "%s/%s",
include_dir[idx], standby->path);
sprintf(path, "%s/%s", include_dir[idx], standby->path);
if ((standby->file = fopen(path, "r"))) {
standby->file_close = fclose;
@@ -2174,7 +2096,7 @@ void destroy_lexor(void)
{
# ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy();
# endif
# endif
+3 -19
View File
@@ -1,5 +1,5 @@
const char COPYRIGHT[] =
"Copyright (c) 1999-2020 Stephen Williams ([email protected])";
"Copyright (c) 1999-2011,2015 Stephen Williams ([email protected])";
/*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -98,10 +98,6 @@ int line_direct_flag = 0;
unsigned error_count = 0;
FILE *depend_file = NULL;
/* Should we warn about macro redefinitions? */
int warn_redef = 0;
int warn_redef_all = 0;
static int flist_read_flags(const char*path)
{
char line_buf[2048];
@@ -286,7 +282,7 @@ int main(int argc, char*argv[])
include_dir[0] = 0; /* 0 is reserved for the current files path. */
include_dir[1] = strdup(".");
while ((opt=getopt(argc, argv, "F:f:K:Lo:p:P:vVW:")) != EOF) switch (opt) {
while ((opt=getopt(argc, argv, "F:f:K:Lo:p:P:vV")) != EOF) switch (opt) {
case 'F':
flist_read_flags(optarg);
@@ -340,15 +336,6 @@ int main(int argc, char*argv[])
break;
}
case 'W':
if (strcmp(optarg, "redef-all") == 0) {
warn_redef_all = 1;
warn_redef = 1;
} else if (strcmp(optarg, "redef-chg") == 0) {
warn_redef = 1;
}
break;
case 'v':
fprintf(stderr, "Icarus Verilog Preprocessor version "
VERSION " (" VERSION_TAG ")\n\n");
@@ -379,10 +366,7 @@ int main(int argc, char*argv[])
" -p<fil> - Write precompiled defines to <fil>\n"
" -P<fil> - Read precompiled defines from <fil>\n"
" -v - Verbose\n"
" -V - Print version information and quit\n"
" -W<cat> - Enable extra ivlpp warning category:\n"
" o redef-all - all macro redefinitions\n"
" o redef-chg - macro definition changes\n",
" -V - Print version information and quit\n",
argv[0]);
return flag_errors;
}
+23 -64
View File
@@ -4,7 +4,7 @@
%{
/*
* Copyright (c) 1998-2020 Stephen Williams ([email protected])
* Copyright (c) 1998-2015 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -51,22 +51,6 @@
*/
extern YYLTYPE yylloc;
char* yytext_string_filter(const char*str, size_t str_len)
{
if (str == 0) return 0;
char*buf = new char[str_len+1];
for (size_t idx = 0 ; idx < str_len ; idx += 1) {
if (str[idx] == 0) {
VLerror(yylloc, "error: Found nil (\\000) in string literal, replacing with space (\\015) character.");
buf[idx] = ' ';
} else {
buf[idx] = str[idx];
}
}
buf[str_len] = 0;
return buf;
}
char* strdupnew(char const *str)
{
return str ? strcpy(new char [strlen(str)+1], str) : 0;
@@ -88,7 +72,6 @@ static const char* set_file_name(char*text)
void reset_lexor();
static void line_directive();
static void line_directive2();
static void reset_all();
verinum*make_unsized_binary(const char*txt);
verinum*make_undef_highz_dec(const char*txt);
@@ -204,11 +187,8 @@ TU [munpf]
"!=" { return K_NE; }
"===" { return K_CEQ; }
"!==" { return K_CNE; }
"==?" { return K_WEQ; }
"!=?" { return K_WNE; }
"||" { return K_LOR; }
"&&" { return K_LAND; }
"<->" { return K_LEQUIV; }
"&&&" { return K_TAND; }
"~|" { return K_NOR; }
"~^" { return K_NXOR; }
@@ -247,12 +227,12 @@ TU [munpf]
<CSTRING>\\\\ { yymore(); /* Catch \\, which is a \ escaping itself */ }
<CSTRING>\\\" { yymore(); /* Catch \", which is an escaped quote */ }
<CSTRING>\n { BEGIN(0);
yylval.text = yytext_string_filter(yytext, yyleng);
yylval.text = strdupnew(yytext);
VLerror(yylloc, "Missing close quote of string.");
yylloc.first_line += 1;
return STRING; }
<CSTRING>\" { BEGIN(0);
yylval.text = yytext_string_filter(yytext, yyleng);
yylval.text = strdupnew(yytext);
yylval.text[strlen(yytext)-1] = 0;
return STRING; }
<CSTRING>. { yymore(); }
@@ -330,6 +310,15 @@ TU [munpf]
BEGIN(UDPTABLE);
break;
/* Translate these to checks if we already have or are
* outside the declaration region. */
case K_timeunit:
if (have_timeunit_decl) rc = K_timeunit_check;
break;
case K_timeprecision:
if (have_timeprec_decl) rc = K_timeprecision_check;
break;
default:
yylval.text = 0;
break;
@@ -379,7 +368,7 @@ TU [munpf]
/* If this identifier names a previously declared type, then
return this as a TYPE_IDENTIFIER instead. */
if (rc == IDENTIFIER && gn_system_verilog()) {
if (data_type_t*type = pform_test_type_identifier(yylloc, yylval.text)) {
if (data_type_t*type = pform_test_type_identifier(yylval.text)) {
yylval.type_identifier.text = yylval.text;
yylval.type_identifier.type = type;
rc = TYPE_IDENTIFIER;
@@ -400,7 +389,7 @@ TU [munpf]
}
}
if (gn_system_verilog()) {
if (data_type_t*type = pform_test_type_identifier(yylloc, yylval.text)) {
if (data_type_t*type = pform_test_type_identifier(yylval.text)) {
yylval.type_identifier.text = yylval.text;
yylval.type_identifier.type = type;
return TYPE_IDENTIFIER;
@@ -439,12 +428,6 @@ TU [munpf]
if (strcmp(yytext,"$attribute") == 0)
return KK_attribute;
if (gn_system_verilog() && strcmp(yytext,"$unit") == 0) {
yylval.package = pform_units.back();
return PACKAGE_IDENTIFIER;
}
yylval.text = strdupnew(yytext);
return SYSTEM_IDENTIFIER; }
@@ -470,7 +453,7 @@ TU [munpf]
return BASED_NUMBER;
}
\'[01xzXZ] {
if (!gn_system_verilog()) {
if (generation_flag < GN_VER2005_SV) {
cerr << yylloc.text << ":" << yylloc.first_line << ": warning: "
<< "Using SystemVerilog 'N bit vector. Use at least "
<< "-g2005-sv to remove this warning." << endl;
@@ -496,7 +479,7 @@ TU [munpf]
/* This rule handles scaled time values for SystemVerilog. */
[0-9][0-9_]*(\.[0-9][0-9_]*)?{TU}?s {
if (gn_system_verilog()) {
if(generation_flag & (GN_VER2005_SV | GN_VER2009 | GN_VER2012)) {
yylval.text = strdupnew(yytext);
return TIME_LITERAL;
} else REJECT; }
@@ -583,7 +566,11 @@ TU [munpf]
"definition." << endl;
error_count += 1;
} else {
reset_all();
pform_set_default_nettype(NetNet::WIRE, yylloc.text,
yylloc.first_line);
in_celldefine = false;
uc_drive = UCD_NONE;
pform_set_timescale(def_ts_units, def_ts_prec, 0, 0);
} }
/* Notice and handle the `unconnected_drive directive. */
@@ -870,7 +857,7 @@ verinum*make_unsized_binary(const char*txt)
ptr += 1;
}
assert((tolower(*ptr) == 'b') || gn_system_verilog());
assert((tolower(*ptr) == 'b') || (generation_flag >= GN_VER2005_SV));
if (tolower(*ptr) == 'b') {
ptr += 1;
} else {
@@ -885,14 +872,6 @@ verinum*make_unsized_binary(const char*txt)
for (const char*idx = ptr ; *idx ; idx += 1)
if (*idx != '_') size += 1;
if (size == 0) {
VLerror(yylloc, "Numeric literal has no digits in it.");
verinum*out = new verinum();
out->has_sign(sign_flag);
out->is_single(single_flag);
return out;
}
if ((based_size > 0) && (size > based_size)) yywarn(yylloc,
"extra digits given for sized binary constant.");
@@ -1610,18 +1589,6 @@ static void line_directive2()
yylloc.first_line = lineno;
}
/*
* Reset all compiler directives. This will be called when a `resetall
* directive is encountered or when a new compilation unit is started.
*/
static void reset_all()
{
pform_set_default_nettype(NetNet::WIRE, yylloc.text, yylloc.first_line);
in_celldefine = false;
uc_drive = UCD_NONE;
pform_set_timescale(def_ts_units, def_ts_prec, 0, 0);
}
extern FILE*vl_input;
void reset_lexor()
{
@@ -1630,14 +1597,6 @@ void reset_lexor()
/* Announce the first file name. */
yylloc.text = set_file_name(strdupnew(vl_file.c_str()));
if (separate_compilation) {
reset_all();
if (!keyword_mask_stack.empty()) {
lexor_keyword_mask = keyword_mask_stack.back();
keyword_mask_stack.clear();
}
}
}
/*
@@ -1647,7 +1606,7 @@ void destroy_lexor()
{
# ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy();
# endif
# endif
+9 -36
View File
@@ -29,13 +29,11 @@ static char **string_pool = NULL;
static unsigned string_pool_count = 0;
#endif
static const unsigned DEFAULT_CELL_SIZE = 0x10000;
StringHeap::StringHeap()
{
cell_base_ = 0;
cell_ptr_ = 0;
cell_ptr_ = HEAPCELL;
cell_count_ = 0;
}
StringHeap::~StringHeap()
@@ -47,53 +45,28 @@ StringHeap::~StringHeap()
const char* StringHeap::add(const char*text)
{
unsigned len = strlen(text);
unsigned rem = cell_base_==0? 0 : (DEFAULT_CELL_SIZE - cell_ptr_);
assert((len+1) <= HEAPCELL);
// Special case: huge items get their own allocation.
if ( (len+1) >= DEFAULT_CELL_SIZE ) {
char*buf = strdup(text);
#ifdef CHECK_WITH_VALGRIND
string_pool_count += 1;
string_pool = (char**)realloc(string_pool,
string_pool_count*sizeof(char**));
string_pool[string_pool_count-1] = buf;
#endif
return buf;
}
// If the current cell that I'm working through cannot hold
// the current string, then set it aside and get another cell
// to put the string into.
unsigned rem = HEAPCELL - cell_ptr_;
if (rem < (len+1)) {
// release any unused memory. This assumes that a
// realloc shrink of the memory region will return the
// same pointer.
if (rem > 0) {
char*old = cell_base_;
cell_base_ = (char*)realloc(cell_base_, cell_ptr_);
assert(cell_base_ != 0);
assert(cell_base_ == old);
}
// start new cell
cell_base_ = (char*)malloc(DEFAULT_CELL_SIZE);
cell_ptr_ = 0;
rem = DEFAULT_CELL_SIZE;
assert(cell_base_ != 0);
cell_base_ = (char*)malloc(HEAPCELL);
#ifdef CHECK_WITH_VALGRIND
string_pool_count += 1;
string_pool = (char **) realloc(string_pool,
string_pool_count*sizeof(char **));
string_pool[string_pool_count-1] = cell_base_;
#endif
cell_ptr_ = 0;
cell_count_ += 1;
assert(cell_base_ != 0);
}
assert( (len+1) <= rem );
char*res = cell_base_ + cell_ptr_;
memcpy(res, text, len);
cell_ptr_ += len;
cell_base_[cell_ptr_++] = 0;
assert(cell_ptr_ <= DEFAULT_CELL_SIZE);
assert(cell_ptr_ <= HEAPCELL);
return res;
}
+4 -1
View File
@@ -46,7 +46,7 @@ class perm_string {
private:
friend class StringHeap;
friend class StringHeapLex;
explicit perm_string(const char*t) : text_(t) { };
perm_string(const char*t) : text_(t) { };
private:
const char*text_;
@@ -78,8 +78,11 @@ class StringHeap {
perm_string make(const char*);
private:
enum { HEAPCELL = 0x10000 };
char*cell_base_;
unsigned cell_ptr_;
unsigned cell_count_;
private: // not implemented
StringHeap(const StringHeap&);
+4 -8
View File
@@ -47,7 +47,7 @@ LDRELOCFLAGS = @LDRELOCFLAGS@
LDTARGETFLAGS = @LDTARGETFLAGS@
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ -DICARUS_VPI_CONST=const @PICFLAG@
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
A = a_close.o a_compare_handles.o a_configure.o a_fetch_argc.o \
@@ -76,9 +76,7 @@ distclean: clean
rm -f config.h stamp-config-h
cppcheck: $(O:.o=.c)
cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \
--suppressions-list=$(srcdir)/cppcheck.sup \
--relative-paths=$(srcdir) $(INCLUDE_PATH) $^
cppcheck --enable=all -f $(INCLUDE_PATH) $^
Makefile: $(srcdir)/Makefile.in
cd ..; ./config.status --file=libveriuser/$@
@@ -103,11 +101,9 @@ libveriuser.a: libveriuser.o
$(CC) $(CPPFLAGS) $(CFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o
mv $*.d dep
install:: all installdirs installfiles
install:: all installdirs $(libdir)/libveriuser$(suffix).a $(INSTALL32)
F = ./libveriuser.a
installfiles: $(F) | installdirs
$(libdir)/libveriuser$(suffix).a: ./libveriuser.a
$(INSTALL_DATA) ./libveriuser.a "$(DESTDIR)$(libdir)/libveriuser$(suffix).a"
installdirs: $(srcdir)/../mkinstalldirs
-187
View File
@@ -1,187 +0,0 @@
// These are the functions that the runtime exports.
// The ACC functions.
// acc_close()
unusedFunction:a_close.c:23
// acc_compare_handles()
unusedFunction:a_compare_handles.c:23
// acc_configure()
unusedFunction:a_configure.c:25
// acc_fetch_argc()
unusedFunction:a_fetch_argc.c:27
// acc_fetch_argv()
unusedFunction:a_fetch_argv.c:27
// acc_fetch_defname()
unusedFunction:a_fetch_fullname.c:37
// acc_fetch_direction()
unusedFunction:a_fetch_dir.c:26
// acc_fetch_fulltype()
unusedFunction:a_fetch_type.c:66
// acc_fetch_itfarg()
unusedFunction:a_fetch_tfarg.c:27
// acc_fetch_location()
unusedFunction:a_fetch_location.c:23
// acc_fetch_name()
unusedFunction:a_fetch_fullname.c:32
// acc_fetch_paramtype()
unusedFunction:a_fetch_type_str.c:47
// acc_fetch_paramval()
unusedFunction:a_fetch_param.c:25
// acc_fetch_range()
unusedFunction:a_fetch_range.c:26
// acc_fetch_size()
unusedFunction:a_fetch_type.c:24
// acc_fetch_tfarg()
unusedFunction:a_fetch_tfarg.c:56
// acc_fetch_tfarg_int()
unusedFunction:a_fetch_tfarg.c:91
// acc_fetch_timescale_info()
unusedFunction:a_fetch_time.c:24
// acc_fetch_type()
unusedFunction:a_fetch_type.c:29
// acc_fetch_type_str()
unusedFunction:a_fetch_type_str.c:24
// acc_fetch_value()
unusedFunction:a_fetch_value.c:115
// acc_handle_by_name()
unusedFunction:a_handle_by_name.c:29
// acc_handle_hiconn()
unusedFunction:a_handle_hiconn.c:26
// acc_handle_object()
unusedFunction:a_handle_object.c:26
// acc_handle_parent()
unusedFunction:a_handle_parent.c:24
// acc_handle_scope()
unusedFunction:a_handle_parent.c:34
// acc_handle_simulated_net()
unusedFunction:a_handle_simulated_net.c:26
// acc_handle_tfarg()
unusedFunction:a_handle_tfarg.c:26
// acc_handle_tfinst()
unusedFunction:a_handle_tfarg.c:53
// acc_initialize()
unusedFunction:a_initialize.c:24
// acc_next_bit()
unusedFunction:a_next_bit.c:26
// acc_next_port()
unusedFunction:a_next_port.c:26
// acc_next_scope()
unusedFunction:a_next.c:86
// acc_next_topmod()
unusedFunction:a_next_topmod.c:30
// acc_product_version()
unusedFunction:a_product_version.c:23
// acc_set_scope()
unusedFunction:a_handle_object.c:40
// acc_set_value()
unusedFunction:a_set_value.c:27
// acc_vcl_add()
unusedFunction:a_vcl.c:157
// acc_vcl_delete()
unusedFunction:a_vcl.c:196
// acc_version()
unusedFunction:a_version.c:23
// These are the TF routines.
// io_printf()
unusedFunction:io_print.c:26
// mc_scan_plusargs()
unusedFunction:mc_scan_plusargs.c:27
// tf_asynchoff()
unusedFunction:asynch.c:34
// tf_asynchon()
unusedFunction:asynch.c:28
// tf_dofinish()
unusedFunction:finish.c:26
// tf_dostop()
unusedFunction:finish.c:32
// tf_error()
unusedFunction:io_print.c:45
// tf_exprinfo()
unusedFunction:exprinfo.c:26
// tf_getcstringp()
unusedFunction:getcstringp.c:26
// tf_getlongp()
unusedFunction:getlongp.c:29
// tf_getlongtime()
unusedFunction:getsimtime.c:112
// tf_getp()
unusedFunction:getp.c:73
// tf_getrealp()
unusedFunction:getp.c:120
// tf_gettime()
unusedFunction:getsimtime.c:77
// tf_getworkarea()
unusedFunction:workarea.c:62
// tf_igettimeprecision()
unusedFunction:getsimtime.c:198
// tf_igettimeunit()
unusedFunction:getsimtime.c:228
// tf_long_to_real()
unusedFunction:math.c:47
// tf_message()
unusedFunction:io_print.c:56
// tf_mipname()
unusedFunction:spname.c:47
// tf_multiply_long()
unusedFunction:math.c:27
// tf_nodeinfo()
unusedFunction:nodeinfo.c:27
// tf_nump()
unusedFunction:nump.c:42
// tf_putlongp()
unusedFunction:putlongp.c:28
// tf_putp()
unusedFunction:putp.c:88
// tf_putrealp()
unusedFunction:putp.c:137
// tf_real_to_long()
unusedFunction:math.c:40
// tf_rosynchronize()
unusedFunction:veriusertfs.c:391
// tf_scale_longdelay()
unusedFunction:getsimtime.c:136
// tf_scale_realdelay()
unusedFunction:getsimtime.c:161
// tf_setdelay()
unusedFunction:delay.c:75
// tf_setrealdelay()
unusedFunction:veriusertfs.c:426
// tf_setworkarea()
unusedFunction:workarea.c:36
// tf_spname()
unusedFunction:spname.c:25
// tf_strgetp()
unusedFunction:getp.c:177
// tf_strgettime()
unusedFunction:getsimtime.c:85
// tf_synchronize()
unusedFunction:veriusertfs.c:364
// tf_typep()
unusedFunction:typep.c:24
// tf_unscale_longdelay()
unusedFunction:getsimtime.c:144
// tf_unscale_realdelay()
unusedFunction:getsimtime.c:171
// tf_warning()
unusedFunction:io_print.c:34
// Non-standard TF routines the Icarus provides.
// tf_getlongsimtime()
unusedFunction:getsimtime.c:126
// veriusertfs_register_table()
unusedFunction:veriusertfs.c:76
+1 -1
View File
@@ -31,6 +31,6 @@ extern char* __acc_newstring(const char*txt);
/*
* Trace file for logging ACC and TF calls.
*/
extern FILE* pli_trace;
FILE* pli_trace;
#endif /* IVL_priv_H */
+6 -33
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2018 Michael Ruff (mruff at chiaro.com)
* Copyright (c) 2002-2014 Michael Ruff (mruff at chiaro.com)
* Michael Runyan (mrunyan at chiaro.com)
*
* This source code is free software; you can redistribute it
@@ -42,9 +42,8 @@ typedef struct t_pli_data {
int paramvc; /* parameter number for misctf */
} s_pli_data, *p_pli_data;
static PLI_INT32 compiletf(ICARUS_VPI_CONST PLI_BYTE8 *);
static PLI_INT32 calltf(ICARUS_VPI_CONST PLI_BYTE8 *);
static PLI_INT32 sizetf(ICARUS_VPI_CONST PLI_BYTE8 *);
static PLI_INT32 compiletf(char *);
static PLI_INT32 calltf(char *);
static PLI_INT32 callback(p_cb_data);
/*
@@ -151,7 +150,7 @@ void veriusertfs_register_table(p_tfcell vtable)
tf_data.tfname = tf->tfname;
tf_data.compiletf = compiletf;
tf_data.calltf = calltf;
tf_data.sizetf = sizetf;
tf_data.sizetf = (PLI_INT32 (*)(PLI_BYTE8 *))tf->sizetf;
tf_data.user_data = (char *)data;
if (pli_trace) {
@@ -181,7 +180,7 @@ void veriusertfs_register_table(p_tfcell vtable)
* This function calls the veriusertfs checktf and sets up all the
* callbacks misctf requires.
*/
static PLI_INT32 compiletf(ICARUS_VPI_CONST PLI_BYTE8*data)
static PLI_INT32 compiletf(char *data)
{
p_pli_data pli;
p_tfcell tf;
@@ -261,7 +260,7 @@ static PLI_INT32 compiletf(ICARUS_VPI_CONST PLI_BYTE8*data)
/*
* This function is the wrapper for the veriusertfs calltf routine.
*/
static PLI_INT32 calltf(ICARUS_VPI_CONST PLI_BYTE8*data)
static PLI_INT32 calltf(char *data)
{
int rc = 0;
p_pli_data pli;
@@ -284,32 +283,6 @@ static PLI_INT32 calltf(ICARUS_VPI_CONST PLI_BYTE8*data)
return rc;
}
/*
* This function is the wrapper for the veriusertfs sizetf routine.
*/
static PLI_INT32 sizetf(ICARUS_VPI_CONST PLI_BYTE8*data)
{
int rc = 32;
p_pli_data pli;
p_tfcell tf;
/* cast back from opaque */
pli = (p_pli_data)data;
tf = pli->tf;
/* execute sizetf */
if (tf->sizetf) {
if (pli_trace) {
fprintf(pli_trace, "Call %s->sizetf(%d, %d)\n",
tf->tfname, tf->data, reason_sizetf);
}
rc = tf->sizetf(tf->data, reason_sizetf);
}
return rc;
}
/*
* This function is the wrapper for all the misctf callbacks
*/
+5 -30
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -102,17 +102,6 @@ bool Nexus::drivers_constant() const
break;
}
const NetSubstitute*ps = dynamic_cast<const NetSubstitute*>(cur->get_obj());
if (ps) {
if (ps->pin(1).nexus()->drivers_constant() &&
ps->pin(2).nexus()->drivers_constant() ) {
constant_drivers += 1;
continue;
}
driven_ = VAR;
return false;
}
if (! dynamic_cast<const NetConst*>(cur->get_obj())) {
driven_ = VAR;
return false;
@@ -173,13 +162,13 @@ verinum::V Nexus::driven_value() const
if ((sig->type() == NetNet::SUPPLY0) ||
(sig->type() == NetNet::TRI0)) {
// Multiple drivers are not currently supported.
ivl_assert(*sig, val == verinum::Vz);
ivl_assert(*obj, val == verinum::Vz);
val = verinum::V0;
}
if ((sig->type() == NetNet::SUPPLY1) ||
(sig->type() == NetNet::TRI1)) {
// Multiple drivers are not currently supported.
ivl_assert(*sig, val == verinum::Vz);
ivl_assert(*obj, val == verinum::Vz);
val = verinum::V1;
}
}
@@ -210,12 +199,10 @@ verinum Nexus::driven_vector() const
const Link*cur = list_;
verinum val;
verinum pval;
unsigned width = 0;
for (cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
const NetSubstitute*ps;
const NetConst*obj;
const NetNet*sig;
if ((obj = dynamic_cast<const NetConst*>(cur->get_obj()))) {
@@ -225,18 +212,6 @@ verinum Nexus::driven_vector() const
val = obj->value();
width = val.len();
} else if ((ps = dynamic_cast<const NetSubstitute*>(cur->get_obj()))) {
if (cur->get_pin() != 0)
continue;
// Multiple drivers are not currently supported.
ivl_assert(*ps, val.len() == 0);
val = ps->pin(1).nexus()->driven_vector();
pval = ps->pin(2).nexus()->driven_vector();
for (unsigned idx = 0; idx < pval.len(); idx += 1)
val.set(ps->base() + idx, pval.get(idx));
width = val.len();
} else if ((sig = dynamic_cast<const NetNet*>(cur->get_obj()))) {
width = sig->vector_width();
@@ -247,13 +222,13 @@ verinum Nexus::driven_vector() const
if ((sig->type() == NetNet::SUPPLY0) ||
(sig->type() == NetNet::TRI0)) {
// Multiple drivers are not currently supported.
ivl_assert(*sig, val.len() == 0);
ivl_assert(*obj, val.len() == 0);
val = verinum(verinum::V0, width);
}
if ((sig->type() == NetNet::SUPPLY1) ||
(sig->type() == NetNet::TRI1)) {
// Multiple drivers are not currently supported.
ivl_assert(*sig, val.len() == 0);
ivl_assert(*obj, val.len() == 0);
val = verinum(verinum::V1, width);
}
}
+33 -9
View File
@@ -54,13 +54,11 @@ extern FILE *depend_file;
* Use the type name as a key, and search the module library for a
* file name that has that key.
*/
bool load_module(const char*type, int&parser_errors)
bool load_module(const char*type)
{
char path[4096];
char*ltype = strdup(type);
parser_errors = 0;
for (char*tmp = ltype ; *tmp ; tmp += 1)
*tmp = tolower(*tmp);
@@ -73,8 +71,7 @@ bool load_module(const char*type, int&parser_errors)
if (cur == lcur->name_map.end())
continue;
snprintf(path, sizeof(path), "%s%c%s",
lcur->dir, dir_character, (*cur).second);
sprintf(path, "%s%c%s", lcur->dir, dir_character, (*cur).second);
if(depend_file) {
if (depfile_mode == 'p') {
@@ -85,17 +82,44 @@ bool load_module(const char*type, int&parser_errors)
fflush(depend_file);
}
if (verbose_flag)
cerr << "Loading library file " << path << "." << endl;
if (ivlpp_string) {
char*cmdline = (char*)malloc(strlen(ivlpp_string) +
strlen(path) + 4);
strcpy(cmdline, ivlpp_string);
strcat(cmdline, " \"");
strcat(cmdline, path);
strcat(cmdline, "\"");
parser_errors = pform_parse(path);
if (verbose_flag)
cerr << "Executing: " << cmdline << endl<< flush;
FILE*file = popen(cmdline, "r");
if (verbose_flag)
cerr << "...parsing output from preprocessor..." << endl << flush;
pform_parse(path, file);
pclose(file);
free(cmdline);
} else {
if (verbose_flag)
cerr << "Loading library file "
<< path << "." << endl;
FILE*file = fopen(path, "r");
assert(file);
pform_parse(path, file);
fclose(file);
}
if (verbose_flag)
cerr << "... Load module complete." << endl << flush;
return parser_errors == 0;
return true;
}
return false;
}
+88
View File
@@ -0,0 +1,88 @@
This file describes the procedure to build and install Icarus Verilog
on Mac OS X. I assume that you have experience with Unix and
Terminal.app and a basic knowledge of how to download, compile and
install software from source form.
Yasuhisa Kato wrote another set of instructions that has also been
known to work: <http://adwis.com/verilog/index.html>. You may try
those instructions instead of these, although they are essentially
quite similar.
1) Obtain and install a libdl compatibility library.
If you don't already have /usr/local/lib/libdl.{a,dylib} and
/usr/local/include/dlfcn.h, you can obtain the source for a
compatibility layer from at least one of two places:
http://download.sourceforge.net/fink/dlcompat-20010831.tar.gz
http://www.omnigroup.com/~bungi/dlcompat-20010831.tar.gz
Unpack this tar file and read the README and Makefile. Install the
library according to the instructions. Installation in /usr/local
is strongly recommended since otherwise autoconf very likely won't
be able to find it.
2) Make sure you have a copy of the 'gperf' tool. This does not come
with the Mac OS X 10.1 developer tools, so you probably don't. You
can check with:
% which gperf
If not found, grab a gperf source package and install it. See "GPERF
FOR MACOSX" below.
Snapshots of Icarus Verilog source now come with the
lexor_keyword.cc file pre-made, so if you have trouble with gperf,
then just make sure the distributed lexor_keyword.cc is newer than
lexor_keyword.gperf, and use that.
3) If working with source from git, you must run autoconf in the top
directory. This is simplified by the 'autoconf.sh' script at the
top of the source tree:
sh ./autoconf.sh
This will also run the gperf command, so make sure you've completed
step #2 first.
4) Configure, build and install the Icarus Verilog sources as normal.
The only change you need to make here is to use a configure command like:
% CC="cc -no-cpp-precomp" ./configure
This assumes you are using 'sh', 'zsh', or 'bash'. If you are using
'csh' or 'tcsh', then you'll want something like:
% setenv CC "cc -no-cpp-precomp"
% ./configure
You can, of course, add other configure options.
6) NOTE: 'make check' will not work until after 'make install' has been run
since dynamically loaded code is searched for in the install location
rather than the build location. The dlopen emulation library doesn't
support a search path option.
If you are worried about overwriting a working installation with a new,
potentially broken one, you can always configure using --prefix="/some/path",
and install there to make sure everything is working and then re-configure
with the real path you want to install at, make clean, and make install.
5) Done!
GPERF FOR MACOSX
Get version 2.7.2 of gperf from here:
<ftp://ftp.gnu.org/gnu/gperf/gperf-2.7.2.tar.gz>
Get a MacosX patch from here:
http://www.eternal.nest.or.jp/~shiro/binaries/gperf-2.7.2-macosx-patch.gz
Apply the patch to the gperf-2.7.2 source that you previously
downloaded, then follow the remaining gperf installation
instructions.
+38 -138
View File
@@ -1,5 +1,5 @@
const char COPYRIGHT[] =
"Copyright (c) 1998-2020 Stephen Williams ([email protected])";
"Copyright (c) 1998-2015 Stephen Williams ([email protected])";
/*
* This source code is free software; you can redistribute it
@@ -68,7 +68,7 @@ extern "C" int optind;
extern "C" const char*optarg;
#endif
#if defined(__CYGWIN__) && !defined(HAVE_GETOPT_H)
#if defined(__CYGWIN32__) && !defined(HAVE_GETOPT_H)
extern "C" int getopt(int argc, char*argv[], const char*fmt);
extern "C" int optind;
extern "C" const char*optarg;
@@ -104,12 +104,10 @@ generation_t generation_flag = GN_DEFAULT;
bool gn_icarus_misc_flag = true;
bool gn_cadence_types_flag = true;
bool gn_specify_blocks_flag = true;
bool gn_supported_assertions_flag = true;
bool gn_unsupported_assertions_flag = true;
bool gn_assertions_flag = true;
bool gn_io_range_error_flag = true;
bool gn_strict_ca_eval_flag = false;
bool gn_strict_expr_width_flag = false;
bool gn_shared_loop_index_flag = true;
bool gn_verilog_ams_flag = false;
/*
@@ -136,14 +134,11 @@ void add_vpi_module(const char*name)
vpi_module_list = tmp;
}
flags["VPI_MODULE_LIST"] = vpi_module_list;
load_vpi_module(name);
}
map<perm_string,unsigned> missing_modules;
map<perm_string,bool> library_file_map;
vector<perm_string> source_files;
list<const char*> library_suff;
list<perm_string> roots;
@@ -166,12 +161,6 @@ bool warn_ob_select = false;
bool warn_sens_entire_vec = false;
bool warn_sens_entire_arr = false;
bool warn_anachronisms = false;
bool warn_floating_nets = false;
/*
* Ignore errors about missing modules
*/
bool ignore_missing_modules = false;
/*
* Debug message class flags.
@@ -183,11 +172,6 @@ bool debug_emit = false;
bool debug_synth2 = false;
bool debug_optimizer = false;
/*
* Compilation control flags.
*/
bool separate_compilation = false;
/*
* Optimization control flags.
*/
@@ -241,7 +225,6 @@ const bool CASE_SENSITIVE = true;
bool synthesis = false;
extern void cprop(Design*des);
extern void exposenodes(Design*des);
extern void synth(Design*des);
extern void synth2(Design*des);
extern void syn_rules(Design*des);
@@ -252,11 +235,10 @@ static struct net_func_map {
const char*name;
void (*func)(Design*);
} func_table[] = {
{ "cprop", &cprop },
{ "exposenodes", &exposenodes },
{ "nodangle", &nodangle },
{ "synth", &synth },
{ "synth2", &synth2 },
{ "cprop", &cprop },
{ "nodangle",&nodangle },
{ "synth", &synth },
{ "synth2", &synth2 },
{ "syn-rules", &syn_rules },
{ 0, 0 }
};
@@ -333,16 +315,10 @@ static void process_generation_flag(const char*gen)
gn_specify_blocks_flag = false;
} else if (strcmp(gen,"assertions") == 0) {
gn_supported_assertions_flag = true;
gn_unsupported_assertions_flag = true;
} else if (strcmp(gen,"supported-assertions") == 0) {
gn_supported_assertions_flag = true;
gn_unsupported_assertions_flag = false;
gn_assertions_flag = true;
} else if (strcmp(gen,"no-assertions") == 0) {
gn_supported_assertions_flag = false;
gn_unsupported_assertions_flag = false;
gn_assertions_flag = false;
} else if (strcmp(gen,"verilog-ams") == 0) {
gn_verilog_ams_flag = true;
@@ -368,12 +344,6 @@ static void process_generation_flag(const char*gen)
} else if (strcmp(gen,"no-strict-expr-width") == 0) {
gn_strict_expr_width_flag = false;
} else if (strcmp(gen,"shared-loop-index") == 0) {
gn_shared_loop_index_flag = true;
} else if (strcmp(gen,"no-shared-loop-index") == 0) {
gn_shared_loop_index_flag = false;
} else {
}
}
@@ -590,15 +560,11 @@ static bool set_default_timescale(const char*ts_string)
*
* warnings:<string>
* Warning flag letters.
*
* ignore_missing_modules:<bool>
* true to ignore errors about missing modules
*/
bool had_timescale = false;
static void read_iconfig_file(const char*ipath)
{
char buf[8*1024];
vector<pair<char*,bool> > to_build_library_index;
FILE*ifile = fopen(ipath, "r");
if (ifile == 0) {
@@ -607,14 +573,6 @@ static void read_iconfig_file(const char*ipath)
}
while (fgets(buf, sizeof buf, ifile) != 0) {
assert(strlen(buf) < sizeof buf);
if ((strlen(buf) == ((sizeof buf) - 1))
&& buf[sizeof buf -2] != '\n') {
cerr << "WARNING: Line buffer overflow reading iconfig file: "
<< ipath
<< "." << endl;
assert(0);
}
if (buf[0] == '#')
continue;
char*cp = strchr(buf, ':');
@@ -718,9 +676,6 @@ static void read_iconfig_file(const char*ipath)
} else if (strcmp(buf,"warnings") == 0) {
/* Scan the warnings enable string for warning flags. */
for ( ; *cp ; cp += 1) switch (*cp) {
case 'f':
warn_floating_nets = true;
break;
case 'i':
warn_implicit = true;
break;
@@ -752,15 +707,11 @@ static void read_iconfig_file(const char*ipath)
break;
}
} else if (strcmp(buf, "ignore_missing_modules") == 0) {
if (strcmp(cp, "true") == 0)
ignore_missing_modules = true;
} else if (strcmp(buf, "-y") == 0) {
to_build_library_index.push_back(make_pair(strdup(cp), CASE_SENSITIVE));
build_library_index(cp, CASE_SENSITIVE);
} else if (strcmp(buf, "-yl") == 0) {
to_build_library_index.push_back(make_pair(strdup(cp), false));
build_library_index(cp, false);
} else if (strcmp(buf, "-Y") == 0) {
library_suff.push_back(strdup(cp));
@@ -799,54 +750,6 @@ static void read_iconfig_file(const char*ipath)
}
}
fclose(ifile);
for (vector<pair<char *, bool> >::iterator it = to_build_library_index.begin() ;
it != to_build_library_index.end() ; ++ it ) {
build_library_index(it->first, it->second);
free(it->first);
}
}
/*
* This function reads a list of source file names. Each name starts
* with the first non-space character, and ends with the last non-space
* character. Spaces in the middle are OK.
*/
static void read_sources_file(const char*path)
{
char line_buf[2048];
FILE*fd = fopen(path, "r");
if (fd == 0) {
cerr << "ERROR: Unable to read source file list: " << path << endl;
return;
}
while (fgets(line_buf, sizeof line_buf, fd) != 0) {
// assertion test that we are not overflowing the line
// buffer. Really should make this more robust, but
// better to assert then go weird.
assert(strlen(line_buf) < sizeof line_buf);
if ((strlen(line_buf) == ((sizeof line_buf) - 1))
&& line_buf[sizeof line_buf -2] != '\n') {
cerr << "WARNING: Line buffer overflow reading sources file: "
<< path
<< "." << endl;
assert(0);
}
char*cp = line_buf + strspn(line_buf, " \t\r\b\f");
char*tail = cp + strlen(cp);
while (tail > cp) {
if (! isspace((int)tail[-1]))
break;
tail -= 1;
tail[0] = 0;
}
if (cp < tail)
source_files.push_back(filename_strings.make(cp));
}
fclose(fd);
}
extern Design* elaborate(list <perm_string> root);
@@ -926,18 +829,20 @@ int main(int argc, char*argv[])
}
library_suff.push_back(strdup(".v"));
// Start the module list with the base system module.
add_vpi_module("system");
add_vpi_module("vhdl_sys");
flags["-o"] = strdup("a.out");
min_typ_max_flag = TYP;
min_typ_max_warn = 10;
while ((opt = getopt(argc, argv, "C:F:f:hN:P:p:Vv")) != EOF) switch (opt) {
while ((opt = getopt(argc, argv, "C:f:hN:P:p:Vv")) != EOF) switch (opt) {
case 'C':
read_iconfig_file(optarg);
break;
case 'F':
read_sources_file(optarg);
break;
case 'f':
parm_to_flagmap(optarg);
break;
@@ -990,7 +895,6 @@ int main(int argc, char*argv[])
"usage: ivl <options> <file>\n"
"options:\n"
"\t-C <name> Config file from driver.\n"
"\t-F <file> List of source files from driver.\n"
"\t-h Print usage information, and exit.\n"
"\t-N <file> Dump the elaborated netlist to <file>.\n"
"\t-P <file> Write the parsed input to <file>.\n"
@@ -1006,19 +910,11 @@ int main(int argc, char*argv[])
return 0;
}
int arg = optind;
while (arg < argc) {
perm_string path = filename_strings.make(argv[arg++]);
source_files.push_back(path);
}
if (source_files.empty()) {
if (optind == argc) {
cerr << "No input files." << endl;
return 1;
}
separate_compilation = source_files.size() > 1;
if( depfile_name ) {
depend_file = fopen(depfile_name, "a");
if(! depend_file) {
@@ -1030,22 +926,16 @@ int main(int argc, char*argv[])
switch (generation_flag) {
case GN_VER2012:
lexor_keyword_mask |= GN_KEYWORDS_1800_2012;
// fallthrough
case GN_VER2009:
lexor_keyword_mask |= GN_KEYWORDS_1800_2009;
// fallthrough
case GN_VER2005_SV:
lexor_keyword_mask |= GN_KEYWORDS_1800_2005;
// fallthrough
case GN_VER2005:
lexor_keyword_mask |= GN_KEYWORDS_1364_2005;
// fallthrough
case GN_VER2001:
lexor_keyword_mask |= GN_KEYWORDS_1364_2001_CONFIG;
// fallthrough
case GN_VER2001_NOCONFIG:
lexor_keyword_mask |= GN_KEYWORDS_1364_2001;
// fallthrough
case GN_VER1995:
lexor_keyword_mask |= GN_KEYWORDS_1364_1995;
}
@@ -1119,10 +1009,8 @@ int main(int argc, char*argv[])
if (flag_tmp) disable_concatz_generation = strcmp(flag_tmp,"true")==0;
/* Parse the input. Make the pform. */
int rc = 0;
for (unsigned idx = 0; idx < source_files.size(); idx += 1) {
rc += pform_parse(source_files[idx]);
}
pform_set_timescale(def_ts_units, def_ts_prec, 0, 0);
int rc = pform_parse(argv[optind]);
if (pf_path) {
ofstream out (pf_path);
@@ -1136,16 +1024,22 @@ int main(int argc, char*argv[])
; cur != disciplines.end() ; ++ cur ) {
pform_dump(out, (*cur).second);
}
out << "PFORM DUMP COMPILATION UNITS:" << endl;
for (vector<PPackage*>::iterator pac = pform_units.begin()
; pac != pform_units.end() ; ++ pac) {
pform_dump(out, *pac);
out << "PFORM DUMP $ROOT TASKS/FUNCTIONS:" << endl;
for (map<perm_string,PTaskFunc*>::iterator cur = pform_tasks.begin()
; cur != pform_tasks.end() ; ++ cur) {
pform_dump(out, cur->second);
}
out << "PFORM DUMP $ROOT CLASSES:" << endl;
for (map<perm_string,PClass*>::iterator cur = pform_classes.begin()
; cur != pform_classes.end() ; ++ cur) {
pform_dump(out, cur->second);
}
out << "PFORM DUMP PACKAGES:" << endl;
for (map<perm_string,PPackage*>::iterator pac = pform_packages.begin()
; pac != pform_packages.end() ; ++ pac) {
pform_dump(out, pac->second);
}
out << "PFORM DUMP MODULES:" << endl;
for (map<perm_string,Module*>::iterator mod = pform_modules.begin()
; mod != pform_modules.end() ; ++ mod ) {
@@ -1202,7 +1096,7 @@ int main(int argc, char*argv[])
if (roots.empty()) {
cerr << "No top level modules, and no -s option." << endl;
return ignore_missing_modules ? 0 : 1;
return 1;
}
@@ -1217,7 +1111,7 @@ int main(int argc, char*argv[])
/* Decide if we are going to allow system functions to be called
* as tasks. */
if (gn_system_verilog()) {
if (generation_flag >= GN_VER2005_SV) {
def_sfunc_as_task = IVL_SFUNC_AS_TASK_WARNING;
}
@@ -1263,6 +1157,12 @@ int main(int argc, char*argv[])
(*idx).second = 0;
}
for(map<perm_string,data_type_t*>::iterator it = pform_typedefs.begin()
; it != pform_typedefs.end() ; ++it) {
delete (*it).second;
(*it).second = 0;
}
if (verbose_flag) {
if (times_flag) {
times(cycles+2);
-27
View File
@@ -1,27 +0,0 @@
These are instructions for building Icarus Verilog binaries for
Windows using mingw cross compiler tools on Linux.
To start with, you need the mingw64-cross-* packages for your linux
distribution, which gives you the x86_64-w64-mingw32-* commands
installed on your system. Installing the cross environment is outside
the scope of this writeup.
First, configure with this command:
$ ./configure --host=x86_64-w64-mingw32
This generates the Makefiles needed to cross compile everything with
the mingw32 compiler. The configure script will generate the command
name paths, so long as commands line x86_64-w64-mingw32-gcc
et. al. are in your path.
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
configure script should have gotten all that right.
+1 -5
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2011 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
@@ -42,10 +42,7 @@ unsigned count_lval_width(const NetAssign_*idx)
NetAssign_::NetAssign_(NetAssign_*n)
: nest_(n), sig_(0), word_(0), base_(0), sel_type_(IVL_SEL_OTHER)
{
lwid_ = 0;
more = 0;
signed_ = false;
turn_sig_to_wire_on_release_ = false;
}
NetAssign_::NetAssign_(NetNet*s)
@@ -54,7 +51,6 @@ NetAssign_::NetAssign_(NetNet*s)
lwid_ = sig_->vector_width();
sig_->incr_lref();
more = 0;
signed_ = false;
turn_sig_to_wire_on_release_ = false;
}
+88 -138
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2019 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2013 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
@@ -101,11 +101,11 @@ uint64_t Design::scale_to_precision(uint64_t val,
return val;
}
NetScope* Design::make_root_scope(perm_string root, NetScope*unit_scope,
bool program_block, bool is_interface)
NetScope* Design::make_root_scope(perm_string root, bool program_block,
bool is_interface)
{
NetScope *root_scope_;
root_scope_ = new NetScope(0, hname_t(root), NetScope::MODULE, unit_scope,
root_scope_ = new NetScope(0, hname_t(root), NetScope::MODULE,
false, program_block, is_interface);
/* This relies on the fact that the basename return value is
permallocated. */
@@ -125,18 +125,31 @@ list<NetScope*> Design::find_root_scopes() const
return root_scopes_;
}
NetScope* Design::make_package_scope(perm_string name, NetScope*unit_scope,
bool is_unit)
NetScope* Design::make_package_scope(perm_string name)
{
NetScope*scope;
scope = new NetScope(0, hname_t(name), NetScope::PACKAGE, unit_scope,
false, false, false, is_unit);
scope = new NetScope(0, hname_t(name), NetScope::PACKAGE, false, false);
scope->set_module_name(scope->basename());
packages_[name] = scope;
return scope;
}
void Design::add_class(netclass_t*cl, PClass*pclass)
{
Definitions::add_class(cl);
class_to_pclass_[cl] = pclass;
}
netclass_t* Design::find_class(perm_string name) const
{
map<perm_string,netclass_t*>::const_iterator cur = classes_.find(name);
if (cur != classes_.end())
return cur->second;
return 0;
}
NetScope* Design::find_package(perm_string name) const
{
map<perm_string,NetScope*>::const_iterator cur = packages_.find(name);
@@ -157,6 +170,17 @@ list<NetScope*> Design::find_package_scopes() const
return res;
}
list<NetScope*> Design::find_roottask_scopes() const
{
list<NetScope*>res;
for (map<NetScope*,PTaskFunc*>::const_iterator cur = root_tasks_.begin()
; cur != root_tasks_.end() ; ++ cur) {
res.push_back (cur->first);
}
return res;
}
/*
* This method locates a scope in the design, given its rooted
* hierarchical name. Each component of the key is used to scan one
@@ -187,6 +211,25 @@ NetScope* Design::find_scope(const std::list<hname_t>&path) const
}
}
for (map<NetScope*,PTaskFunc*>::const_iterator root = root_tasks_.begin()
; root != root_tasks_.end() ; ++ root) {
NetScope*cur = root->first;
if (path.front() != cur->fullname())
continue;
std::list<hname_t> tmp = path;
tmp.pop_front();
while (cur) {
if (tmp.empty()) return cur;
cur = cur->child( tmp.front() );
tmp.pop_front();
}
}
return 0;
}
@@ -210,55 +253,6 @@ NetScope* Design::find_scope(const hname_t&path) const
return 0;
}
static bool is_design_unit(NetScope*scope)
{
return (scope->type() == NetScope::MODULE && !scope->nested_module())
|| (scope->type() == NetScope::PACKAGE);
}
static bool is_subroutine(NetScope::TYPE type)
{
return type == NetScope::TASK || type == NetScope::FUNC;
}
/*
* This method locates a scope within another scope, given its relative
* hierarchical name. Each component of the key is used to scan one
* more step down the tree until the name runs out or the search
* fails.
*/
NetScope* Design::find_scope_(NetScope*scope, const std::list<hname_t>&path,
NetScope::TYPE type) const
{
std::list<hname_t> tmp = path;
do {
hname_t key = tmp.front();
/* If we are looking for a module or we are not
* looking at the last path component check for
* a name match (second line). */
if (scope->type() == NetScope::MODULE
&& (type == NetScope::MODULE || tmp.size() > 1)
&& scope->module_name()==key.peek_name()) {
/* Up references may match module name */
} else {
NetScope*found_scope = scope->child(key);
if (found_scope == 0) {
found_scope = scope->find_import(this, key.peek_name());
if (found_scope)
found_scope = found_scope->child(key);
}
scope = found_scope;
if (scope == 0) break;
}
tmp.pop_front();
} while (! tmp.empty());
return scope;
}
/*
* This is a relative lookup of a scope by name. The starting point is
* the scope parameter within which I start looking for the scope. If
@@ -272,68 +266,36 @@ NetScope* Design::find_scope(NetScope*scope, const std::list<hname_t>&path,
if (path.empty())
return scope;
// Record the compilation unit scope for use later.
NetScope*unit_scope = scope->unit();
for ( ; scope ; scope = scope->parent()) {
// First search upwards through the hierarchy.
while (scope) {
NetScope*found_scope = find_scope_(scope, path, type);
if (found_scope)
return found_scope;
std::list<hname_t> tmp = path;
// Avoid searching the unit scope twice.
if (scope == unit_scope)
unit_scope = 0;
NetScope*cur = scope;
do {
hname_t key = tmp.front();
/* If we are looking for a module or we are not
* looking at the last path component check for
* a name match (second line). */
if (cur->type() == NetScope::MODULE
&& (type == NetScope::MODULE || tmp.size() > 1)
&& cur->module_name()==key.peek_name()) {
// Special case - see IEEE 1800-2012 section 23.8.1.
if (unit_scope && is_design_unit(scope) && is_subroutine(type)) {
found_scope = find_scope_(unit_scope, path, type);
if (found_scope)
return found_scope;
/* Up references may match module name */
unit_scope = 0;
}
} else {
cur = cur->child( key );
if (cur == 0) break;
}
tmp.pop_front();
} while (! tmp.empty());
scope = scope->parent();
}
// If we haven't already done so, search the compilation unit scope.
if (unit_scope) {
NetScope*found_scope = find_scope_(unit_scope, path, type);
if (found_scope)
return found_scope;
if (cur) return cur;
}
// Last chance. Look for the name starting at the root.
return find_scope(path);
}
/*
* This method locates a scope within another scope, given its relative
* hierarchical name. Each component of the key is used to scan one
* more step down the tree until the name runs out or the search
* fails.
*/
NetScope* Design::find_scope_(NetScope*scope, const hname_t&path,
NetScope::TYPE type) const
{
/* If we are looking for a module or we are not
* looking at the last path component check for
* a name match (second line). */
if ((scope->type() == NetScope::MODULE) && (type == NetScope::MODULE)
&& (scope->module_name() == path.peek_name())) {
/* Up references may match module name */
return scope;
}
NetScope*found_scope = scope->child(path);
if (found_scope == 0) {
found_scope = scope->find_import(this, path.peek_name());
if (found_scope)
found_scope = found_scope->child(path);
}
return found_scope;
}
/*
* This is a relative lookup of a scope by name. The starting point is
* the scope parameter within which I start looking for the scope. If
@@ -345,36 +307,24 @@ NetScope* Design::find_scope(NetScope*scope, const hname_t&path,
{
assert(scope);
// Record the compilation unit scope for use later.
NetScope*unit_scope = scope->unit();
for ( ; scope ; scope = scope->parent()) {
// First search upwards through the hierarchy.
while (scope) {
NetScope*found_scope = find_scope_(scope, path, type);
if (found_scope)
return found_scope;
NetScope*cur = scope;
// Avoid searching the unit scope twice.
if (scope == unit_scope)
unit_scope = 0;
/* If we are looking for a module or we are not
* looking at the last path component check for
* a name match (second line). */
if (cur->type() == NetScope::MODULE
&& (type == NetScope::MODULE)
&& cur->module_name()==path.peek_name()) {
// Special case - see IEEE 1800-2012 section 23.8.1.
if (unit_scope && is_design_unit(scope) && is_subroutine(type)) {
found_scope = find_scope_(unit_scope, path, type);
if (found_scope)
return found_scope;
/* Up references may match module name */
unit_scope = 0;
} else {
cur = cur->child( path );
}
scope = scope->parent();
}
// If we haven't already done so, search the compilation unit scope.
if (unit_scope) {
NetScope*found_scope = find_scope_(unit_scope, path, type);
if (found_scope)
return found_scope;
if (cur) return cur;
}
// Last chance. Look for the name starting at the root.
@@ -876,11 +826,6 @@ NetNet* Design::find_signal(NetScope*scope, pform_name_t path)
if (NetNet*net = scope->find_signal(key))
return net;
if (NetScope*import_scope = scope->find_import(this, key)) {
scope = import_scope;
continue;
}
if (scope->type() == NetScope::MODULE)
break;
@@ -922,6 +867,11 @@ NetScope* Design::find_task(NetScope*scope, const pform_name_t&name)
return 0;
}
void Design::add_root_task(NetScope*tscope, PTaskFunc*tf)
{
root_tasks_[tscope] = tf;
}
void Design::add_node(NetNode*net)
{
assert(net->design_ == 0);
@@ -940,8 +890,8 @@ void Design::add_node(NetNode*net)
void Design::del_node(NetNode*net)
{
assert(net != 0);
assert(net->design_ == this);
assert(net != 0);
/* Interact with the Design::functor method by manipulating the
cur and nxt pointers that it is using. */
+2 -9
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2017 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2013 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
@@ -28,7 +28,6 @@
NetEvent::NetEvent(perm_string n)
: name_(n)
{
local_flag_ = false;
scope_ = 0;
snext_ = 0;
probes_ = 0;
@@ -346,7 +345,7 @@ void NetEvProbe::find_similar_probes(list<NetEvProbe*>&plist)
}
NetEvWait::NetEvWait(NetProc*pr)
: statement_(pr), has_t0_trigger_(false)
: statement_(pr)
{
}
@@ -370,7 +369,6 @@ NetEvWait::~NetEvWait()
tmp->next = tmp->next->next;
delete tmp;
}
delete tgt;
}
events_.clear();
}
@@ -443,8 +441,3 @@ NetProc* NetEvWait::statement()
{
return statement_;
}
const NetProc* NetEvWait::statement() const
{
return statement_;
}
+19 -21
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2020 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-2013 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
@@ -403,14 +403,7 @@ ivl_variable_type_t NetEProperty::expr_type() const
NetESelect::NetESelect(NetExpr*exp, NetExpr*base, unsigned wid,
ivl_select_type_t sel_type)
: expr_(exp), base_(base), use_type_(0), sel_type_(sel_type)
{
expr_width(wid);
}
NetESelect::NetESelect(NetExpr*exp, NetExpr*base, unsigned wid,
ivl_type_t use_type)
: expr_(exp), base_(base), use_type_(use_type), sel_type_(IVL_SEL_OTHER)
: expr_(exp), base_(base), sel_type_(sel_type)
{
expr_width(wid);
}
@@ -438,9 +431,6 @@ ivl_select_type_t NetESelect::select_type() const
ivl_variable_type_t NetESelect::expr_type() const
{
if (use_type_)
return use_type_->base_type();
ivl_variable_type_t type = expr_->expr_type();
// Special case: If the sub-expression is an IVL_VT_STRING,
@@ -449,12 +439,20 @@ ivl_variable_type_t NetESelect::expr_type() const
if (type == IVL_VT_STRING && expr_width()==8)
return IVL_VT_BOOL;
return type;
}
if (type != IVL_VT_DARRAY)
return type;
const netenum_t* NetESelect::enumeration() const
{
return dynamic_cast<const netenum_t*> (use_type_);
ivl_assert(*this, type == IVL_VT_DARRAY);
// Special case: If the expression is a DARRAY, then the
// sub-expression must be a NetESignal and the type of the
// NetESelect expression is the element type of the arrayed signal.
NetESignal*sig = dynamic_cast<NetESignal*>(expr_);
ivl_assert(*this, sig);
const netarray_t*array_type = dynamic_cast<const netarray_t*> (sig->sig()->net_type());
ivl_assert(*this, array_type);
return array_type->element_type()->base_type();
}
bool NetESelect::has_width() const
@@ -463,15 +461,15 @@ bool NetESelect::has_width() const
}
NetESFunc::NetESFunc(const char*n, ivl_variable_type_t t,
unsigned width, unsigned np, bool is_overridden)
: name_(0), type_(t), enum_type_(0), parms_(np), is_overridden_(is_overridden)
unsigned width, unsigned np)
: name_(0), type_(t), enum_type_(0), parms_(np)
{
name_ = lex_strings.add(n);
expr_width(width);
}
NetESFunc::NetESFunc(const char*n, ivl_type_t rtype, unsigned np)
: NetExpr(rtype), name_(0), type_(IVL_VT_NO_TYPE), enum_type_(0), parms_(np), is_overridden_(false)
: NetExpr(rtype), name_(0), type_(IVL_VT_NO_TYPE), enum_type_(0), parms_(np)
{
name_ = lex_strings.add(n);
expr_width(rtype->packed_width());
@@ -487,7 +485,7 @@ NetESFunc::NetESFunc(const char*n, ivl_type_t rtype, unsigned np)
}
NetESFunc::NetESFunc(const char*n, const netenum_t*enum_type, unsigned np)
: name_(0), type_(enum_type->base_type()), enum_type_(enum_type), parms_(np), is_overridden_(false)
: name_(0), type_(enum_type->base_type()), enum_type_(enum_type), parms_(np)
{
name_ = lex_strings.add(n);
expr_width(enum_type->packed_width());
+6 -154
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2018 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-2013 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
@@ -23,10 +23,6 @@
# include <typeinfo>
# include "ivl_assert.h"
#if __cplusplus < 201103L
#define unique_ptr auto_ptr
#endif
using namespace std;
/*
@@ -92,10 +88,6 @@ NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector<Net
// fills in the context_map with local variables held by the scope.
scope()->evaluate_function_find_locals(loc, context_map);
// Execute any variable initialization statements.
if (const NetProc*init_proc = scope()->var_init())
init_proc->evaluate_function(loc, context_map);
if (debug_eval_tree && proc_==0) {
cerr << loc.get_fileline() << ": NetFuncDef::evaluate_function: "
<< "Function " << scope_path(scope())
@@ -217,98 +209,6 @@ bool NetProc::evaluate_function(const LineInfo&,
return false;
}
void NetAssign::eval_func_lval_op_real_(const LineInfo&loc,
verireal&lv, verireal&rv) const
{
switch (op_) {
case '+':
lv = lv + rv;
break;
case '-':
lv = lv - rv;
break;
case '*':
lv = lv * rv;
break;
case '/':
lv = lv / rv;
break;
case '%':
lv = lv % rv;
break;
default:
cerr << "Illegal assignment operator: "
<< human_readable_op(op_) << endl;
ivl_assert(loc, 0);
}
}
void NetAssign::eval_func_lval_op_(const LineInfo&loc,
verinum&lv, verinum&rv) const
{
unsigned lv_width = lv.len();
bool lv_sign = lv.has_sign();
switch (op_) {
case 'l':
case 'R':
// The left operand is self-determined.
break;
case 'r':
// The left operand is self-determined, but we need to
// cast it to unsigned to get a logical shift.
lv.has_sign(false);
break;
default:
// The left operand must be cast to the expression type/size
lv.has_sign(rv.has_sign());
lv = cast_to_width(lv, rv.len());
}
switch (op_) {
case '+':
lv = lv + rv;
break;
case '-':
lv = lv - rv;
break;
case '*':
lv = lv * rv;
break;
case '/':
lv = lv / rv;
break;
case '%':
lv = lv % rv;
break;
case '&':
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1)
lv.set(idx, lv[idx] & rv[idx]);
break;
case '|':
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1)
lv.set(idx, lv[idx] | rv[idx]);
break;
case '^':
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1)
lv.set(idx, lv[idx] ^ rv[idx]);
break;
case 'l':
lv = lv << rv.as_unsigned();
break;
case 'r':
lv = lv >> rv.as_unsigned();
break;
case 'R':
lv = lv >> rv.as_unsigned();
break;
default:
cerr << "Illegal assignment operator: "
<< human_readable_op(op_) << endl;
ivl_assert(loc, 0);
}
lv = cast_to_width(lv, lv_width);
lv.has_sign(lv_sign);
}
bool NetAssign::eval_func_lval_(const LineInfo&loc,
map<perm_string,LocalVar>&context_map,
const NetAssign_*lval, NetExpr*rval_result) const
@@ -369,55 +269,18 @@ bool NetAssign::eval_func_lval_(const LineInfo&loc,
ivl_assert(loc, base + lval->lwidth() <= old_lval->expr_width());
NetEConst*lval_const = dynamic_cast<NetEConst*>(old_lval);
ivl_assert(loc, lval_const);
verinum lval_v = lval_const->value();
NetEConst*rval_const = dynamic_cast<NetEConst*>(rval_result);
ivl_assert(loc, rval_const);
verinum rval_v = rval_const->value();
verinum rval_v = cast_to_width(rval_const->value(), lval->lwidth());
verinum lpart(verinum::Vx, lval->lwidth());
if (op_) {
for (unsigned idx = 0 ; idx < lpart.len() ; idx += 1)
lpart.set(idx, lval_v[base+idx]);
eval_func_lval_op_(loc, lpart, rval_v);
} else {
lpart = cast_to_width(rval_v, lval->lwidth());
}
for (unsigned idx = 0 ; idx < lpart.len() ; idx += 1)
lval_v.set(idx+base, lpart[idx]);
for (unsigned idx = 0 ; idx < rval_v.len() ; idx += 1)
lval_v.set(idx+base, rval_v[idx]);
delete base_result;
delete rval_result;
rval_result = new NetEConst(lval_v);
} else {
if (op_ == 0) {
rval_result = fix_assign_value(lval->sig(), rval_result);
} else if (dynamic_cast<NetECReal*>(rval_result)) {
NetECReal*lval_const = dynamic_cast<NetECReal*>(old_lval);
ivl_assert(loc, lval_const);
verireal lval_r = lval_const->value();
NetECReal*rval_const = dynamic_cast<NetECReal*>(rval_result);
ivl_assert(loc, rval_const);
verireal rval_r = rval_const->value();
eval_func_lval_op_real_(loc, lval_r, rval_r);
delete rval_result;
rval_result = new NetECReal(lval_r);
} else {
NetEConst*lval_const = dynamic_cast<NetEConst*>(old_lval);
ivl_assert(loc, lval_const);
verinum lval_v = lval_const->value();
NetEConst*rval_const = dynamic_cast<NetEConst*>(rval_result);
ivl_assert(loc, rval_const);
verinum rval_v = rval_const->value();
eval_func_lval_op_(loc, lval_v, rval_v);
delete rval_result;
rval_result = new NetEConst(lval_v);
}
rval_result = fix_assign_value(lval->sig(), rval_result);
}
if (old_lval)
@@ -455,13 +318,6 @@ bool NetAssign::evaluate_function(const LineInfo&loc,
NetEConst*rval_const = dynamic_cast<NetEConst*>(rval_result);
ivl_assert(*this, rval_const);
if (op_) {
cerr << get_fileline() << ": sorry: Assignment operators "
"inside a constant function are not currently "
"supported if the LHS is a concatenation." << endl;
return false;
}
verinum rval_full = rval_const->value();
delete rval_result;
@@ -513,10 +369,6 @@ bool NetBlock::evaluate_function(const LineInfo&loc,
// Now collect the new locals.
subscope_->evaluate_function_find_locals(loc, local_context_map);
use_local_context_map = true;
// Execute any variable initialization statements.
if (const NetProc*init_proc = subscope_->var_init())
init_proc->evaluate_function(loc, local_context_map);
}
// Now use the local context map if there is any local
@@ -1022,7 +874,7 @@ NetExpr* NetESignal::evaluate_function(const LineInfo&loc,
NetExpr* NetETernary::evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&context_map) const
{
unique_ptr<NetExpr> cval (cond_->evaluate_function(loc, context_map));
auto_ptr<NetExpr> cval (cond_->evaluate_function(loc, context_map));
switch (const_logical(cval.get())) {
+1 -26
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2013 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
@@ -311,20 +311,6 @@ void Nexus::count_io(unsigned&inp, unsigned&out) const
}
}
bool Nexus::has_floating_input() const
{
bool found_input = false;
for (const Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
if (cur->get_dir() == Link::OUTPUT)
return false;
if (cur->get_dir() == Link::INPUT)
found_input = true;
}
return found_input;
}
bool Nexus::drivers_present() const
{
for (const Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
@@ -481,17 +467,6 @@ NetNet* Nexus::pick_any_net()
return 0;
}
NetNode* Nexus::pick_any_node()
{
for (Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
NetNode*node = dynamic_cast<NetNode*>(cur->get_obj());
if (node != 0)
return node;
}
return 0;
}
const char* Nexus::name() const
{
if (name_)
+136 -258
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2019 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-2013 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -19,37 +19,37 @@
# include "config.h"
# include <iostream>
# include <set>
# include <iostream>
# include <cassert>
# include <typeinfo>
# include "compiler.h"
# include "netlist.h"
# include "netmisc.h"
NexusSet* NetExpr::nex_input(bool, bool, bool) const
NexusSet* NetExpr::nex_input(bool)
{
cerr << get_fileline()
<< ": internal error: nex_input not implemented: "
<< *this << endl;
return new NexusSet;
return 0;
}
NexusSet* NetProc::nex_input(bool, bool, bool) const
NexusSet* NetProc::nex_input(bool)
{
cerr << get_fileline()
<< ": internal error: NetProc::nex_input not implemented"
<< endl;
return new NexusSet;
return 0;
}
NexusSet* NetEArrayPattern::nex_input(bool rem_out, bool always_sens, bool nested_func) const
NexusSet* NetEArrayPattern::nex_input(bool rem_out)
{
NexusSet*result = new NexusSet;
for (size_t idx = 0 ; idx < items_.size() ; idx += 1) {
if (items_[idx]==0) continue;
NexusSet*tmp = items_[idx]->nex_input(rem_out, always_sens, nested_func);
NexusSet*tmp = items_[idx]->nex_input(rem_out);
if (tmp == 0) continue;
result->add(*tmp);
@@ -58,32 +58,32 @@ NexusSet* NetEArrayPattern::nex_input(bool rem_out, bool always_sens, bool neste
return result;
}
NexusSet* NetEBinary::nex_input(bool rem_out, bool always_sens, bool nested_func) const
NexusSet* NetEBinary::nex_input(bool rem_out)
{
NexusSet*result = left_->nex_input(rem_out, always_sens, nested_func);
NexusSet*tmp = right_->nex_input(rem_out, always_sens, nested_func);
NexusSet*result = left_->nex_input(rem_out);
NexusSet*tmp = right_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
return result;
}
NexusSet* NetEConcat::nex_input(bool rem_out, bool always_sens, bool nested_func) const
NexusSet* NetEConcat::nex_input(bool rem_out)
{
if (parms_[0] == NULL) return new NexusSet;
NexusSet*result = parms_[0]->nex_input(rem_out, always_sens, nested_func);
if (parms_[0] == NULL) return NULL;
NexusSet*result = parms_[0]->nex_input(rem_out);
for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) {
if (parms_[idx] == NULL) {
delete result;
return new NexusSet;
return NULL;
}
NexusSet*tmp = parms_[idx]->nex_input(rem_out, always_sens, nested_func);
NexusSet*tmp = parms_[idx]->nex_input(rem_out);
result->add(*tmp);
delete tmp;
}
return result;
}
NexusSet* NetEAccess::nex_input(bool, bool, bool) const
NexusSet* NetEAccess::nex_input(bool)
{
return new NexusSet;
}
@@ -91,73 +91,63 @@ NexusSet* NetEAccess::nex_input(bool, bool, bool) const
/*
* A constant has not inputs, so always return an empty set.
*/
NexusSet* NetEConst::nex_input(bool, bool, bool) const
NexusSet* NetEConst::nex_input(bool)
{
return new NexusSet;
}
NexusSet* NetECReal::nex_input(bool, bool, bool) const
NexusSet* NetECReal::nex_input(bool)
{
return new NexusSet;
}
NexusSet* NetEEvent::nex_input(bool, bool, bool) const
NexusSet* NetEEvent::nex_input(bool)
{
return new NexusSet;
}
NexusSet* NetELast::nex_input(bool, bool, bool) const
NexusSet* NetELast::nex_input(bool)
{
return new NexusSet;
}
NexusSet* NetENetenum::nex_input(bool, bool, bool) const
NexusSet* NetENetenum::nex_input(bool)
{
return new NexusSet;
}
NexusSet* NetENew::nex_input(bool, bool, bool) const
NexusSet* NetENew::nex_input(bool)
{
return new NexusSet;
}
NexusSet* NetENull::nex_input(bool, bool, bool) const
NexusSet* NetENull::nex_input(bool)
{
return new NexusSet;
}
NexusSet* NetEProperty::nex_input(bool, bool, bool) const
NexusSet* NetEProperty::nex_input(bool)
{
return new NexusSet;
}
NexusSet* NetEScope::nex_input(bool, bool, bool) const
NexusSet* NetEScope::nex_input(bool)
{
return new NexusSet;
}
NexusSet* NetESelect::nex_input(bool rem_out, bool always_sens, bool nested_func) const
NexusSet* NetESelect::nex_input(bool rem_out)
{
NexusSet*result = base_? base_->nex_input(rem_out, always_sens, nested_func) : new NexusSet();
NexusSet*tmp = expr_->nex_input(rem_out, always_sens, nested_func);
bool const_select = result->size() == 0;
if (always_sens && const_select) {
if (NetEConst *val = dynamic_cast <NetEConst*> (base_)) {
assert(select_type() == IVL_SEL_OTHER);
if (NetESignal *sig = dynamic_cast<NetESignal*> (expr_)) {
delete tmp;
tmp = sig->nex_input_base(rem_out, always_sens, nested_func,
val->value().as_unsigned(), expr_width());
} else {
cerr << get_fileline() << ": Sorry, cannot determine the sensitivity "
<< "for the select of " << *expr_ << ", using all bits." << endl;
}
}
NexusSet*result = base_? base_->nex_input(rem_out) : new NexusSet();
NexusSet*tmp = expr_->nex_input(rem_out);
if (tmp == NULL) {
delete result;
return NULL;
}
result->add(*tmp);
delete tmp;
/* See the comment for NetESignal below. */
if (base_ && ! always_sens && warn_sens_entire_vec) {
if (base_ && warn_sens_entire_vec) {
cerr << get_fileline() << ": warning: @* is sensitive to all "
"bits in '" << *expr_ << "'." << endl;
}
@@ -167,35 +157,30 @@ NexusSet* NetESelect::nex_input(bool rem_out, bool always_sens, bool nested_func
/*
* The $fread, etc. system functions can have NULL arguments.
*/
NexusSet* NetESFunc::nex_input(bool rem_out, bool always_sens, bool nested_func) const
NexusSet* NetESFunc::nex_input(bool rem_out)
{
NexusSet*result = new NexusSet;
if (parms_.empty())
return new NexusSet;
if (parms_.empty()) return result;
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
NexusSet*result;
if (parms_[0]) result = parms_[0]->nex_input(rem_out);
else result = new NexusSet;
for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) {
if (parms_[idx]) {
NexusSet*tmp = parms_[idx]->nex_input(rem_out, always_sens, nested_func);
NexusSet*tmp = parms_[idx]->nex_input(rem_out);
result->add(*tmp);
delete tmp;
}
}
return result;
}
NexusSet* NetEShallowCopy::nex_input(bool, bool, bool) const
NexusSet* NetEShallowCopy::nex_input(bool)
{
return new NexusSet;
}
NexusSet* NetESignal::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
return nex_input_base(rem_out, always_sens, nested_func, 0, 0);
}
NexusSet* NetESignal::nex_input_base(bool rem_out, bool always_sens, bool nested_func,
unsigned base, unsigned width) const
NexusSet* NetESignal::nex_input(bool rem_out)
{
/*
* This is not what I would expect for the various selects (bit,
@@ -203,88 +188,48 @@ NexusSet* NetESignal::nex_input_base(bool rem_out, bool always_sens, bool nested
* instead of building the appropriate select and then using it
* as the trigger. Other simulators also add everything.
*/
bool const_select = false;
unsigned const_word = 0;
NexusSet*result = new NexusSet;
/* Local signals are not added to the sensitivity list. */
if (net_->local_flag()) return result;
/* If we have an array index add it to the sensitivity list. */
if (word_) {
NexusSet*tmp;
tmp = word_->nex_input(rem_out, always_sens, nested_func);
tmp = word_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
if (!always_sens && warn_sens_entire_arr) {
if (warn_sens_entire_arr) {
cerr << get_fileline() << ": warning: @* is sensitive to all "
<< net_->unpacked_count() << " words in array '"
<< name() << "'." << endl;
}
if (always_sens) if (NetEConst *val = dynamic_cast <NetEConst*> (word_)) {
const_select = true;
const_word = val->value().as_unsigned();
}
}
if ((base == 0) && (width == 0)) width = net_->vector_width();
if (const_select) {
result->add(net_->pin(const_word).nexus(), base, width);
} else {
for (unsigned idx = 0 ; idx < net_->pin_count() ; idx += 1)
result->add(net_->pin(idx).nexus(), base, width);
}
for (unsigned idx = 0 ; idx < net_->pin_count() ; idx += 1)
result->add(net_->pin(idx).nexus(), 0, net_->vector_width());
return result;
}
NexusSet* NetETernary::nex_input(bool rem_out, bool always_sens, bool nested_func) const
NexusSet* NetETernary::nex_input(bool rem_out)
{
NexusSet*tmp;
NexusSet*result = cond_->nex_input(rem_out, always_sens, nested_func);
NexusSet*result = cond_->nex_input(rem_out);
tmp = true_val_->nex_input(rem_out, always_sens, nested_func);
tmp = true_val_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
tmp = false_val_->nex_input(rem_out, always_sens, nested_func);
tmp = false_val_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
return result;
}
NexusSet* NetEUFunc::nex_input(bool rem_out, bool always_sens, bool nested_func) const
NexusSet* NetEUFunc::nex_input(bool rem_out)
{
NexusSet*result = new NexusSet;
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
NexusSet*tmp = parms_[idx]->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
if (always_sens) {
NetFuncDef*func = func_->func_def();
// Avoid recursive function calls.
static set<NetFuncDef*> func_set;
if (!nested_func)
func_set.clear();
if (!func_set.insert(func).second)
return result;
NexusSet*tmp = func->proc()->nex_input(rem_out, always_sens, true);
// Remove the function inputs
NexusSet*in = new NexusSet;
for (unsigned idx = 0 ; idx < func->port_count() ; idx += 1) {
NetNet*net = func->port(idx);
assert(net->pin_count() == 1);
in->add(net->pin(0).nexus(), 0, net->vector_width());
}
tmp->rem(*in);
delete in;
NexusSet*tmp = parms_[idx]->nex_input(rem_out);
result->add(*tmp);
delete tmp;
}
@@ -292,28 +237,21 @@ NexusSet* NetEUFunc::nex_input(bool rem_out, bool always_sens, bool nested_func)
return result;
}
NexusSet* NetEUnary::nex_input(bool rem_out, bool always_sens, bool nested_func) const
NexusSet* NetEUnary::nex_input(bool rem_out)
{
return expr_->nex_input(rem_out, always_sens, nested_func);
return expr_->nex_input(rem_out);
}
NexusSet* NetAlloc::nex_input(bool, bool, bool) const
NexusSet* NetAssign_::nex_input(bool rem_out)
{
return new NexusSet;
}
NexusSet* NetAssign_::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
assert(! nest_);
NexusSet*result = new NexusSet;
if (word_) {
NexusSet*tmp = word_->nex_input(rem_out, always_sens, nested_func);
NexusSet*tmp = word_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
}
if (base_) {
NexusSet*tmp = base_->nex_input(rem_out, always_sens, nested_func);
NexusSet*tmp = base_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
}
@@ -321,21 +259,15 @@ NexusSet* NetAssign_::nex_input(bool rem_out, bool always_sens, bool nested_func
return result;
}
NexusSet* NetAssignBase::nex_input(bool rem_out, bool always_sens, bool nested_func) const
NexusSet* NetAssignBase::nex_input(bool rem_out)
{
NexusSet*result = new NexusSet;
// For the deassign and release statements there is no R-value.
if (rval_) {
NexusSet*tmp = rval_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
NexusSet*result = rval_->nex_input(rem_out);
/* It is possible that the lval_ can have nex_input values. In
particular, index expressions are statement inputs as well,
so should be addressed here. */
for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) {
NexusSet*tmp = cur->nex_input(rem_out, always_sens, nested_func);
NexusSet*tmp = cur->nex_input(rem_out);
result->add(*tmp);
delete tmp;
}
@@ -360,15 +292,16 @@ NexusSet* NetAssignBase::nex_input(bool rem_out, bool always_sens, bool nested_f
* In this example, "t" should not be in the input set because it is
* used by the sequence as a temporary value.
*/
NexusSet* NetBlock::nex_input(bool rem_out, bool always_sens, bool nested_func) const
NexusSet* NetBlock::nex_input(bool rem_out)
{
if (last_ == 0) return new NexusSet;
if (last_ == 0)
return new NexusSet;
if (! always_sens && (type_ != SEQU)) {
if (type_ != SEQU) {
cerr << get_fileline() << ": internal error: Sorry, "
<< "I don't know how to synthesize fork/join blocks."
<< endl;
return new NexusSet;
return 0;
}
NetProc*cur = last_->next_;
@@ -379,10 +312,10 @@ NexusSet* NetBlock::nex_input(bool rem_out, bool always_sens, bool nested_func)
do {
/* Get the inputs for the current statement. */
NexusSet*tmp = cur->nex_input(rem_out, always_sens, nested_func);
NexusSet*tmp = cur->nex_input(rem_out);
/* Add the current input set to the accumulated input set. */
result->add(*tmp);
if (tmp != 0) result->add(*tmp);
delete tmp;
/* Add the current outputs to the accumulated output set if
@@ -406,9 +339,11 @@ NexusSet* NetBlock::nex_input(bool rem_out, bool always_sens, bool nested_func)
* the inputs to all the guards, and the inputs to all the guarded
* statements.
*/
NexusSet* NetCase::nex_input(bool rem_out, bool always_sens, bool nested_func) const
NexusSet* NetCase::nex_input(bool rem_out)
{
NexusSet*result = expr_->nex_input(rem_out, always_sens, nested_func);
NexusSet*result = expr_->nex_input(rem_out);
if (result == 0)
return 0;
for (size_t idx = 0 ; idx < items_.size() ; idx += 1) {
@@ -416,7 +351,8 @@ NexusSet* NetCase::nex_input(bool rem_out, bool always_sens, bool nested_func) c
if (items_[idx].statement == 0)
continue;
NexusSet*tmp = items_[idx].statement->nex_input(rem_out, always_sens, nested_func);
NexusSet*tmp = items_[idx].statement->nex_input(rem_out);
assert(tmp);
result->add(*tmp);
delete tmp;
@@ -424,7 +360,8 @@ NexusSet* NetCase::nex_input(bool rem_out, bool always_sens, bool nested_func) c
case is special and is identified by a null
guard. The default guard obviously has no input. */
if (items_[idx].guard) {
tmp = items_[idx].guard->nex_input(rem_out, always_sens, nested_func);
tmp = items_[idx].guard->nex_input(rem_out);
assert(tmp);
result->add(*tmp);
delete tmp;
}
@@ -433,18 +370,24 @@ NexusSet* NetCase::nex_input(bool rem_out, bool always_sens, bool nested_func) c
return result;
}
NexusSet* NetCondit::nex_input(bool rem_out, bool always_sens, bool nested_func) const
NexusSet* NetCAssign::nex_input(bool)
{
NexusSet*result = expr_->nex_input(rem_out, always_sens, nested_func);
cerr << get_fileline() << ": internal warning: NetCAssign::nex_input()"
<< " not implemented." << endl;
return new NexusSet;
}
NexusSet* NetCondit::nex_input(bool rem_out)
{
NexusSet*result = expr_->nex_input(rem_out);
if (if_ != 0) {
NexusSet*tmp = if_->nex_input(rem_out, always_sens, nested_func);
NexusSet*tmp = if_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
}
if (else_ != 0) {
NexusSet*tmp = else_->nex_input(rem_out, always_sens, nested_func);
NexusSet*tmp = else_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
}
@@ -452,100 +395,47 @@ NexusSet* NetCondit::nex_input(bool rem_out, bool always_sens, bool nested_func)
return result;
}
NexusSet* NetDisable::nex_input(bool, bool, bool) const
NexusSet* NetDoWhile::nex_input(bool rem_out)
{
NexusSet*result = proc_->nex_input(rem_out);
NexusSet*tmp = cond_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
return result;
}
NexusSet* NetForce::nex_input(bool)
{
cerr << get_fileline() << ": internal warning: NetForce::nex_input()"
<< " not implemented." << endl;
return new NexusSet;
}
NexusSet* NetDoWhile::nex_input(bool rem_out, bool always_sens, bool nested_func) const
NexusSet* NetForLoop::nex_input(bool rem_out)
{
NexusSet*result = cond_->nex_input(rem_out, always_sens, nested_func);
NexusSet*result = init_expr_->nex_input(rem_out);
if (proc_) {
NexusSet*tmp = proc_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
NexusSet*tmp = condition_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
tmp = statement_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
tmp = step_statement_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
return result;
}
NexusSet* NetEvTrig::nex_input(bool, bool, bool) const
NexusSet* NetForever::nex_input(bool rem_out)
{
return new NexusSet;
}
NexusSet* NetEvWait::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
NexusSet*result = new NexusSet;
if (statement_) {
NexusSet*tmp = statement_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
NexusSet*result = statement_->nex_input(rem_out);
return result;
}
NexusSet* NetForever::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
NexusSet*result = new NexusSet;
if (statement_) {
NexusSet*tmp = statement_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
return result;
}
NexusSet* NetForLoop::nex_input(bool rem_out, bool always_sens, bool nested_func) const
{
NexusSet*result = new NexusSet;
if (init_expr_) {
NexusSet*tmp = init_expr_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
if (condition_) {
NexusSet*tmp = condition_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
if (step_statement_) {
NexusSet*tmp = step_statement_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
if (statement_) {
NexusSet*tmp = statement_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
if (gn_shared_loop_index_flag) {
NexusSet*tmp = new NexusSet();
for (unsigned idx = 0 ; idx < index_->pin_count() ; idx += 1)
tmp->add(index_->pin(idx).nexus(), 0, index_->vector_width());
result->rem(*tmp);
delete tmp;
}
return result;
}
NexusSet* NetFree::nex_input(bool, bool, bool) const
{
return new NexusSet;
}
/*
* The NetPDelay statement is a statement of the form
*
@@ -555,44 +445,36 @@ NexusSet* NetFree::nex_input(bool, bool, bool) const
* include the input set of the <expr> because it does not affect the
* result. The statement can be omitted.
*/
NexusSet* NetPDelay::nex_input(bool rem_out, bool always_sens, bool nested_func) const
NexusSet* NetPDelay::nex_input(bool rem_out)
{
NexusSet*result = new NexusSet;
if (statement_) {
NexusSet*tmp = statement_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
if (statement_ == 0) return 0;
NexusSet*result = statement_->nex_input(rem_out);
return result;
}
NexusSet* NetRepeat::nex_input(bool rem_out, bool always_sens, bool nested_func) const
NexusSet* NetRepeat::nex_input(bool rem_out)
{
NexusSet*result = expr_->nex_input(rem_out, always_sens, nested_func);
if (statement_) {
NexusSet*tmp = statement_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
NexusSet*result = statement_->nex_input(rem_out);
NexusSet*tmp = expr_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
return result;
}
/*
* The $display, etc. system tasks can have NULL arguments.
*/
NexusSet* NetSTask::nex_input(bool rem_out, bool always_sens, bool nested_func) const
NexusSet* NetSTask::nex_input(bool rem_out)
{
NexusSet*result = new NexusSet;
if (parms_.empty())
return new NexusSet;
if (parms_.empty()) return result;
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
NexusSet*result;
if (parms_[0]) result = parms_[0]->nex_input(rem_out);
else result = new NexusSet;
for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) {
if (parms_[idx]) {
NexusSet*tmp = parms_[idx]->nex_input(rem_out, always_sens, nested_func);
NexusSet*tmp = parms_[idx]->nex_input(rem_out);
result->add(*tmp);
delete tmp;
}
@@ -606,20 +488,16 @@ NexusSet* NetSTask::nex_input(bool rem_out, bool always_sens, bool nested_func)
* parameters to consider, because the compiler already removed them
* and converted them to blocking assignments.
*/
NexusSet* NetUTask::nex_input(bool, bool, bool) const
NexusSet* NetUTask::nex_input(bool)
{
return new NexusSet;
}
NexusSet* NetWhile::nex_input(bool rem_out, bool always_sens, bool nested_func) const
NexusSet* NetWhile::nex_input(bool rem_out)
{
NexusSet*result = cond_->nex_input(rem_out, always_sens, nested_func);
if (proc_) {
NexusSet*tmp = proc_->nex_input(rem_out, always_sens, nested_func);
result->add(*tmp);
delete tmp;
}
NexusSet*result = proc_->nex_input(rem_out);
NexusSet*tmp = cond_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
return result;
}
+16 -35
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2017 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-2013 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
@@ -36,13 +36,8 @@ void NetProc::nex_output(NexusSet&)
<< endl;
}
void NetAlloc::nex_output(NexusSet&)
{
}
void NetAssign_::nex_output(NexusSet&out)
{
assert(! nest_);
assert(sig_);
unsigned use_word = 0;
unsigned use_base = 0;
@@ -94,7 +89,8 @@ void NetAssignBase::nex_output(NexusSet&out)
void NetBlock::nex_output(NexusSet&out)
{
if (last_ == 0) return;
if (last_ == 0)
return;
NetProc*cur = last_;
do {
@@ -108,8 +104,10 @@ void NetCase::nex_output(NexusSet&out)
for (size_t idx = 0 ; idx < items_.size() ; idx += 1) {
// Empty statements clearly have no output.
if (items_[idx].statement == 0) continue;
if (items_[idx].statement == 0)
continue;
assert(items_[idx].statement);
items_[idx].statement->nex_output(out);
}
@@ -117,31 +115,22 @@ void NetCase::nex_output(NexusSet&out)
void NetCondit::nex_output(NexusSet&out)
{
if (if_) if_->nex_output(out);
if (else_) else_->nex_output(out);
}
void NetDisable::nex_output(NexusSet&)
{
if (if_ != 0)
if_->nex_output(out);
if (else_ != 0)
else_->nex_output(out);
}
void NetDoWhile::nex_output(NexusSet&out)
{
if (proc_) proc_->nex_output(out);
}
void NetEvTrig::nex_output(NexusSet&)
{
if (proc_ != 0)
proc_->nex_output(out);
}
void NetEvWait::nex_output(NexusSet&out)
{
if (statement_) statement_->nex_output(out);
}
void NetForever::nex_output(NexusSet&out)
{
if (statement_) statement_->nex_output(out);
assert(statement_);
statement_->nex_output(out);
}
void NetForLoop::nex_output(NexusSet&out)
@@ -149,20 +138,11 @@ void NetForLoop::nex_output(NexusSet&out)
if (statement_) statement_->nex_output(out);
}
void NetFree::nex_output(NexusSet&)
{
}
void NetPDelay::nex_output(NexusSet&out)
{
if (statement_) statement_->nex_output(out);
}
void NetRepeat::nex_output(NexusSet&out)
{
if (statement_) statement_->nex_output(out);
}
/*
* For the purposes of synthesis, system task calls have no output at
* all. This is OK because most system tasks are not synthesizable in
@@ -183,5 +163,6 @@ void NetUTask::nex_output(NexusSet&)
void NetWhile::nex_output(NexusSet&out)
{
if (proc_) proc_->nex_output(out);
if (proc_ != 0)
proc_->nex_output(out);
}
+3 -15
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2014 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
@@ -56,17 +56,6 @@ void NetBlock::append(NetProc*cur)
}
}
void NetBlock::prepend(NetProc*cur)
{
if (last_ == 0) {
last_ = cur;
cur->next_ = cur;
} else {
cur->next_ = last_->next_;
last_->next_ = cur;
}
}
const NetProc* NetBlock::proc_first() const
{
if (last_ == 0)
@@ -83,8 +72,8 @@ const NetProc* NetBlock::proc_next(const NetProc*cur) const
return cur->next_;
}
NetCase::NetCase(ivl_case_quality_t q, NetCase::TYPE c, NetExpr*ex, unsigned cnt)
: quality_(q), type_(c), expr_(ex), items_(cnt)
NetCase::NetCase(NetCase::TYPE c, NetExpr*ex, unsigned cnt)
: type_(c), expr_(ex), items_(cnt)
{
ivl_assert(*this, expr_);
}
@@ -199,7 +188,6 @@ NetForever::~NetForever()
NetForLoop::NetForLoop(NetNet*ind, NetExpr*iexpr, NetExpr*cond, NetProc*sub, NetProc*step)
: index_(ind), init_expr_(iexpr), condition_(cond), statement_(sub), step_statement_(step)
{
as_block_ = NULL;
}
void NetForLoop::wrap_up()
+39 -147
View File
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2000-2019 Stephen Williams (steve@icarus.com)
* Copyright (c) 2016 CERN Michele Castellana (michele.castellana@cern.ch)
* Copyright (c) 2000-2014 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
@@ -24,8 +23,6 @@
# include "netlist.h"
# include "netclass.h"
# include "netenum.h"
# include "netvector.h"
# include "PPackage.h"
# include <cstring>
# include <cstdlib>
# include <sstream>
@@ -113,13 +110,11 @@ void Definitions::add_class(netclass_t*net_class)
* in question.
*/
NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, NetScope*in_unit,
bool nest, bool program, bool interface, bool compilation_unit)
NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest,
bool program, bool interface)
: type_(t), name_(n), nested_module_(nest), program_block_(program),
is_interface_(interface), is_unit_(compilation_unit), unit_(in_unit), up_(up)
is_interface_(interface), up_(up)
{
imports_ = 0;
typedefs_ = 0;
events_ = 0;
lcounter_ = 0;
is_auto_ = false;
@@ -127,10 +122,8 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, NetScope*in_u
calls_stask_ = false;
in_final_ = false;
if (compilation_unit)
unit_ = this;
if (up) {
assert(t!=CLASS);
need_const_func_ = up->need_const_func_;
is_const_func_ = up->is_const_func_;
time_unit_ = up->time_unit();
@@ -138,8 +131,6 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, NetScope*in_u
time_from_timescale_ = up->time_from_timescale();
// Need to check for duplicate names?
up_->children_[name_] = this;
if (unit_ == 0)
unit_ = up_->unit_;
} else {
need_const_func_ = false;
is_const_func_ = false;
@@ -148,7 +139,6 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, NetScope*in_u
time_from_timescale_ = false;
}
var_init_ = 0;
switch (t) {
case NetScope::TASK:
task_ = 0;
@@ -171,8 +161,6 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, NetScope*in_u
lineno_ = 0;
def_lineno_ = 0;
genvar_tmp_val = 0;
tie_hi_ = 0;
tie_lo_ = 0;
}
NetScope::~NetScope()
@@ -207,72 +195,16 @@ void NetScope::set_line(perm_string file, perm_string def_file,
def_lineno_ = def_lineno;
}
void NetScope::add_imports(const map<perm_string,PPackage*>*imports)
{
if (!imports->empty())
imports_ = imports;
}
NetScope*NetScope::find_import(const Design*des, perm_string name)
{
if (imports_ == 0)
return 0;
map<perm_string,PPackage*>::const_iterator cur = imports_->find(name);
if (cur != imports_->end()) {
return des->find_package(cur->second->pscope_name());
} else
return 0;
}
void NetScope::add_typedefs(const map<perm_string,data_type_t*>*typedefs)
{
if (!typedefs->empty())
typedefs_ = typedefs;
}
NetScope*NetScope::find_typedef_scope(const Design*des, data_type_t*type)
{
assert(type);
NetScope *cur_scope = this;
while (cur_scope) {
if (cur_scope->typedefs_ && cur_scope->typedefs_->find(type->name) != cur_scope->typedefs_->end())
return cur_scope;
NetScope*import_scope = cur_scope->find_import(des, type->name);
if (import_scope)
cur_scope = import_scope;
else if (cur_scope == unit_)
return 0;
else
cur_scope = cur_scope->parent();
if (cur_scope == 0)
cur_scope = unit_;
}
return 0;
}
/*
* Look for the enumeration in the current scope and any parent scopes.
*/
const netenum_t*NetScope::find_enumeration_for_name(const Design*des, perm_string name)
const netenum_t*NetScope::find_enumeration_for_name(perm_string name)
{
NetScope *cur_scope = this;
while (cur_scope) {
NetEConstEnum*tmp = cur_scope->enum_names_[name];
if (tmp) break;
NetScope*import_scope = cur_scope->find_import(des, name);
if (import_scope)
cur_scope = import_scope;
else if (cur_scope == unit_)
return 0;
else
cur_scope = cur_scope->parent();
if (cur_scope == 0)
cur_scope = unit_;
cur_scope = cur_scope->parent();
}
assert(cur_scope);
@@ -367,16 +299,16 @@ bool NetScope::auto_name(const char*prefix, char pad, const char* suffix)
*/
bool NetScope::replace_parameter(perm_string key, PExpr*val, NetScope*scope)
{
if (parameters.find(key) == parameters.end())
return false;
bool flag = false;
param_expr_t&ref = parameters[key];
if (ref.local_flag)
return false;
if (parameters.find(key) != parameters.end()) {
param_expr_t&ref = parameters[key];
ref.val_expr = val;
ref.val_scope = scope;
flag = true;
}
ref.val_expr = val;
ref.val_scope = scope;
return true;
return flag;
}
bool NetScope::make_parameter_unannotatable(perm_string key)
@@ -427,7 +359,12 @@ const NetExpr* NetScope::get_parameter(Design*des,
msb = 0;
lsb = 0;
const NetExpr*tmp = enumeration_expr(key);
return tmp;
if (tmp) return tmp;
tmp = des->enumeration_expr(key);
if (tmp) return tmp;
return 0;
}
NetScope::param_ref_t NetScope::find_parameter(perm_string key)
@@ -444,6 +381,11 @@ NetScope::param_ref_t NetScope::find_parameter(perm_string key)
return idx;
}
NetScope::TYPE NetScope::type() const
{
return type_;
}
void NetScope::print_type(ostream&stream) const
{
switch (type_) {
@@ -562,7 +504,6 @@ void NetScope::add_module_port_info( unsigned idx, perm_string name, PortType::E
unsigned long width )
{
assert(type_ == MODULE);
assert(ports_.size() > idx);
PortInfo &info = ports_[idx];
info.name = name;
info.type = ptype;
@@ -710,11 +651,15 @@ netclass_t*NetScope::find_class(perm_string name)
if (type_==CLASS && name_==hname_t(name))
return class_def_;
// Look for the class directly within this scope.
// Look for the class that directly within this scope.
map<perm_string,netclass_t*>::const_iterator cur = classes_.find(name);
if (cur != classes_.end())
return cur->second;
// If this is a module scope, then look no further.
if (type_==MODULE)
return 0;
if (up_==0 && type_==CLASS) {
assert(class_def_);
@@ -722,16 +667,12 @@ netclass_t*NetScope::find_class(perm_string name)
return def_parent->find_class(name);
}
// If there is no further to look, ...
if (up_ == 0)
return 0;
// Try looking up for the class.
if (up_!=0 && type_!=MODULE)
return up_->find_class(name);
// Try the compilation unit.
if (unit_ != 0)
return unit_->find_class(name);
// Nowhere left to try...
return 0;
return up_->find_class(name);
}
/*
@@ -799,56 +740,7 @@ const NetScope* NetScope::child_byname(perm_string name) const
perm_string NetScope::local_symbol()
{
perm_string sym;
do {
ostringstream res;
res << "_ivl_" << (lcounter_++);
perm_string sym_tmp = lex_strings.make(res.str());
// If the name already exists as a signal, try again.
if (signals_map_.find(sym_tmp) != signals_map_.end())
continue;
// If the name already exists as a parameter, try again.
if (parameters.find(sym_tmp) != parameters.end())
continue;
if (genvars_.find(sym_tmp) != genvars_.end())
continue;
// If the name already exists as a class, try again.
if (classes_.find(sym_tmp) != classes_.end())
continue;
// No collisions, this is the one.
sym = sym_tmp;
} while (sym.nil());
return sym;
}
void NetScope::add_tie_hi(Design*des)
{
if (tie_hi_ == 0) {
NetNet*sig = new NetNet(this, lex_strings.make("_LOGIC1"),
NetNet::WIRE, &netvector_t::scalar_logic);
sig->local_flag(true);
tie_hi_ = new NetLogic(this, local_symbol(),
1, NetLogic::PULLUP, 1);
des->add_node(tie_hi_);
connect(sig->pin(0), tie_hi_->pin(0));
}
}
void NetScope::add_tie_lo(Design*des)
{
if (tie_lo_ == 0) {
NetNet*sig = new NetNet(this, lex_strings.make("_LOGIC0"),
NetNet::WIRE, &netvector_t::scalar_logic);
sig->local_flag(true);
tie_lo_ = new NetLogic(this, local_symbol(),
1, NetLogic::PULLDOWN, 1);
des->add_node(tie_lo_);
connect(sig->pin(0), tie_lo_->pin(0));
}
ostringstream res;
res << "_s" << (lcounter_++);
return lex_strings.make(res.str());
}
+2 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2017 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-2014 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
@@ -165,8 +165,7 @@ bool netclass_t::test_for_missing_initializers() const
NetScope*netclass_t::method_from_name(perm_string name) const
{
NetScope*task = class_scope_->child( hname_t(name) );
if ((task == 0) && super_)
task = super_->method_from_name(name);
if (task == 0) return 0;
return task;
}
+4 -12
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2020 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012 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
@@ -18,7 +18,6 @@
*/
# include "netdarray.h"
# include "netqueue.h"
# include <iostream>
using namespace std;
@@ -39,16 +38,9 @@ ivl_variable_type_t netdarray_t::base_type(void) const
bool netdarray_t::test_compatibility(ivl_type_t that) const
{
ivl_type_t elem_type = 0;
if (const netdarray_t*that_da = dynamic_cast<const netdarray_t*>(that))
elem_type = that_da->element_type();
if (const netqueue_t*that_q = dynamic_cast<const netqueue_t*>(that))
elem_type = that_q->element_type();
if (elem_type == 0)
const netdarray_t*that_da = dynamic_cast<const netdarray_t*>(that);
if (that_da == 0)
return false;
return element_type()->type_compatible(elem_type);
return element_type()->type_compatible(that_da->element_type());
}
+48 -743
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2020 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -24,7 +24,6 @@
# include <typeinfo>
# include <cstdlib>
# include <climits>
# include <cstring>
# include "compiler.h"
# include "netlist.h"
# include "netmisc.h"
@@ -176,7 +175,6 @@ bool NetPins::pins_are_virtual(void) const
NetPins::NetPins(unsigned npins)
: npins_(npins)
{
default_dir_ = Link::PASSIVE;
pins_ = NULL; // Wait until someone asks.
if (disable_virtual_pins) devirtualize_pins(); // Ask. Bummer.
}
@@ -309,12 +307,11 @@ unsigned NetBus::find_link(const Link&that) const
}
NetDelaySrc::NetDelaySrc(NetScope*s, perm_string n, unsigned npins,
bool condit_src, bool conditional, bool parallel)
bool condit_src, bool conditional)
: NetObj(s, n, npins + (condit_src?1:0))
{
condit_flag_ = false;
conditional_ = conditional;
parallel_ = parallel;
posedge_ = false;
negedge_ = false;
for (unsigned idx = 0 ; idx < npins ; idx += 1) {
@@ -473,11 +470,6 @@ const Link& NetDelaySrc::condit_pin() const
return pin(pin_count()-1);
}
bool NetDelaySrc::is_parallel() const
{
return parallel_;
}
PortType::Enum PortType::merged( Enum lhs, Enum rhs )
{
if( lhs == NOT_A_PORT || rhs == NOT_A_PORT )
@@ -565,7 +557,7 @@ void NetNet::calculate_slice_widths_from_packed_dims_(void)
ivl_assert(*this, ! slice_wids_.empty());
slice_wids_[0] = netrange_width(slice_dims_);
vector<netrange_t>::const_iterator cur = slice_dims_.begin();
for (size_t idx = 1 ; idx < slice_wids_.size() ; idx += 1, ++cur) {
for (size_t idx = 1 ; idx < slice_wids_.size() ; idx += 1) {
slice_wids_[idx] = slice_wids_[idx-1] / cur->width();
}
}
@@ -1029,36 +1021,11 @@ NetProc::~NetProc()
NetProcTop::NetProcTop(NetScope*s, ivl_process_type_t t, NetProc*st)
: type_(t), statement_(st), scope_(s)
{
synthesized_design_ = 0;
}
NetProcTop::~NetProcTop()
{
if (!synthesized_design_) {
delete statement_;
return;
}
NexusSet nex_set;
statement_->nex_output(nex_set);
delete statement_;
bool flag = false;
for (unsigned idx = 0 ; idx < nex_set.size() ; idx += 1) {
NetNet*net = nex_set[idx].lnk.nexus()->pick_any_net();
if (net->peek_lref() > 0) {
cerr << get_fileline() << ": warning: '" << net->name()
<< "' is driven by more than one process." << endl;
flag = true;
}
}
if (flag) {
cerr << get_fileline() << ": sorry: Cannot synthesize signals "
"that are driven by more than one process." << endl;
synthesized_design_->errors += 1;
}
}
NetProc* NetProcTop::statement()
@@ -1313,60 +1280,6 @@ const verinum& NetFF::sset_value() const
return sset_value_;
}
/*
* The NetLatch class represents an LPM_LATCH device. The pinout is assigned
* like so:
* 0 -- Enable
* 1 -- Data
* 2 -- Q
*/
NetLatch::NetLatch(NetScope*s, perm_string n, unsigned width__)
: NetNode(s, n, 3), width_(width__)
{
pin_Enable().set_dir(Link::INPUT);
pin_Data().set_dir(Link::INPUT);
pin_Q().set_dir(Link::OUTPUT);
}
NetLatch::~NetLatch()
{
}
unsigned NetLatch::width() const
{
return width_;
}
Link& NetLatch::pin_Enable()
{
return pin(0);
}
const Link& NetLatch::pin_Enable() const
{
return pin(0);
}
Link& NetLatch::pin_Data()
{
return pin(1);
}
const Link& NetLatch::pin_Data() const
{
return pin(1);
}
Link& NetLatch::pin_Q()
{
return pin(2);
}
const Link& NetLatch::pin_Q() const
{
return pin(2);
}
NetAbs::NetAbs(NetScope*s, perm_string n, unsigned w)
: NetNode(s, n, 2), width_(w)
@@ -2241,14 +2154,6 @@ ivl_variable_type_t NetEUFunc::expr_type() const
return IVL_VT_VOID;
}
const netenum_t* NetEUFunc::enumeration() const
{
if (result_sig_)
return result_sig_->enumeration();
return 0;
}
NetUTask::NetUTask(NetScope*def)
: task_(def)
{
@@ -2538,20 +2443,6 @@ NetETernary::~NetETernary()
delete false_val_;
}
const netenum_t* NetETernary::enumeration() const
{
// If the condition can evaluate to an ambiguous value,
// the result may be blended, and so is not guaranteed
// to be a valid enumeration value.
if (cond_->expr_type() != IVL_VT_BOOL)
return 0;
if (true_val_->enumeration() != false_val_->enumeration())
return 0;
return true_val_->enumeration();
}
const NetExpr* NetETernary::cond_expr() const
{
return cond_;
@@ -2797,7 +2688,7 @@ static DelayType delay_type_from_expr(const NetExpr*expr)
* The looping structures can use the same basic code so put it here
* instead of duplicating it for each one (repeat and while).
*/
static DelayType get_loop_delay_type(const NetExpr*expr, const NetProc*proc, bool print_delay)
static DelayType get_loop_delay_type(const NetExpr*expr, const NetProc*proc)
{
DelayType result;
@@ -2808,20 +2699,12 @@ static DelayType get_loop_delay_type(const NetExpr*expr, const NetProc*proc, boo
break;
/* We have a constant true expression so the body always runs. */
case DEFINITE_DELAY:
if (proc) {
result = proc->delay_type(print_delay);
} else {
result = NO_DELAY;
}
result = proc->delay_type();
break;
/* We don't know if the body will run so reduce a DEFINITE_DELAY
* to a POSSIBLE_DELAY. All other stay the same. */
case POSSIBLE_DELAY:
if (proc) {
result = combine_delays(NO_DELAY, proc->delay_type(print_delay));
} else {
result = NO_DELAY;
}
result = combine_delays(NO_DELAY, proc->delay_type());
break;
/* This should never happen since delay_type_from_expr() only
* returns three different values. */
@@ -2834,40 +2717,25 @@ static DelayType get_loop_delay_type(const NetExpr*expr, const NetProc*proc, boo
}
/* The default object does not have any delay. */
DelayType NetProc::delay_type(bool /* print_delay */ ) const
DelayType NetProc::delay_type() const
{
return NO_DELAY;
}
DelayType NetBlock::delay_type(bool print_delay) const
DelayType NetBlock::delay_type() const
{
// A join_none has no delay.
if (type() == PARA_JOIN_NONE) return NO_DELAY;
DelayType result = NO_DELAY;
DelayType result;
// A join_any has the minimum delay.
if (type() == PARA_JOIN_ANY) {
result = DEFINITE_DELAY;
for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
DelayType dt = cur->delay_type(print_delay);
if (dt < result) result = dt;
if ((dt == NO_DELAY) && !print_delay) break;
}
// A begin or join has the maximum delay.
} else {
result = NO_DELAY;
for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
DelayType dt = cur->delay_type(print_delay);
if (dt > result) result = dt;
if ((dt == DEFINITE_DELAY) && !print_delay) break;
}
for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
DelayType dt = cur->delay_type();
if (dt > result) result = dt;
if (dt == DEFINITE_DELAY) break;
}
return result;
}
DelayType NetCase::delay_type(bool print_delay) const
DelayType NetCase::delay_type() const
{
DelayType result = NO_DELAY;
bool def_stmt = false;
@@ -2875,7 +2743,7 @@ DelayType NetCase::delay_type(bool print_delay) const
for (unsigned idx = 0; idx < nstmts; idx += 1) {
if (!expr(idx)) def_stmt = true;
DelayType dt = stat(idx) ? stat(idx)->delay_type(print_delay) : NO_DELAY;
DelayType dt = stat(idx) ? stat(idx)->delay_type() : NO_DELAY;
if (idx == 0) {
result = dt;
} else {
@@ -2883,7 +2751,6 @@ DelayType NetCase::delay_type(bool print_delay) const
}
}
// FIXME: If all the cases are covered (e.g. an enum) then this is not true.
/* If we don't have a default statement we don't know for sure
* that we have a delay. */
if (!def_stmt) result = combine_delays(NO_DELAY, result);
@@ -2891,636 +2758,74 @@ DelayType NetCase::delay_type(bool print_delay) const
return result;
}
DelayType NetCondit::delay_type(bool print_delay) const
DelayType NetCondit::delay_type() const
{
DelayType if_type = if_ ? if_->delay_type(print_delay) : NO_DELAY;
DelayType el_type = else_? else_->delay_type(print_delay) : NO_DELAY;
DelayType if_type = if_ ? if_->delay_type() : NO_DELAY;
DelayType el_type = else_? else_->delay_type() : NO_DELAY;
return combine_delays(if_type, el_type);
}
/*
* A do/while will execute the body at least once.
*/
DelayType NetDoWhile::delay_type(bool print_delay) const
DelayType NetDoWhile::delay_type() const
{
if (proc_) return proc_->delay_type(print_delay);
return ZERO_DELAY;
ivl_assert(*this, proc_);
return proc_->delay_type();
}
DelayType NetEvWait::delay_type(bool print_delay) const
DelayType NetEvWait::delay_type() const
{
if (print_delay) {
cerr << get_fileline() << ": error: an event control is not allowed "
"in an always_comb, always_ff or always_latch process."
<< endl;
}
return DEFINITE_DELAY;
}
DelayType NetForever::delay_type(bool print_delay) const
DelayType NetForever::delay_type() const
{
if (statement_) return statement_->delay_type(print_delay);
return ZERO_DELAY;
ivl_assert(*this, statement_);
return statement_->delay_type();
}
DelayType NetForLoop::delay_type(bool print_delay) const
DelayType NetForLoop::delay_type() const
{
return get_loop_delay_type(condition_, statement_, print_delay);
ivl_assert(*this, statement_);
return get_loop_delay_type(condition_, statement_);
}
DelayType NetPDelay::delay_type(bool print_delay) const
DelayType NetPDelay::delay_type() const
{
if (print_delay) {
cerr << get_fileline() << ": error: a blocking delay is not allowed "
"in an always_comb, always_ff or always_latch process."
<< endl;
}
if (expr_) {
if (statement_) {
return combine_delays(delay_type_from_expr(expr_),
statement_->delay_type(print_delay));
return delay_type_from_expr(expr_);
} else {
if (delay() > 0) {
return DEFINITE_DELAY;
} else {
return delay_type_from_expr(expr_);
}
}
if (delay() > 0) return DEFINITE_DELAY;
if (statement_) {
return combine_delays(ZERO_DELAY,
statement_->delay_type(print_delay));
} else {
return ZERO_DELAY;
}
}
DelayType NetRepeat::delay_type(bool print_delay) const
{
return get_loop_delay_type(expr_, statement_, print_delay);
}
DelayType NetTaskDef::delay_type(bool print_delay) const
{
if (proc_) {
return proc_->delay_type(print_delay);
} else {
return NO_DELAY;
}
}
DelayType NetUTask::delay_type(bool print_delay) const
{
return task()->task_def()->delay_type(print_delay);
}
static bool do_expr_event_match(const NetExpr*expr, const NetEvWait*evwt)
{
// The event wait should only have a single event.
if (evwt->nevents() != 1) return false;
// The event should have a single probe.
const NetEvent *evt = evwt->event(0);
if (evt->nprobe() != 1) return false;
// The probe should be for any edge.
const NetEvProbe *prb = evt->probe(0);
if (prb->edge() != NetEvProbe::ANYEDGE) return false;
// Create a NexusSet from the event probe signals.
NexusSet *ns_evwt = new NexusSet;
for (unsigned idx =0; idx < prb->pin_count(); idx += 1) {
if (! prb->pin(idx).is_linked()) {
delete ns_evwt;
return false;
}
// Casting away const is safe since this nexus set is only being read.
ns_evwt->add(const_cast<Nexus*> (prb->pin(idx).nexus()),
0, prb->pin(idx).nexus()->vector_width());
}
// Get the NexusSet for the expression.
NexusSet *ns_expr = expr->nex_input();
// Make sure the event and expression NexusSets match exactly.
if (ns_evwt->size() != ns_expr->size()) {
delete ns_evwt;
delete ns_expr;
return false;
}
ns_expr->rem(*ns_evwt);
delete ns_evwt;
if (ns_expr->size() != 0) {
delete ns_expr;
return false;
}
delete ns_expr;
return true;
}
static bool while_is_wait(const NetExpr*expr, const NetProc*stmt)
{
if (const NetEvWait*evwt = dynamic_cast<const NetEvWait*>(stmt)) {
if (evwt->statement()) return false;
const NetEBComp*cond = dynamic_cast<const NetEBComp*>(expr);
if (! cond) return false;
if (cond->op() != 'N') return false;
const NetEConst*cval = dynamic_cast<const NetEConst*>(cond->right());
if (! cval) return false;
const verinum val = cval->value();
if (val.len() != 1) return false;
if (val.get(0) != verinum::V1) return false;
if (! do_expr_event_match(cond->left(), evwt)) return false;
if (evwt->get_lineno() != cond->get_lineno()) return false;
if (evwt->get_file() != cond->get_file()) return false;
return true;
}
return false;
}
DelayType NetWhile::delay_type(bool print_delay) const
{
// If the wait was a constant value the compiler already removed it
// so we know we can only have a possible delay.
if (while_is_wait(cond_, proc_)) {
if (print_delay) {
cerr << get_fileline() << ": error: a wait statement is "
"not allowed in an "
"always_comb, always_ff or always_latch process."
<< endl;
}
return POSSIBLE_DELAY;
}
return get_loop_delay_type(cond_, proc_, print_delay);
}
/*
* These are the check_synth() functions. They are used to print
* a warning if the item is not synthesizable.
*/
static const char * get_process_type_as_string(ivl_process_type_t pr_type)
{
switch (pr_type) {
case IVL_PR_ALWAYS_COMB:
return "in an always_comb process.";
break;
case IVL_PR_ALWAYS_FF:
return "in an always_ff process.";
break;
case IVL_PR_ALWAYS_LATCH:
return "in an always_latch process.";
break;
default:
assert(0);
return 0;
}
}
static void print_synth_warning(const NetProc *net_proc, const char *name,
ivl_process_type_t pr_type)
{
cerr << net_proc->get_fileline() << ": warning: " << name
<< " statement cannot be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
static void check_if_logic_l_value(const NetAssignBase *base,
ivl_process_type_t pr_type)
{
if (base->l_val_count() != 1) return;
const NetAssign_*lval = base->l_val(0);
if (! lval) return;
NetNet*sig = lval->sig();
if (! sig) return;
if ((sig->data_type() != IVL_VT_BOOL) &&
(sig->data_type() != IVL_VT_LOGIC)) {
cerr << base->get_fileline() << ": warning: Assinging to a "
"non-integral variable ("<< sig->name()
<< ") cannot be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
}
/* By default elements can be synthesized or ignored. */
bool NetProc::check_synth(ivl_process_type_t /* pr_type */,
const NetScope* /* scope */ ) const
{
return false;
}
// FIXME: User function calls still need to be checked (NetEUFunc).
// : Non-constant system functions need a warning (NetESFunc).
// : Constant functions should already be elaborated.
/* By default assign elements can be synthesized. */
bool NetAssignBase::check_synth(ivl_process_type_t /* pr_type */,
const NetScope* /* scope */ ) const
{
return false;
}
bool NetAssign::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */ ) const
{
check_if_logic_l_value(this, pr_type);
// FIXME: Check that ff/latch only use this for internal signals.
return false;
}
bool NetAssignNB::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */ ) const
{
bool result = false;
if (pr_type == IVL_PR_ALWAYS_COMB) {
cerr << get_fileline() << ": warning: A non-blocking assignment "
"should not be used in an always_comb process." << endl;
}
if (event_) {
cerr << get_fileline() << ": error: A non-blocking assignment "
"cannot be synthesized with an event control "
<< get_process_type_as_string(pr_type) << endl;
result = true;
}
check_if_logic_l_value(this, pr_type);
return result;
}
bool NetBlock::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
bool result = false;
// Only a begin/end can be synthesized.
if (type() != SEQU) {
cerr << get_fileline() << ": error: A fork/";
switch (type()) {
case PARA:
cerr << "join";
break;
case PARA_JOIN_ANY:
cerr << "join_any";
break;
case PARA_JOIN_NONE:
cerr << "join_none";
break;
default:
assert(0);
}
cerr << " statement cannot be synthesized "
<< get_process_type_as_string(pr_type) << endl;
result = true;
}
const NetScope*save_scope = scope;
if (subscope()) scope = subscope();
if (scope != save_scope) {
result |= scope->check_synth(pr_type, scope);
}
for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
result |= cur->check_synth(pr_type, scope);
}
scope = save_scope;
return result;
}
bool NetCase::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
bool result = false;
for (unsigned idx = 0; idx < nitems(); idx += 1) {
if (stat(idx)) result |= stat(idx)->check_synth(pr_type, scope);
}
// FIXME: Check for ff/latch/comb structures.
return result;
}
bool NetCAssign::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */ ) const
{
print_synth_warning(this, "A procedural assign", pr_type);
return false;
}
bool NetCondit::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
bool result = false;
if (if_) result |= if_->check_synth(pr_type, scope);
if (else_) result |= else_->check_synth(pr_type, scope);
// FIXME: Check for ff/latch/comb structures.
return result;
}
bool NetDeassign::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */ ) const
{
print_synth_warning(this, "A procedural deassign", pr_type);
return false;
}
bool NetDisable::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
while (scope) {
if (scope != target_) scope = scope->parent();
else break;
}
if (! scope) {
cerr << get_fileline() << ": warning: A disable statement can "
"only be synthesized when disabling an enclosing block "
<< get_process_type_as_string(pr_type) << endl;
}
return false;
}
bool NetDoWhile::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
bool result = false;
print_synth_warning(this, "A do/while", pr_type);
if (proc_) result |= proc_->check_synth(pr_type, scope);
return result;
}
bool NetEvTrig::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */ ) const
{
print_synth_warning(this, "An event trigger", pr_type);
return false;
}
// The delay check above has already marked this as an error.
bool NetEvWait::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
bool result = false;
if (statement_) result |= statement_->check_synth(pr_type, scope);
return result;
}
bool NetForce::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */ ) const
{
print_synth_warning(this, "A force", pr_type);
return false;
}
bool NetForever::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
bool result = false;
print_synth_warning(this, "A forever", pr_type);
if (statement_) result |= statement_->check_synth(pr_type, scope);
return result;
}
/*
* A bunch of private routines to verify that a for loop has the correct
* structure for synthesis.
*/
static void print_for_idx_warning(const NetProc*proc, const char*check,
ivl_process_type_t pr_type, NetNet*idx)
{
cerr << proc->get_fileline() << ": warning: A for statement must use "
"the index (" << idx->name() << ") in the " << check
<< " expression to be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
static void check_for_const_synth(const NetExpr*expr, const NetProc*proc,
const char*str, ivl_process_type_t pr_type)
{
if (! dynamic_cast<const NetEConst*>(expr)) {
cerr << proc-> get_fileline() << ": warning: A for "
"statement must " << str
<< " value to be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
}
static void check_for_bin_synth(const NetExpr*left,const NetExpr*right,
const char*str, const char*check,
const NetProc*proc,
ivl_process_type_t pr_type, NetNet*index)
{
const NetESignal*lsig = dynamic_cast<const NetESignal*>(left);
const NetESignal*rsig = dynamic_cast<const NetESignal*>(right);
if (lsig && (lsig->sig() == index)) {
check_for_const_synth(right, proc, str, pr_type);
} else if (rsig && (rsig->sig() == index)) {
check_for_const_synth(left, proc, str, pr_type);
} else {
print_for_idx_warning(proc, check, pr_type, index);
}
}
static void print_for_step_warning(const NetProc*proc,
ivl_process_type_t pr_type)
{
cerr << proc->get_fileline() << ": warning: A for statement step must "
"be a simple assignment statement to be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
static void print_for_step_warning(const NetProc*proc,
ivl_process_type_t pr_type, NetNet*idx)
{
cerr << proc->get_fileline() << ": warning: A for statement step must "
"be an assignment to the index variable ("
<< idx->name() << ") to be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
static void check_for_bstep_synth(const NetExpr*expr, const NetProc*proc,
ivl_process_type_t pr_type, NetNet*index)
{
if (const NetECast*tmp = dynamic_cast<const NetECast*>(expr)) {
expr = tmp->expr();
}
if (const NetEBAdd*tmp = dynamic_cast<const NetEBAdd*>(expr)) {
check_for_bin_synth(tmp->left(), tmp->right(),
"change by a constant", "step", proc, pr_type,
index);
} else {
cerr << proc->get_fileline() << ": warning: A for statement "
"step must be a simple binary +/- "
"to be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
}
static void check_for_step_synth(const NetAssign*assign, const NetProc*proc,
ivl_process_type_t pr_type, NetNet*index)
{
if (assign->l_val_count() != 1) {
print_for_step_warning(proc, pr_type);
} else if (assign->l_val(0)->sig() != index) {
print_for_step_warning(proc, pr_type, index);
} else {
switch (assign->assign_operator()) {
case '+':
case '-':
check_for_const_synth(assign->rval(), proc,
"have a constant step", pr_type);
break;
case 0:
check_for_bstep_synth(assign->rval(), proc, pr_type, index);
break;
default:
cerr << proc->get_fileline() << ": warning: A for statement "
"step does not support operator '"
<< assign->assign_operator()
<< "' it must be +/- to be synthesized "
<< get_process_type_as_string(pr_type) << endl;
break;
if (statement_) {
return statement_->delay_type();
} else {
return NO_DELAY;
}
}
}
}
bool NetForLoop::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
DelayType NetRepeat::delay_type() const
{
bool result = false;
// FIXME: What about an enum (NetEConstEnum)?
if (! dynamic_cast<const NetEConst*>(init_expr_)) {
cerr << get_fileline() << ": warning: A for statement must "
"have a constant initial value to be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
// FIXME: Do the following also need to be supported in the condition?
// It would seem like they are hard to use to find the bounds.
// From NetEBinary
// What about NetEBits sig & constant, etc.
// From NetEUnary
// What about NetEUBits ! sig or ! (sig == constat)
// What about NetEUReduce &signal
if (const NetESignal*tmp = dynamic_cast<const NetESignal*>(condition_)) {
if (tmp->sig() != index_) {
print_for_idx_warning(this, "condition", pr_type, index_);
}
} else if (const NetEBComp*cmp = dynamic_cast<const NetEBComp*>(condition_)) {
check_for_bin_synth(cmp->left(), cmp->right(),
"compare against a constant", "condition",
this, pr_type, index_);
} else {
print_for_idx_warning(this, "condition", pr_type, index_);
}
if (const NetAssign*tmp = dynamic_cast<const NetAssign*>(step_statement_)) {
check_for_step_synth(tmp, this, pr_type, index_);
} else {
print_for_step_warning(this, pr_type);
}
if (statement_) result |= statement_->check_synth(pr_type, scope);
return result;
ivl_assert(*this, statement_);
return get_loop_delay_type(expr_, statement_);
}
// The delay check above has already marked this as an error.
bool NetPDelay::check_synth(ivl_process_type_t /* pr_type */,
const NetScope* /* scope */ ) const
DelayType NetTaskDef::delay_type() const
{
return false;
return proc_->delay_type();
}
bool NetRelease::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */ ) const
DelayType NetUTask::delay_type() const
{
print_synth_warning(this, "A release", pr_type);
return false;
return task()->task_def()->delay_type();
}
bool NetRepeat::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
DelayType NetWhile::delay_type() const
{
bool result = false;
print_synth_warning(this, "A repeat", pr_type);
if (statement_) result |= statement_->check_synth(pr_type, scope);
return result;
}
bool NetScope::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */) const
{
bool result = false;
// Skip local events/signals
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_) {
if (cur->local_flag()) continue;
cerr << cur->get_fileline() << ": warning: An event ("
<< cur->name() << ") cannot be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
for (signals_map_iter_t cur = signals_map_.begin();
cur != signals_map_.end() ; ++ cur) {
const NetNet*sig = cur->second;
if ((sig->data_type() != IVL_VT_BOOL) &&
(sig->data_type() != IVL_VT_LOGIC)) {
cerr << sig->get_fileline() << ": warning: A non-integral "
"variable (" << sig->name() << ") cannot be "
"synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
}
return result;
}
bool NetSTask::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */) const
{
if (strcmp(name(), "$ivl_darray_method$delete") == 0) {
cerr << get_fileline() << ": warning: Dynamic array "
"delete method cannot be synthesized "
<< get_process_type_as_string(pr_type) << endl;
} else {
cerr << get_fileline() << ": warning: System task ("
<< name() << ") cannot be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
return false;
}
bool NetTaskDef::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */) const
{
bool result = false;
const NetScope *tscope = this->scope();
result |= tscope->check_synth(pr_type, tscope);
if (! tscope->is_auto()) {
cerr << tscope->get_def_file() << ":"
<< tscope->get_def_lineno()
<< ": warning: user task (" << tscope->basename()
<< ") must be automatic to be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
if (proc_) result |= proc_->check_synth(pr_type, tscope);
return result;
}
bool NetUTask::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
return task()->task_def()->check_synth(pr_type, scope);
}
bool NetWhile::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
bool result = false;
// A wait is already maked as an error in the delay check above.
if (! while_is_wait(cond_, proc_)) {
print_synth_warning(this, "A while", pr_type);
if (proc_) result |= proc_->check_synth(pr_type, scope);
}
return result;
ivl_assert(*this, proc_);
return get_loop_delay_type(cond_, proc_);
}
+128 -346
View File
File diff suppressed because it is too large Load Diff
+62 -250
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2020 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2014 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
@@ -158,7 +158,7 @@ NetExpr* cast_to_int2(NetExpr*expr, unsigned width)
NetExpr* cast_to_int4(NetExpr*expr, unsigned width)
{
// Special case: The expression is already LOGIC or BOOL
if (expr->expr_type() == IVL_VT_LOGIC || expr->expr_type() == IVL_VT_BOOL)
if (expr->expr_type() != IVL_VT_REAL)
return expr;
if (debug_elaborate)
@@ -203,7 +203,7 @@ static NetExpr* make_add_expr(NetExpr*expr, long val)
}
verinum val_v (val, expr->expr_width());
val_v.has_sign(expr->has_sign());
val_v.has_sign(true);
NetEConst*val_c = new NetEConst(val_v);
val_c->set_line(*expr);
@@ -236,7 +236,7 @@ static NetExpr* make_add_expr(const LineInfo*loc, NetExpr*expr1, NetExpr*expr2)
static NetExpr* make_sub_expr(long val, NetExpr*expr)
{
verinum val_v (val, expr->expr_width());
val_v.has_sign(expr->has_sign());
val_v.has_sign(true);
NetEConst*val_c = new NetEConst(val_v);
val_c->set_line(*expr);
@@ -249,26 +249,7 @@ static NetExpr* make_sub_expr(long val, NetExpr*expr)
}
/*
* Subtract a signed constant from an existing expression.
*/
static NetExpr* make_sub_expr(NetExpr*expr, long val)
{
verinum val_v (val, expr->expr_width());
val_v.has_sign(expr->has_sign());
NetEConst*val_c = new NetEConst(val_v);
val_c->set_line(*expr);
NetEBAdd*res = new NetEBAdd('-', expr, val_c, expr->expr_width(),
expr->has_sign());
res->set_line(*expr);
return res;
}
/*
* Multiply an existing expression by a signed positive number.
* Multiple an existing expression by a signed positive number.
* This does a lossless multiply, so the arguments will need to be
* sized to match the output size.
*/
@@ -277,7 +258,7 @@ static NetExpr* make_mult_expr(NetExpr*expr, unsigned long val)
const unsigned val_wid = ceil(log2((double)val)) ;
unsigned use_wid = expr->expr_width() + val_wid;
verinum val_v (val, use_wid);
val_v.has_sign(expr->has_sign());
val_v.has_sign(true);
NetEConst*val_c = new NetEConst(val_v);
val_c->set_line(*expr);
@@ -453,41 +434,17 @@ NetExpr *normalize_variable_slice_base(const list<long>&indices, NetExpr*base,
-- pcur;
}
long sb = min(pcur->get_lsb(), pcur->get_msb());
long sb;
if (pcur->get_msb() >= pcur->get_lsb())
sb = pcur->get_lsb();
else
sb = pcur->get_msb();
long loff;
reg->sb_to_slice(indices, sb, loff, lwid);
unsigned min_wid = base->expr_width();
if ((sb < 0) && !base->has_sign()) min_wid += 1;
if (min_wid < num_bits(pcur->get_lsb())) min_wid = pcur->get_lsb();
if (min_wid < num_bits(pcur->get_msb())) min_wid = pcur->get_msb();
base = pad_to_width(base, min_wid, *base);
if ((sb < 0) && !base->has_sign()) {
NetESelect *tmp = new NetESelect(base, 0 , min_wid);
tmp->set_line(*base);
tmp->cast_signed(true);
base = tmp;
}
if (pcur->get_msb() >= pcur->get_lsb()) {
if (pcur->get_lsb() != 0)
base = make_sub_expr(base, pcur->get_lsb());
base = make_mult_expr(base, lwid);
min_wid = base->expr_width();
if (min_wid < num_bits(loff)) min_wid = num_bits(loff);
if (loff != 0) min_wid += 1;
base = pad_to_width(base, min_wid, *base);
base = make_add_expr(base, loff);
} else {
if (pcur->get_msb() != 0)
base = make_sub_expr(base, pcur->get_msb());
base = make_mult_expr(base, lwid);
min_wid = base->expr_width();
if (min_wid < num_bits(loff)) min_wid = num_bits(loff);
if (loff != 0) min_wid += 1;
base = pad_to_width(base, min_wid, *base);
base = make_sub_expr(loff, base);
}
base = make_mult_expr(base, lwid);
base = make_add_expr(base, loff);
return base;
}
@@ -845,10 +802,9 @@ NetExpr* condition_reduce(NetExpr*expr)
}
static NetExpr* do_elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
int context_width, bool need_const,
bool annotatable, bool force_expand,
ivl_variable_type_t cast_type,
bool force_unsigned)
int context_width, bool need_const, bool annotatable,
bool force_expand,
ivl_variable_type_t cast_type)
{
PExpr::width_mode_t mode = PExpr::SIZED;
if ((context_width == -2) && !gn_strict_expr_width_flag)
@@ -868,11 +824,6 @@ static NetExpr* do_elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
if ((pe->expr_type() != IVL_VT_REAL) && (expr_width < pos_context_width))
expr_width = pos_context_width;
// If this is the RHS of a compressed assignment, the LHS also
// affects the expression type (signed/unsigned).
if (force_unsigned)
pe->cast_signed(false);
if (debug_elaborate) {
cerr << pe->get_fileline() << ": elab_and_eval: test_width of "
<< *pe << endl;
@@ -925,19 +876,6 @@ static NetExpr* do_elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
if (tmp == 0) return 0;
if ((cast_type != IVL_VT_NO_TYPE) && (cast_type != tmp->expr_type())) {
switch (tmp->expr_type()) {
case IVL_VT_BOOL:
case IVL_VT_LOGIC:
case IVL_VT_REAL:
break;
default:
cerr << tmp->get_fileline() << ": error: "
"The expression '" << *pe << "' cannot be implicitly "
"cast to the target type." << endl;
des->errors += 1;
delete tmp;
return 0;
}
switch (cast_type) {
case IVL_VT_REAL:
tmp = cast_to_real(tmp);
@@ -972,16 +910,15 @@ static NetExpr* do_elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
int context_width, bool need_const, bool annotatable,
ivl_variable_type_t cast_type, bool force_unsigned)
ivl_variable_type_t cast_type)
{
return do_elab_and_eval(des, scope, pe, context_width,
need_const, annotatable, false,
cast_type, force_unsigned);
need_const, annotatable, false, cast_type);
}
/*
* This variant of elab_and_eval does the expression losslessly, no
* matter what the generation of Verilog. This is in support of
* matter what the generation of verilog. This is in support of
* certain special contexts, notably index expressions.
*/
NetExpr* elab_and_eval_lossless(Design*des, NetScope*scope, PExpr*pe,
@@ -989,8 +926,7 @@ NetExpr* elab_and_eval_lossless(Design*des, NetScope*scope, PExpr*pe,
ivl_variable_type_t cast_type)
{
return do_elab_and_eval(des, scope, pe, context_width,
need_const, annotatable, true,
cast_type, false);
need_const, annotatable, true, cast_type);
}
NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
@@ -1009,41 +945,6 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
flags |= PExpr::NEED_CONST;
NetExpr*tmp = pe->elaborate_expr(des, scope, lv_net_type, flags);
if (tmp == 0) return 0;
ivl_variable_type_t cast_type = ivl_type_base(lv_net_type);
if ((cast_type != IVL_VT_NO_TYPE) && (cast_type != tmp->expr_type())) {
// Catch some special cases.
switch (cast_type) {
case IVL_VT_DARRAY:
case IVL_VT_QUEUE:
if (NetESignal*net = dynamic_cast<NetESignal*>(tmp)) {
ivl_variable_type_t type = net->expr_type();
if ((type == IVL_VT_DARRAY) || (type == IVL_VT_QUEUE))
return tmp;
}
if (dynamic_cast<PEAssignPattern*>(pe))
return tmp;
// fall through
case IVL_VT_STRING:
if (dynamic_cast<PEConcat*>(pe))
return tmp;
break;
case IVL_VT_CLASS:
if (dynamic_cast<PENull*>(pe))
return tmp;
break;
default:
break;
}
cerr << tmp->get_fileline() << ": error: "
"The expression '" << *pe << "' cannot be implicitly "
"cast to the target type." << endl;
des->errors += 1;
delete tmp;
return 0;
}
return tmp;
}
@@ -1085,94 +986,50 @@ NetExpr* elab_sys_task_arg(Design*des, NetScope*scope, perm_string name,
return tmp;
}
bool evaluate_range(Design*des, NetScope*scope, const LineInfo*li,
const pform_range_t&range, long&index_l, long&index_r)
{
bool dimension_ok = true;
// Unsized and queue dimensions should be handled before calling
// this function. If we find them here, we are in a context where
// they are not allowed.
if (range.first == 0) {
cerr << li->get_fileline() << ": error: "
"An unsized dimension is not allowed here." << endl;
dimension_ok = false;
des->errors += 1;
} else if (dynamic_cast<PENull*>(range.first)) {
cerr << li->get_fileline() << ": error: "
"A queue dimension is not allowed here." << endl;
dimension_ok = false;
des->errors += 1;
} else {
NetExpr*texpr = elab_and_eval(des, scope, range.first, -1, true);
if (! eval_as_long(index_l, texpr)) {
cerr << range.first->get_fileline() << ": error: "
"Dimensions must be constant." << endl;
cerr << range.first->get_fileline() << " : "
<< (range.second ? "This MSB" : "This size")
<< " expression violates the rule: "
<< *range.first << endl;
dimension_ok = false;
des->errors += 1;
}
delete texpr;
if (range.second == 0) {
// This is a SystemVerilog [size] dimension. The IEEE
// standard does not allow this in a packed dimension,
// but we do. At least one commercial simulator does too.
if (!dimension_ok) {
// bail out
} else if (index_l > 0) {
index_l = index_l - 1;
index_r = 0;
} else {
cerr << range.first->get_fileline() << ": error: "
"Dimension size must be greater than zero." << endl;
cerr << range.first->get_fileline() << " : "
"This size expression violates the rule: "
<< *range.first << endl;
dimension_ok = false;
des->errors += 1;
}
} else {
texpr = elab_and_eval(des, scope, range.second, -1, true);
if (! eval_as_long(index_r, texpr)) {
cerr << range.second->get_fileline() << ": error: "
"Dimensions must be constant." << endl;
cerr << range.second->get_fileline() << " : "
"This LSB expression violates the rule: "
<< *range.second << endl;
dimension_ok = false;
des->errors += 1;
}
delete texpr;
}
}
/* Error recovery */
if (!dimension_ok) {
index_l = 0;
index_r = 0;
}
return dimension_ok;
}
bool evaluate_ranges(Design*des, NetScope*scope, const LineInfo*li,
bool evaluate_ranges(Design*des, NetScope*scope,
vector<netrange_t>&llist,
const list<pform_range_t>&rlist)
{
bool dimensions_ok = true;
bool bad_msb = false, bad_lsb = false;
for (list<pform_range_t>::const_iterator cur = rlist.begin()
; cur != rlist.end() ; ++cur) {
long index_l, index_r;
dimensions_ok &= evaluate_range(des, scope, li, *cur, index_l, index_r);
llist.push_back(netrange_t(index_l, index_r));
long use_msb, use_lsb;
NetExpr*texpr = elab_and_eval(des, scope, cur->first, -1, true);
if (! eval_as_long(use_msb, texpr)) {
cerr << cur->first->get_fileline() << ": error: "
"Range expressions must be constant." << endl;
cerr << cur->first->get_fileline() << " : "
"This MSB expression violates the rule: "
<< *cur->first << endl;
des->errors += 1;
bad_msb = true;
}
delete texpr;
texpr = elab_and_eval(des, scope, cur->second, -1, true);
if (! eval_as_long(use_lsb, texpr)) {
cerr << cur->second->get_fileline() << ": error: "
"Range expressions must be constant." << endl;
cerr << cur->second->get_fileline() << " : "
"This LSB expression violates the rule: "
<< *cur->second << endl;
des->errors += 1;
bad_lsb = true;
}
delete texpr;
/* Error recovery */
if (bad_lsb) use_lsb = 0;
if (bad_msb) use_msb = use_lsb;
llist.push_back(netrange_t(use_msb, use_lsb));
}
return dimensions_ok;
return bad_msb | bad_lsb;
}
void eval_expr(NetExpr*&expr, int context_width)
@@ -1341,11 +1198,9 @@ const char *human_readable_op(const char op, bool unary)
case '|': type = "|"; break; // Bitwise OR
case 'O': type = "~|"; break; // NOR
case '!': type = "!"; break; // Logical NOT
case 'a': type = "&&"; break; // Logical AND
case 'o': type = "||"; break; // Logical OR
case 'q': type = "->"; break; // Logical implication
case 'Q': type = "<->"; break; // Logical equivalence
case '!': type = "!"; break; // Logical NOT
case 'a': type = "&&"; break; // Logical AND
case 'o': type = "||"; break; // Logical OR
case 'e': type = "=="; break;
case 'n': type = "!="; break;
@@ -1354,8 +1209,6 @@ const char *human_readable_op(const char op, bool unary)
if (unary) type = "~|"; // NOR
else type = "!=="; // Case inequality
break;
case 'w': type = "==?"; break; // Wild equality
case 'W': type = "!=?"; break; // Wild inequality
case 'l': type = "<<(<)"; break; // Left shifts
case 'r': type = ">>"; break; // Logical right shift
@@ -1540,13 +1393,7 @@ bool evaluate_index_prefix(Design*des, NetScope*scope,
list<index_component_t>::const_iterator icur = indices.begin();
for (size_t idx = 0 ; (idx+1) < indices.size() ; idx += 1, ++icur) {
assert(icur != indices.end());
if (icur->sel != index_component_t::SEL_BIT) {
cerr << icur->msb->get_fileline() << ": error: "
"All but the final index in a chain of indices must be "
"a single value, not a range." << endl;
des->errors += 1;
return false;
}
assert(icur->sel == index_component_t::SEL_BIT);
NetExpr*texpr = elab_and_eval(des, scope, icur->msb, -1, true);
long tmp;
@@ -1557,7 +1404,7 @@ bool evaluate_index_prefix(Design*des, NetScope*scope,
return false;
}
prefix_indices.push_back(tmp);
prefix_indices .push_back(tmp);
delete texpr;
}
@@ -1767,38 +1614,3 @@ NetScope* find_method_containing_scope(const LineInfo&, NetScope*scope)
return scope;
}
/*
* Print a warning if we find a mixture of default and explicit timescale
* based delays in the design, since this is likely an error.
*/
void check_for_inconsistent_delays(NetScope*scope)
{
static bool used_implicit_timescale = false;
static bool used_explicit_timescale = false;
static bool display_ts_dly_warning = true;
if (scope->time_from_timescale())
used_explicit_timescale = true;
else
used_implicit_timescale = true;
if (display_ts_dly_warning &&
used_explicit_timescale &&
used_implicit_timescale) {
if (gn_system_verilog()) {
cerr << "warning: Found both default and explicit "
"timescale based delays. Use" << endl;
cerr << " : -Wtimescale to find the design "
"element(s) with no explicit" << endl;
cerr << " : timescale." << endl;
} else {
cerr << "warning: Found both default and "
"`timescale based delays. Use" << endl;
cerr << " : -Wtimescale to find the "
"module(s) with no `timescale." << endl;
}
display_ts_dly_warning = false;
}
}
+14 -42
View File
@@ -1,7 +1,7 @@
#ifndef IVL_netmisc_H
#define IVL_netmisc_H
/*
* Copyright (c) 1999-2019 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2014 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
@@ -60,32 +60,12 @@ inline NetScope* symbol_search(const LineInfo*li,
}
/*
* This function transforms an expression by either zero or sign extending
* the high bits until the expression has the desired width. This may mean
* not transforming the expression at all, if it is already wide enough.
* The extension method and the returned expression type is determined by
* signed_flag.
* This function transforms an expression by padding the high bits
* with V0 until the expression has the desired width. This may mean
* not transforming the expression at all, if it is already wide
* enough.
*/
extern NetExpr*pad_to_width(NetExpr*expr, unsigned wid, bool signed_flag,
const LineInfo&info);
/*
* This version determines the extension method from the base expression type.
*/
inline NetExpr*pad_to_width(NetExpr*expr, unsigned wid, const LineInfo&info)
{
return pad_to_width(expr, wid, expr->has_sign(), info);
}
/*
* This function transforms an expression by either zero or sign extending
* or discarding the high bits until the expression has the desired width.
* This may mean not transforming the expression at all, if it is already
* the correct width. The extension method (if needed) and the returned
* expression type is determined by signed_flag.
*/
extern NetExpr*cast_to_width(NetExpr*expr, unsigned wid, bool signed_flag,
const LineInfo&info);
extern NetExpr*pad_to_width(NetExpr*expr, unsigned wid, const LineInfo&info);
extern NetNet*pad_to_width(Design*des, NetNet*n, unsigned w,
const LineInfo&info);
@@ -175,7 +155,7 @@ extern NetExpr*normalize_variable_slice_base(const list<long>&indices, NetExpr *
* index values in the form [<>][<>]....
*/
template <class TYPE> struct __IndicesManip {
explicit inline __IndicesManip(const std::list<TYPE>&v) : val(v) { }
inline __IndicesManip(const std::list<TYPE>&v) : val(v) { }
const std::list<TYPE>&val;
};
template <class TYPE> inline __IndicesManip<TYPE> as_indices(const std::list<TYPE>&indices)
@@ -278,8 +258,7 @@ extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
PExpr*pe, int context_width,
bool need_const =false,
bool annotatable =false,
ivl_variable_type_t cast_type =IVL_VT_NO_TYPE,
bool force_unsigned =false);
ivl_variable_type_t cast_type =IVL_VT_NO_TYPE);
extern NetExpr* elab_and_eval_lossless(Design*des, NetScope*scope,
PExpr*pe, int context_width,
@@ -318,14 +297,9 @@ extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
ivl_type_t lv_net_type,
ivl_variable_type_t lv_type,
unsigned lv_width, PExpr*expr,
bool need_const =false,
bool force_unsigned =false);
bool need_const =false);
extern bool evaluate_range(Design*des, NetScope*scope, const LineInfo*li,
const pform_range_t&range,
long&index_l, long&index_r);
extern bool evaluate_ranges(Design*des, NetScope*scope, const LineInfo*li,
extern bool evaluate_ranges(Design*des, NetScope*scope,
std::vector<netrange_t>&llist,
const std::list<pform_range_t>&rlist);
/*
@@ -382,6 +356,10 @@ const char *human_readable_op(const char op, bool unary = false);
enum const_bool { C_NON, C_0, C_1, C_X };
const_bool const_logical(const NetExpr*expr);
extern bool dly_used_no_timescale;
extern bool dly_used_timescale;
extern bool display_ts_dly_warning;
/*
* When scaling a real value to a time we need to do some standard
* processing.
@@ -409,10 +387,4 @@ extern void assign_unpacked_with_bufz(Design*des, NetScope*scope,
extern NetPartSelect* detect_partselect_lval(Link&pin);
/*
* Print a warning if we find a mixture of default and explicit timescale
* based delays in the design, since this is likely an error.
*/
extern void check_for_inconsistent_delays(NetScope*scope);
#endif /* IVL_netmisc_H */
+6 -13
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2020 Stephen Williams (steve@icarus.com)
* Copyright (c) 2014 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
@@ -22,8 +22,8 @@
using namespace std;
netqueue_t::netqueue_t(ivl_type_t vec, long max_idx)
: netdarray_t(vec), max_idx_(max_idx)
netqueue_t::netqueue_t(ivl_type_t vec)
: netdarray_t(vec)
{
}
@@ -38,16 +38,9 @@ ivl_variable_type_t netqueue_t::base_type() const
bool netqueue_t::test_compatibility(ivl_type_t that) const
{
ivl_type_t elem_type = 0;
if (const netqueue_t*that_q = dynamic_cast<const netqueue_t*>(that))
elem_type = that_q->element_type();
if (const netdarray_t*that_da = dynamic_cast<const netdarray_t*>(that))
elem_type = that_da->element_type();
if (elem_type == 0)
const netqueue_t*that_q = dynamic_cast<const netqueue_t*>(that);
if (that_q == 0)
return false;
return element_type()->type_compatible(elem_type);
return element_type()->type_compatible(that_q->element_type());
}
+2 -8
View File
@@ -1,7 +1,7 @@
#ifndef IVL__netqueue_H
#define IVL__netqueue_H
/*
* Copyright (c) 2014-2020 Stephen Williams (steve@icarus.com)
* Copyright (c) 2014-2015 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -30,7 +30,7 @@
class netqueue_t : public netdarray_t {
public:
explicit netqueue_t(ivl_type_t vec, long max_idx);
explicit netqueue_t(ivl_type_t vec);
~netqueue_t();
// This is the "base_type()" virtual method of the
@@ -41,16 +41,10 @@ class netqueue_t : public netdarray_t {
// A queue may have a type that is signed.
inline bool get_signed() const { return element_type()->get_signed(); }
// Use the packed width to pass the element width
long packed_width(void) const { return element_type()->packed_width(); }
long max_idx(void) const { return max_idx_; }
std::ostream& debug_dump(std::ostream&) const;
private:
bool test_compatibility(ivl_type_t that) const;
long max_idx_;
};
#endif
+3 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-2013 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
@@ -147,12 +147,13 @@ bool prefix_to_slice(const std::vector<netrange_t>&dims,
do {
-- icur;
acc_wid *= pcur->width();
-- pcur;
if (pcur->get_msb() >= pcur->get_lsb())
acc_off += (*icur - pcur->get_lsb()) * acc_wid;
else
acc_off += (pcur->get_lsb() - *icur) * acc_wid;
-- pcur;
} while (icur != prefix.begin());
// Got our final offset.
-53
View File
@@ -122,63 +122,10 @@ void nodangle_f::event(Design*, NetEvent*ev)
}
}
static bool floating_net_tested(NetNet*sig)
{
static set<NetNet*> tested_set;
pair< set<NetNet*>::iterator, bool > cur = tested_set.insert(sig);
return !cur.second;
}
static void check_is_floating(NetNet*sig)
{
// Some signal types are implicitly driven if nothing else.
if (sig->type() == NetNet::SUPPLY0) return;
if (sig->type() == NetNet::SUPPLY1) return;
if (sig->type() == NetNet::TRI0) return;
if (sig->type() == NetNet::TRI1) return;
if (sig->type() == NetNet::IMPLICIT_REG) return;
if (sig->type() == NetNet::REG) return ;
// Assignments drive a signal.
if (sig->peek_lref() > 0) return;
for (unsigned idx = 0 ; idx < sig->pin_count() ; idx += 1) {
if (sig->pin(idx).get_dir() == Link::OUTPUT)
continue;
if (sig->pin(idx).nexus()->drivers_present())
continue;
if (sig->port_type() == PortType::NOT_A_PORT && sig->pin_count()==1) {
cerr << sig->get_fileline() << ": warning: "
<< "Signal " << scope_path(sig->scope())
<< "." << sig->name()
<< " has no drivers." << endl;
} else if (sig->port_type()==PortType::NOT_A_PORT) {
cerr << sig->get_fileline() << ": warning: "
<< "Signal " << scope_path(sig->scope())
<< "." << sig->name()
<< "[" << idx << "]"
<< " has no drivers." << endl;
} else {
cerr << sig->get_fileline() << ": warning: "
<< "Port " << sig->name()
<< " of " << scope_path(sig->scope())
<< " has no drivers." << endl;
}
}
}
void nodangle_f::signal(Design*, NetNet*sig)
{
if (scomplete) return;
if (warn_floating_nets && !sig->local_flag() && !floating_net_tested(sig)) {
check_is_floating(sig);
}
/* Cannot delete signals referenced in an expression
or an l-value. */
if (sig->get_refs() > 0)
+11 -32
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2011 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
@@ -24,20 +24,21 @@
# include "netmisc.h"
NetExpr*pad_to_width(NetExpr*expr, unsigned wid, bool signed_flag,
const LineInfo&info)
/*
* This function transforms an expression by padding the high bits
* with V0 until the expression has the desired width. This may mean
* not transforming the expression at all, if it is already wide
* enough.
*/
NetExpr*pad_to_width(NetExpr*expr, unsigned wid, const LineInfo&info)
{
if (wid <= expr->expr_width()) {
expr->cast_signed(signed_flag);
if (wid <= expr->expr_width())
return expr;
}
/* If the expression is a const, then replace it with a wider
const. This is a more efficient result. */
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
verinum oval = tmp->value();
oval.has_sign(signed_flag);
oval = pad_to_width(oval, wid);
verinum oval = pad_to_width(tmp->value(), wid);
tmp = new NetEConst(oval);
tmp->set_line(info);
delete expr;
@@ -45,30 +46,8 @@ NetExpr*pad_to_width(NetExpr*expr, unsigned wid, bool signed_flag,
}
NetESelect*tmp = new NetESelect(expr, 0, wid);
tmp->cast_signed(signed_flag);
tmp->set_line(info);
return tmp;
}
NetExpr*cast_to_width(NetExpr*expr, unsigned wid, bool signed_flag,
const LineInfo&info)
{
/* If the expression is a const, then replace it with a new
const. This is a more efficient result. */
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
tmp->cast_signed(signed_flag);
if (wid != tmp->expr_width()) {
tmp = new NetEConst(verinum(tmp->value(), wid));
tmp->set_line(info);
delete expr;
}
return tmp;
}
NetESelect*tmp = new NetESelect(expr, 0, wid);
tmp->cast_signed(signed_flag);
tmp->set_line(info);
tmp->cast_signed(expr->has_sign());
return tmp;
}

Some files were not shown because too many files have changed in this diff Show More