Compare commits

..
Author SHA1 Message Date
Stephen Williams afa2478801 Merge branch 'master' of ssh://[email protected]/home/u/icarus/steve/git/verilog 2008-06-09 16:58:21 -07:00
Stephen Williams 79feb44f10 Turn of concat output scheduling.
We really want lazy processing of concatenation because it has multiple
inputs and lazy processing should (in theory) prevent redundant and
useless propagations through the net.

But enabling it seems to cause many tests in the regression test suite
to fail to compare their results. There are races in many tests that
are interacting badly with this feature. So for now, ifdef it out.
2008-06-09 16:57:51 -07:00
Stephen Williams c03d76a0d7 Do not do lazy processing of part selects.
It doesn't really make any sense to do lazy processing of part selects,
but it is possible to use the part select position to more toroughly
check for changes in output and suppress non-changes. In particular,
we only need to check that the output part actually changes, and by the
way we only need to save those bits for the next go-round.

We do want to make sure that the very first input causes an output,
though, so that time-0 values get propagated.
2008-06-09 16:46:06 -07:00
Stephen Williams d0f303463d ASSIGN transfer data to scheduler efficiently/permalloc vvp_net_t objects.
The vvp_net_t objects are never deleted, so overload the new operator
to do a more space efficient permanent allocation.

The %assign/v instruction copied the vvp_vector4_t object needlessly
on its way to the scheduler. Eliminate that duplication.
2008-06-06 19:50:44 -07:00
Stephen Williams 35fe8fae00 Have vvp_vector8_t avoid allocating tiny scalar arrays. 2008-06-06 16:36:43 -07:00
Stephen Williams 2e95a740da Rework scheduling of concat, part, buf/not and resolv for efficiency.
The concat and resolv functors are best evaluated lazily, because each
evaluation is costly and there is a high probability that an evaluation
will be invalidated when new input comes in.

Also optimization the recv_vec4_pv method of the resolver, which is
commonly used, and adjust the order of handling of vvp_fun_part to
work more efficiently.
2008-06-06 15:31:22 -07:00
Stephen Williams 2f4e5bf5b6 Obvious optimizations of vvp_vector8_t handling.
The vvp_vector8_t constructor and destructor involve memory allocation
so it is best to pass these objects by reference as much as possible.

Also rework the resolver functor to only perform resolution after inputs
are in so that it doesn't get needlessly repeated. This eliminates many
resolve function calls, as well as activations throughout the net.

Also have the islands take more care not to perform resolution if the
inputs aren't really different.
2008-06-06 11:12:07 -07:00
310 changed files with 16696 additions and 24186 deletions
-37
View File
@@ -1,37 +0,0 @@
/*
* Copyright (c) 2008 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
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "config.h"
# include "AStatement.h"
AContrib::AContrib(PExpr*lv, PExpr*rv)
: lval_(lv), rval_(rv)
{
}
AContrib::~AContrib()
{
delete lval_;
delete rval_;
}
AProcess::~AProcess()
{
}
-85
View File
@@ -1,85 +0,0 @@
#ifndef __AStatement_H
#define __AStatement_H
/*
* Copyright (c) 2008 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
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include <map>
# include "ivl_target.h"
# include "StringHeap.h"
# include "LineInfo.h"
# include "Statement.h"
# include "PExpr.h"
class PExpr;
class NetAnalog;
class NetScope;
class Design;
/*
* A contribution statement is like an assignment: there is an l-value
* expression and an r-value expression. The l-value is a branch probe
* expression.
*/
class AContrib : public Statement {
public:
AContrib(PExpr*lval, PExpr*rval);
~AContrib();
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
private:
PExpr*lval_;
PExpr*rval_;
};
/*
* An analog process is not a statement, but contains an analog
* statement. The process is where we attach process characteristics
* such as initial vs. always, attributes....
*/
class AProcess : public LineInfo {
public:
AProcess(ivl_process_type_t t, Statement*st)
: type_(t), statement_(st) { }
~AProcess();
bool elaborate(Design*des, NetScope*scope) const;
ivl_process_type_t type() const { return type_; }
Statement*statement() { return statement_; }
map<perm_string,PExpr*> attributes;
// Dump the analog process
void dump(ostream&out, unsigned ind) const;
private:
ivl_process_type_t type_;
Statement*statement_;
private: // not implemented
AProcess(const AProcess&);
AProcess& operator= (const AProcess&);
};
#endif
+68 -62
View File
@@ -4,24 +4,23 @@ HOW TO REPORT BUGS
Before I can fix an error, I need to understand what the problem
is. Try to explain what is wrong and why you think it is wrong. Please
try to include sample code that demonstrates the problem. Include a
description of what Icarus Verilog does that is wrong, and what you
expect should happen. And include the command line flags passed to the
compiler to make the error happen. (This is often overlooked, and
sometimes important.)
description of what ivl does that is wrong, and what you expect should
happen. And include the command line flags passed to the compiler to make
the error happen. (This is often overlooked, and sometimes important.)
* The Compiler Doesn't Compile
If Icarus Verilog doesn't compile, I need to know about the
If the Icarus Verilog don't compile, I need to know about the
compilation tools you are using. Specifically, I need to know:
- Operating system and processor type,
- Compiler w/ version,
- Versions of any libraries being linked, and
- Library version, and
- anything else you think relevant.
Be aware that I do not have at my disposal a porting lab. I have the
workstation on my desk, a Mac laptop, and the Linux/Intel box with a
logic analyzer and 'scope hanging off it.
alpha on my desk, and the Linux/Intel box with a logic analyzer and
'scope hanging off it.
* The Compiler Crashes
@@ -29,26 +28,26 @@ No compiler should crash, no matter what kind of garbage is fed to
it. If the compiler crashes, you definitely found a bug and I need to
know about it.
Icarus Verilog internally checks its state while it works, and if it
detects something wrong that it cannot recover from, it will abort
Ivl internally checks its state while it works, and if it detects
something wrong that it cannot recover from, it will abort
intentionally. The "assertion failure" message that the program
prints in the process of dying is very important. It tells me where in
the source the bad thing happened. Include that message in the bug
report.
If there are no assertion messages, I need to know that as well.
If there are not assertion messages, I need to know that as well.
I also need a complete test program that demonstrates the crash.
* It Doesn't Like My Perfectly Valid Program(tm)
I need to know what you think is right that Icarus Verilog gets
wrong. Does it reject your "Perfectly Valid Program(tm)" or does it
compile it but give incorrect results? The latter is the most
insidious as it doesn't scream out to be fixed unless someone is
watching closely. However, if I get a sample program from you, and I
can compile it, and I run it and nuclear junk doesn't fall from the
sky, I'm moving on to the next problem.
I need to know what you think is right that ivl gets wrong. Does it
reject your "Perfectly Valid Program(tm)" or does it compile it but
give incorrect results? The latter is the most insidious as it doesn't
scream out to be fixed unless someone is watching closely. However, if
I get a sample program from you, and I can compile it, and I run it
and nuclear junk doesn't fall from the sky, I'm moving on to the next
problem.
So, if your program doesn't compile, tell me so, tell me where the
error occurs, and include a complete Perfectly Valid Test Program(tm).
@@ -58,25 +57,24 @@ know. What's on my disk is more recent then the latest snapshot.
If your program does compile, but generates incorrect output, I need
to know what it says and what you think it should say. From this I can
take your sample program and work on Icarus Verilog until it gets the
proper results. For this to work, of course, I first need to know what
is wrong with the output. Spell it out, because I've been known to
miss the obvious. Compiler writers often get buried in the details of
the wrong problem.
take your sample program and work on ivl until it gets the proper
results. For this to work, of course, I first need to know what is
wrong with the output. Spell it out, because I've been known to miss
the obvious. Compiler writers often get buried in the details of the
wrong problem.
* It Generates Incorrect Target Code
* It Generates Incorrect Target Code (XNF, EDIF/LPM, etc.)
As Icarus Verilog adds target code generators, there will be cases
where errors in the output netlist format occur. This is a tough nut
because I might not have all the tools to test the target format you
are reporting problems with. However, if you clearly explain what is
right and wrong about the generated output, I will probably be able
to fix the problem. It may take a few iterations.
As ivl adds target code generators, there will be cases where errors
in the output netlist format occur. This is a tough nut because I
might not have all the tools to test the target format you are
reporting problems with. However, if you clearly explain what is right
and wrong about the generated netlist, I will probably be able to fix
the problem. It may take a few iterations.
In this case, if possible include not only the sample Verilog program,
but the generated netlist file(s) and a clear indication of what went
wrong or what is expected. If it is not clear to me, I will ask for
clarification.
wrong. If it is not clear to me, I will ask for clarification.
* The Output is Correct, But Less Than Ideal
@@ -93,13 +91,13 @@ demonstrates the problem. If the error occurs after elaboration,
please include a top level module in the program that is suitable for
the target format. If I have to write the module myself, I might not
write it in a way that tickles the bug. So please, send all the
Verilog source that I need to invoke the error.
Verilog source (after preprocessing) that I need to invoke the error.
Also, include the command line you use to invoke the compiler. For
example:
iverilog -o foo.out -tvvp foo.v
iverilog foo.vl -s starthere
ivl foo.vl -o foo.cc -tvvm
ivl foo.vl -s starthere
If the error occurs with the null target (``-tnull'') then a top level
module may not be needed as long as the ``-s <name>'' switch is
@@ -110,19 +108,15 @@ invoke the error without any Verilog other than what is included?" And
while we are at it, please place a copyright notice in your test
program and include a GPL license statement if you can. Your test
program may find its way into the test suite, and the notices will
make it all nice and legal. Please look at the existing tests in the
test suite <http://sourceforge.net/ivtest> for examples of good test
programs.
make it all nice and legal.
RESEARCHING EXISTING/PAST BUGS, AND FILING REPORTS
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 URL <http://www.icarus.com/cgi-bin/ivl-bugs> 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.
The bug database supports basic keyword searches, and you can
optionally limit your search to active bugs, or fixed bugs. You may
@@ -131,7 +125,8 @@ broken. You may for example find a related bug that explains your
symptom.
The root page of the bug report database describes how to submit your
completed bug report.
completed bug report. You may submit it via the web form, or via
e-mail.
HOW TO SEND PATCHES
@@ -139,26 +134,21 @@ Bug reports with patches are very welcome, especially if they are
formatted such that I can inspect them, decide that they are obviously
correct, and apply them without worry.
I prefer patches generated by the git source code tracking system. If
you are editing the source, you really should be using the latest
version from git. Please see the developer documentation for more
detailed instructions -- <http://iverilog.wikia.com/wiki/>.
I prefer context diffs as emitted by diff from GNU diffutils. Human
beings can read such things, and they are resilient to changing
originals. A good set of flags to diff are ``diff -cNB''. With such
diffs, I can look at the changes you are offering and probably tell at
a glance that they are plausible. Then I can use patch(1) to apply
them. Or I can apply them by hand.
When you make a patch, submit it to the "Patches" tracker at
<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.
If you send patches, *please* tell me what this patch is supposed to
accomplish, which branch you intended to be patched, and if
appropriate include a test program that demonstrates the efficacy of
the patch. (If I have no idea what the patch is for, I will ask for
clarification before applying it.)
However, if you send patches, *please* tell me what this patch is
supposed to accomplish, and if appropriate include a test program that
demonstrates the efficacy of the patch. (If I have no idea what the
patch is for, I will ask for clarification before applying it.)
COPYRIGHT ISSUES
Icarus Verilog is Copyright (c) 1998-2008 Stephen Williams except
Icarus Verilog is Copyright (c) 1998-2003 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
@@ -168,3 +158,19 @@ then falls under the "otherwise noted" category.
I must insist that any copyright material submitted for inclusion
include the GPL license notice as shown in the rest of the source.
$Id: BUGS.txt,v 1.5 2007/03/22 16:08:14 steve Exp $
$Log: BUGS.txt,v $
Revision 1.5 2007/03/22 16:08:14 steve
Spelling fixes from Larry
Revision 1.4 2003/02/19 04:36:31 steve
Notes on hte bug database.
Revision 1.3 2003/01/30 16:23:07 steve
Spelling fixes.
Revision 1.2 1999/08/06 04:05:28 steve
Handle scope of parameters.
+31 -15
View File
@@ -1,7 +1,7 @@
#ifndef __HName_H
#define __HName_H
/*
* Copyright (c) 2001-2008 Stephen Williams ([email protected])
* Copyright (c) 2001-2007 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
@@ -18,9 +18,11 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: HName.h,v 1.7 2007/06/02 03:42:12 steve Exp $"
#endif
# include <iostream>
# include <list>
# include "StringHeap.h"
#ifdef __GNUC__
#if __GNUC__ > 2
@@ -55,7 +57,7 @@ class hname_t {
private:
perm_string name_;
// If the number is anything other than INT_MIN, then this is
// If the number is anything other then INT_MIN, then this is
// the numeric part of the name. Otherwise, it is not part of
// the name at all.
int number_;
@@ -68,16 +70,30 @@ extern bool operator == (const hname_t&, const hname_t&);
extern bool operator != (const hname_t&, const hname_t&);
extern ostream& operator<< (ostream&, const hname_t&);
inline ostream& operator<< (ostream&out, const list<hname_t>&ll)
{
list<hname_t>::const_iterator cur = ll.begin();
out << *cur;
cur ++;
while (cur != ll.end()) {
out << "." << *cur;
cur ++;
}
return out;
}
/*
* $Log: HName.h,v $
* Revision 1.7 2007/06/02 03:42:12 steve
* Properly evaluate scope path expressions.
*
* Revision 1.6 2007/05/16 19:12:33 steve
* Fix hname_t use of space for 1 perm_string.
*
* Revision 1.5 2007/04/26 03:06:21 steve
* Rework hname_t to use perm_strings.
*
* Revision 1.4 2002/11/02 03:27:51 steve
* Allow named events to be referenced by
* hierarchical names.
*
* Revision 1.3 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.2 2002/06/14 03:25:51 steve
* Compiler portability.
*
* Revision 1.1 2001/12/03 04:47:14 steve
* Parser and pform use hierarchical names as hname_t
* objects instead of encoded strings.
*
*/
#endif
+66 -70
View File
@@ -18,35 +18,12 @@
#
SHELL = /bin/sh
# Normally, the "make" will build all the files only by dependencies.
# The MODE, however, can control your rebuild intentions. The proper way
# to use the MODE is on the make command like, this this:
#
# make MODE=XXXX all
#
# The possible MODE= values are:
#
# regular
# Build as normal
#
# full
# Do some extra builds. in particular:
# Build version.h again, even if it already exists.
#
MODE=regular
# This version string is only used in the version message printed
# by the compiler. It reflects the assigned version number for the
# product as a whole. Most components also print the CVS Name: token
# in order to get a more automatic version stamp as well.
VERSION = 0.9.devel
# This string is used as an installation suffix. It modifies certain
# key install paths/files such that a build and install of Icarus Verilog
# with the same $(prefix) but a different $(suffix) will not interfere.
# The normal configuratin leaves suffix empty
suffix = @install_suffix@
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
@@ -58,9 +35,7 @@ VPATH = $(srcdir)
bindir = @bindir@
libdir = @libdir@
# This is actually the directory where we install our own header files.
# It is a little different from the generic includedir.
includedir = @includedir@/verilog$(suffix)
includedir = @includedir@
mandir = @mandir@
dllib=@DLLIB@
@@ -77,15 +52,15 @@ MAN = @MAN@
PS2PDF = @PS2PDF@
GIT = @GIT@
CPPFLAGS = @ident_support@ @DEFS@ -I. -I$(srcdir) -DVERSION='"$(VERSION)"' @CPPFLAGS@
CPPFLAGS = @ident_support@ @DEFS@ -I. -I$(srcdir) @CPPFLAGS@
CXXFLAGS = -Wall @CXXFLAGS@
PICFLAGS = @PICFLAG@
LDFLAGS = @rdynamic@ @LDFLAGS@
all: dep version.h ivl@EXEEXT@
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) VERSION=$(VERSION) $@); done
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for dir in ivlpp ; \
do (cd $$dir ; $(MAKE) VERSION=$(VERSION) $@); done
do (cd $$dir ; $(MAKE) $@); done
cd driver ; $(MAKE) VERSION=$(VERSION) $@
# In the windows world, the installer will need a dosify program to
@@ -124,22 +99,20 @@ distclean: clean
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.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 \
O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o elab_expr.o \
elab_lval.o elab_net.o elab_pexpr.o elab_scope.o \
elab_sig.o elab_sig_analog.o emit.o eval.o eval_attrib.o \
elab_sig.o emit.o eval.o eval_attrib.o \
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
load_module.o netlist.o netmisc.o net_analog.o net_assign.o \
net_design.o net_event.o net_expr.o net_func.o \
load_module.o netlist.o netmisc.o net_assign.o \
net_design.o net_event.o net_expr.o net_force.o net_func.o \
net_link.o net_modulo.o net_nex_input.o net_nex_output.o \
net_proc.o net_scope.o net_tran.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_types.o \
parse.o parse_misc.o pform.o pform_disciplines.o pform_dump.o pform_types.o \
set_width.o symbol_search.o sync.o sys_funcs.o \
verinum.o verireal.o target.o \
verinum.o verireal.o target.o targets.o \
Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \
PExpr.o PGate.o PGenerate.o PScope.o PSpec.o \
PTask.o PUdp.o PFunction.o PWire.o Statement.o AStatement.o StringHeap.o \
PTask.o PUdp.o PFunction.o PWire.o Statement.o StringHeap.o \
$(FF) $(TT)
Makefile: Makefile.in config.h.in config.status
@@ -168,11 +141,10 @@ all: dep iverilog-vpi
iverilog-vpi: iverilog-vpi.sh
sed -e 's;@SHARED@;@shared@;' -e 's;@PIC@;@PICFLAG@;' \
-e 's;@SUFFIX@;$(suffix);' \
-e 's;@IVCC@;$(CC);' \
-e 's;@IVCXX@;$(CXX);' \
-e 's;@IVCFLAGS@;$(CXXFLAGS);' \
-e 's;@INCLUDEDIR@;$(includedir);' \
-e 's;@INCLUDEDIR@;@includedir@;' \
-e 's;@LIBDIR@;@libdir@;' $< > $@
chmod +x $@
endif
@@ -213,9 +185,7 @@ iverilog-vpi.pdf: iverilog-vpi.ps
# For VERSION_TAG in driver/main.c, first try git-describe, then look for a
# version.h file in the source tree (included in snapshots and releases), and
# finally use nothing.
ifeq ($(MODE),full)
.PHONY: version.h
endif
# "true" and "false" in the next few lines are Unix shell command names
ifeq ($(GIT),none)
GIT_PRESENT = false
@@ -238,43 +208,51 @@ version.h:
ifeq (@MINGW32@,yes)
ifeq ($(MAN),none)
INSTALL_DOC = $(mandir)/man1/iverilog-vpi$(suffix).1
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
else
ifeq ($(PS2PDF),none)
INSTALL_DOC = $(mandir)/man1/iverilog-vpi$(suffix).1
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
else
INSTALL_DOC = $(prefix)/iverilog-vpi$(suffix).pdf $(mandir)/man1/iverilog-vpi$(suffix).1
INSTALL_DOC = $(prefix)/iverilog-vpi.pdf $(mandir)/man1/iverilog-vpi.1
all: dep iverilog-vpi.pdf
endif
endif
INSTALL_DOCDIR = $(mandir)/man1
else
INSTALL_DOC = $(mandir)/man1/iverilog-vpi$(suffix).1
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
INSTALL_DOCDIR = $(mandir)/man1
endif
ifeq (@MINGW32@,yes)
WIN32_INSTALL =
WIN32_INSTALL = $(prefix)/hello.vl $(prefix)/sqrt.vl $(prefix)/sqrt-virtex.v $(prefix)/QUICK_START.txt
else
WIN32_INSTALL = $(bindir)/iverilog-vpi$(suffix)
WIN32_INSTALL = $(bindir)/iverilog-vpi
endif
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)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
XNF_INSTALL = $(libdir)/ivl/xnf.conf $(libdir)/ivl/xnf-s.conf
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/include/constants.vams $(libdir)/ivl/include/disciplines.vams $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for dir in vpi ivlpp driver; \
do (cd $$dir ; $(MAKE) $@); done
$(bindir)/iverilog-vpi$(suffix): ./iverilog-vpi
$(INSTALL_SCRIPT) ./iverilog-vpi $(DESTDIR)$(bindir)/iverilog-vpi$(suffix)
$(bindir)/iverilog-vpi: ./iverilog-vpi
$(INSTALL_SCRIPT) ./iverilog-vpi $(DESTDIR)$(bindir)/iverilog-vpi
$(libdir)/ivl$(suffix)/ivl@EXEEXT@: ./ivl@EXEEXT@
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(DESTDIR)$(libdir)/ivl$(suffix)/ivl@EXEEXT@
$(libdir)/ivl/ivl@EXEEXT@: ./ivl@EXEEXT@
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(DESTDIR)$(libdir)/ivl/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/include/constants.vams: $(srcdir)/constants.vams
$(INSTALL_DATA) $(srcdir)/constants.vams $@
$(libdir)/ivl$(suffix)/include/disciplines.vams: $(srcdir)/disciplines.vams
$(INSTALL_DATA) $(srcdir)/disciplines.vams $(DESTDIR)$(libdir)/ivl$(suffix)/include/disciplines.vams
$(libdir)/ivl/include/disciplines.vams: $(srcdir)/disciplines.vams
$(INSTALL_DATA) $(srcdir)/disciplines.vams $@
$(libdir)/ivl/xnf-s.conf: $(srcdir)/xnf-s.conf
$(INSTALL_DATA) $(srcdir)/xnf-s.conf $(DESTDIR)$(libdir)/ivl/xnf-s.conf
$(libdir)/ivl/xnf.conf: $(srcdir)/xnf.conf
$(INSTALL_DATA) $(srcdir)/xnf.conf $(DESTDIR)$(libdir)/ivl/xnf.conf
$(includedir)/ivl_target.h: $(srcdir)/ivl_target.h
$(INSTALL_DATA) $(srcdir)/ivl_target.h $(DESTDIR)$(includedir)/ivl_target.h
@@ -291,31 +269,49 @@ $(includedir)/acc_user.h: $(srcdir)/acc_user.h
$(includedir)/veriuser.h: $(srcdir)/veriuser.h
$(INSTALL_DATA) $(srcdir)/veriuser.h $(DESTDIR)$(includedir)/veriuser.h
$(mandir)/man1/iverilog-vpi$(suffix).1: $(srcdir)/iverilog-vpi.man
$(INSTALL_DATA) $(srcdir)/iverilog-vpi.man $(DESTDIR)$(mandir)/man1/iverilog-vpi$(suffix).1
$(mandir)/man1/iverilog-vpi.1: $(srcdir)/iverilog-vpi.man
$(INSTALL_DATA) $(srcdir)/iverilog-vpi.man $(DESTDIR)$(mandir)/man1/iverilog-vpi.1
$(prefix)/iverilog-vpi$(suffix).pdf: iverilog-vpi.pdf
$(INSTALL_DATA) iverilog-vpi.pdf $(DESTDIR)$(prefix)/iverilog-vpi$(suffix).pdf
$(prefix)/iverilog-vpi.pdf: iverilog-vpi.pdf
$(INSTALL_DATA) iverilog-vpi.pdf $(DESTDIR)$(prefix)/iverilog-vpi.pdf
# In windows installations, put a few examples and the quick_start
# into the destination directory.
ifeq (@MINGW32@,yes)
$(prefix)/hello.vl: $(srcdir)/examples/hello.vl
./dosify.exe $(srcdir)/examples/hello.vl tmp.vl
mv tmp.vl $(prefix)/hello.vl
$(prefix)/sqrt.vl: $(srcdir)/examples/sqrt.vl
./dosify.exe $(srcdir)/examples/sqrt.vl tmp.vl
mv tmp.vl $(prefix)/sqrt.vl
$(prefix)/sqrt-virtex.v: $(srcdir)/examples/sqrt-virtex.v
./dosify.exe $(srcdir)/examples/sqrt-virtex.v tmp.vl
mv tmp.vl $(prefix)/sqrt-virtex.v
$(prefix)/QUICK_START.txt: $(srcdir)/QUICK_START.txt
./dosify.exe $(srcdir)/QUICK_START.txt tmp.txt
mv tmp.txt $(prefix)/QUICK_START.txt
endif
installdirs: mkinstalldirs
$(srcdir)/mkinstalldirs $(DESTDIR)$(bindir) $(DESTDIR)$(includedir) $(DESTDIR)$(libdir)/ivl$(suffix) \
$(DESTDIR)$(libdir)/ivl$(suffix)/include $(DESTDIR)$(mandir) $(DESTDIR)$(mandir)/man1
$(srcdir)/mkinstalldirs $(DESTDIR)$(bindir) $(DESTDIR)$(includedir) $(DESTDIR)$(libdir)/ivl \
$(DESTDIR)$(libdir)/ivl/include $(DESTDIR)$(mandir) $(DESTDIR)$(mandir)/man1
uninstall:
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for dir in vpi ivlpp driver; \
do (cd $$dir ; $(MAKE) $@); done
for f in ivl@EXEEXT@ include/constants.vams include/disciplines.vams; \
do rm -f $(DESTDIR)$(libdir)/ivl$(suffix)/$$f; done
-rmdir $(DESTDIR)$(libdir)/ivl$(suffix)/include
-rmdir $(DESTDIR)$(libdir)/ivl$(suffix)
for f in verilog$(suffix) iverilog-vpi$(suffix) gverilog$(suffix)@EXEEXT@; \
for f in xnf.conf xnf-s.conf ivl@EXEEXT@ include/constants.vams include/disciplines.vams; \
do rm -f $(DESTDIR)$(libdir)/ivl/$$f; done
-rmdir $(DESTDIR)$(libdir)/ivl/include
-rmdir $(DESTDIR)$(libdir)/ivl
for f in verilog iverilog-vpi gverilog@EXEEXT@; \
do rm -f $(DESTDIR)$(bindir)/$$f; done
for f in ivl_target.h vpi_user.h _pli_types.h acc_user.h veriuser.h; \
do rm -f $(DESTDIR)$(includedir)/$$f; done
-test X$(suffix) = X || rmdir $(DESTDIR)/$(includedir)
rm -f $(DESTDIR)$(mandir)/man1/iverilog-vpi$(suffix).1 $(DESTDIR)$(prefix)/iverilog-vpi$(suffix).pdf
rm -f $(DESTDIR)$(mandir)/man1/iverilog-vpi.1 $(DESTDIR)$(prefix)/iverilog-vpi.pdf
-include $(patsubst %.o, dep/%.d, $O)
+17 -7
View File
@@ -26,7 +26,7 @@
/* n is a permallocated string. */
Module::Module(perm_string n)
: PScope(n)
: PScope(n, 0)
{
library_flag = false;
default_nettype = NetNet::NONE;
@@ -41,9 +41,19 @@ void Module::add_gate(PGate*gate)
gates_.push_back(gate);
}
void Module::add_task(perm_string name, PTask*task)
{
tasks_[name] = task;
}
void Module::add_function(perm_string name, PFunction *func)
{
funcs_[name] = func;
}
unsigned Module::port_count() const
{
return ports.size();
return ports.count();
}
/*
@@ -51,10 +61,10 @@ unsigned Module::port_count() const
* module. If the port is internally unconnected, return an empty
* array.
*/
const vector<PEIdent*>& Module::get_port(unsigned idx) const
const svector<PEIdent*>& Module::get_port(unsigned idx) const
{
assert(idx < ports.size());
static const vector<PEIdent*> zero;
assert(idx < ports.count());
static svector<PEIdent*> zero;
if (ports[idx])
return ports[idx]->expr;
@@ -65,7 +75,7 @@ const vector<PEIdent*>& Module::get_port(unsigned idx) const
unsigned Module::find_port(const char*name) const
{
assert(name != 0);
for (unsigned idx = 0 ; idx < ports.size() ; idx += 1) {
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
if (ports[idx] == 0) {
/* It is possible to have undeclared ports. These
are ports that are skipped in the declaration,
@@ -79,7 +89,7 @@ unsigned Module::find_port(const char*name) const
return idx;
}
return ports.size();
return ports.count();
}
+44 -12
View File
@@ -22,8 +22,7 @@
# include <list>
# include <map>
# include <vector>
# include <utility>
# include "svector.h"
# include "StringHeap.h"
# include "HName.h"
# include "named.h"
@@ -59,7 +58,7 @@ class Module : public PScope, public LineInfo {
public:
struct port_t {
perm_string name;
vector<PEIdent*> expr;
svector<PEIdent*> expr;
};
public:
@@ -76,6 +75,40 @@ class Module : public PScope, public LineInfo {
NetNet::Type default_nettype;
struct range_t {
// True if this is an exclude
bool exclude_flag;
// lower bound
// If low_open_flag is false and low_expr=0, then use -inf
bool low_open_flag;
PExpr*low_expr;
// upper bound
// If high_open_flag is false and high_expr=0, then use +inf
bool high_open_flag;
PExpr*high_expr;
// Next range description in list
struct range_t*next;
};
/* The module has parameters that are evaluated when the
module is elaborated. During parsing, I put the parameters
into this map. */
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;
PExpr*msb;
PExpr*lsb;
bool signed_flag;
// Value expression
PExpr*expr;
// If there are range constrants, list them here
range_t*range;
};
map<perm_string,param_expr_t>parameters;
map<perm_string,param_expr_t>localparams;
/* specparams are simpler then other params, in that they have
no type information. They are merely constant
expressions. */
@@ -85,8 +118,7 @@ class Module : public PScope, public LineInfo {
new parameters within the module, but may be used to set
values within this module (when instantiated) or in other
instantiated modules. */
typedef pair<pform_name_t,PExpr*> named_expr_t;
list<named_expr_t>defparms;
map<pform_name_t,PExpr*>defparms;
/* Parameters may be overridden at instantiation time;
the overrides do not contain explicit parameter names,
@@ -98,7 +130,7 @@ class Module : public PScope, public LineInfo {
/* This is an array of port descriptors, which is in turn a
named array of PEident pointers. */
vector<port_t*> ports;
svector<port_t*> ports;
map<perm_string,PExpr*> attributes;
@@ -106,10 +138,6 @@ class Module : public PScope, public LineInfo {
set by the `timescale directive. */
int time_unit, time_precision;
/* Task definitions within this module */
map<perm_string,PTask*> tasks;
map<perm_string,PFunction*> funcs;
/* The module has a list of genvars that may be used in
various generate schemes. */
map<perm_string,LineInfo*> genvars;
@@ -124,9 +152,11 @@ class Module : public PScope, public LineInfo {
perm_string mod_name() const { return pscope_name(); }
void add_gate(PGate*gate);
void add_task(perm_string name, PTask*def);
void add_function(perm_string name, PFunction*def);
unsigned port_count() const;
const vector<PEIdent*>& get_port(unsigned idx) const;
const svector<PEIdent*>& get_port(unsigned idx) const;
unsigned find_port(const char*name) const;
PGate* get_gate(perm_string name);
@@ -137,12 +167,14 @@ class Module : public PScope, public LineInfo {
bool elaborate(Design*, NetScope*scope) const;
typedef map<perm_string,NetExpr*> replace_t;
bool elaborate_scope(Design*, NetScope*scope, const replace_t&rep);
bool elaborate_scope(Design*, NetScope*scope, const replace_t&rep) const;
bool elaborate_sig(Design*, NetScope*scope) const;
private:
list<PGate*> gates_;
map<perm_string,PTask*> tasks_;
map<perm_string,PFunction*> funcs_;
static void elaborate_parm_item_(perm_string name, const param_expr_t&cur,
Design*des, NetScope*scope);
+5 -5
View File
@@ -101,7 +101,7 @@ static NetExpr*calculate_val(Design*des, NetScope*scope, const PExpr*expr)
return dex;
}
static NetExpr* make_delay_nets(Design*des, NetScope*scope, NetExpr*expr)
static NetExpr* make_delay_nets(Design*des, NetExpr*expr)
{
if (dynamic_cast<NetESignal*> (expr))
return expr;
@@ -109,7 +109,7 @@ static NetExpr* make_delay_nets(Design*des, NetScope*scope, NetExpr*expr)
if (dynamic_cast<NetEConst*> (expr))
return expr;
NetNet*sig = expr->synthesize(des, scope);
NetNet*sig = expr->synthesize(des);
if (sig == 0) {
cerr << expr->get_fileline() << ": error: Expression " << *expr
<< " is not suitable for delay expression." << endl;
@@ -132,17 +132,17 @@ void PDelays::eval_delays(Design*des, NetScope*scope,
if (delay_[0]) {
rise_time = calculate_val(des, scope, delay_[0]);
if (as_nets_flag)
rise_time = make_delay_nets(des, scope, rise_time);
rise_time = make_delay_nets(des, rise_time);
if (delay_[1]) {
fall_time = calculate_val(des, scope, delay_[1]);
if (as_nets_flag)
fall_time = make_delay_nets(des, scope, fall_time);
fall_time = make_delay_nets(des, fall_time);
if (delay_[2]) {
decay_time = calculate_val(des, scope, delay_[2]);
if (as_nets_flag)
decay_time = make_delay_nets(des, scope, decay_time);
decay_time = make_delay_nets(des, decay_time);
} else {
if (rise_time < fall_time)
+66 -80
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2008 Stephen Williams <[email protected]>
* Copyright (c) 1998-2007 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
@@ -21,31 +21,28 @@
# include <iostream>
# include "compiler.h"
# include "PExpr.h"
# include "Module.h"
# include "netmisc.h"
# include <typeinfo>
PExpr::PExpr()
{
expr_type_ = IVL_VT_NO_TYPE;
}
PExpr::~PExpr()
{
}
bool PExpr::has_aa_term(Design*, NetScope*) const
{
return false;
}
bool PExpr::is_the_same(const PExpr*that) const
{
return typeid(this) == typeid(that);
}
bool PExpr::is_constant(Module*) const
{
return false;
}
NetNet* PExpr::elaborate_lnet(Design*des, NetScope*) const
{
cerr << get_fileline() << ": error: expression not valid in assign l-value: "
@@ -70,10 +67,9 @@ PEBinary::~PEBinary()
{
}
bool PEBinary::has_aa_term(Design*des, NetScope*scope) const
bool PEBinary::is_constant(Module*mod) const
{
assert(left_ && right_);
return left_->has_aa_term(des, scope) || right_->has_aa_term(des, scope);
return left_->is_constant(mod) && right_->is_constant(mod);
}
PEBComp::PEBComp(char op, PExpr*l, PExpr*r)
@@ -85,16 +81,6 @@ PEBComp::~PEBComp()
{
}
PEBLogic::PEBLogic(char op, PExpr*l, PExpr*r)
: PEBinary(op, l, r)
{
assert(op == 'a' || op == 'o');
}
PEBLogic::~PEBLogic()
{
}
PEBShift::PEBShift(char op, PExpr*l, PExpr*r)
: PEBinary(op, l, r)
{
@@ -104,7 +90,7 @@ PEBShift::~PEBShift()
{
}
PECallFunction::PECallFunction(const pform_name_t&n, const vector<PExpr *> &parms)
PECallFunction::PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms)
: path_(n), parms_(parms)
{
}
@@ -117,7 +103,7 @@ static pform_name_t pn_from_ps(perm_string n)
return tmp;
}
PECallFunction::PECallFunction(perm_string n, const vector<PExpr*>&parms)
PECallFunction::PECallFunction(perm_string n, const svector<PExpr*>&parms)
: path_(pn_from_ps(n)), parms_(parms)
{
}
@@ -127,52 +113,29 @@ PECallFunction::PECallFunction(perm_string n)
{
}
// NOTE: Anachronism. Try to work all use of svector out.
PECallFunction::PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms)
: path_(n), parms_(vector_from_svector(parms))
{
}
PECallFunction::PECallFunction(perm_string n, const svector<PExpr*>&parms)
: path_(pn_from_ps(n)), parms_(vector_from_svector(parms))
{
}
PECallFunction::~PECallFunction()
{
}
bool PECallFunction::has_aa_term(Design*des, NetScope*scope) const
{
bool flag = false;
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
flag = parms_[idx]->has_aa_term(des, scope) || flag;
}
return flag;
}
PEConcat::PEConcat(const svector<PExpr*>&p, PExpr*r)
: parms_(p), repeat_(r)
{
}
bool PEConcat::is_constant(Module *mod) const
{
bool constant = repeat_? repeat_->is_constant(mod) : true;
for (unsigned i = 0; constant && i < parms_.count(); ++i) {
constant = constant && parms_[i]->is_constant(mod);
}
return constant;
}
PEConcat::~PEConcat()
{
delete repeat_;
}
bool PEConcat::has_aa_term(Design*des, NetScope*scope) const
{
bool flag = false;
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
flag = parms_[idx]->has_aa_term(des, scope) || flag;
}
if (repeat_)
flag = repeat_->has_aa_term(des, scope) || flag;
return flag;
}
PEEvent::PEEvent(PEEvent::edge_t t, PExpr*e)
: type_(t), expr_(e)
{
@@ -187,12 +150,6 @@ PEEvent::edge_t PEEvent::type() const
return type_;
}
bool PEEvent::has_aa_term(Design*des, NetScope*scope) const
{
assert(expr_);
return expr_->has_aa_term(des, scope);
}
PExpr* PEEvent::expr() const
{
return expr_;
@@ -213,6 +170,11 @@ const verireal& PEFNumber::value() const
return *value_;
}
bool PEFNumber::is_constant(Module*) const
{
return true;
}
PEIdent::PEIdent(const pform_name_t&that)
: path_(that)
{
@@ -227,20 +189,35 @@ PEIdent::~PEIdent()
{
}
bool PEIdent::has_aa_term(Design*des, NetScope*scope) const
/*
* An identifier can be in a constant expression if (and only if) it is
* a parameter or genvar.
*
* NOTE: This test does not work if the name is hierarchical!
*/
bool PEIdent::is_constant(Module*mod) const
{
NetNet* net = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
if (mod == 0) return false;
const NetExpr*ex1, *ex2;
/* */
perm_string tmp = path_.back().name;
scope = symbol_search(0, des, scope, path_, net, par, eve, ex1, ex2);
{ map<perm_string,Module::param_expr_t>::const_iterator cur;
cur = mod->parameters.find(tmp);
if (cur != mod->parameters.end()) return true;
}
if (scope)
return scope->is_auto();
else
return false;
{ map<perm_string,Module::param_expr_t>::const_iterator cur;
cur = mod->localparams.find(tmp);
if (cur != mod->localparams.end()) return true;
}
{ map<perm_string,LineInfo*>::const_iterator cur;
cur = mod->genvars.find(tmp);
if (cur != mod->genvars.end()) return true;
}
return false;
}
PENumber::PENumber(verinum*vp)
@@ -268,6 +245,11 @@ bool PENumber::is_the_same(const PExpr*that) const
return *value_ == *obj->value_;
}
bool PENumber::is_constant(Module*) const
{
return true;
}
PEString::PEString(char*s)
: text_(s)
{
@@ -283,6 +265,11 @@ string PEString::value() const
return text_;
}
bool PEString::is_constant(Module*) const
{
return true;
}
PETernary::PETernary(PExpr*e, PExpr*t, PExpr*f)
: expr_(e), tru_(t), fal_(f)
{
@@ -292,12 +279,11 @@ PETernary::~PETernary()
{
}
bool PETernary::has_aa_term(Design*des, NetScope*scope) const
bool PETernary::is_constant(Module*m) const
{
assert(expr_ && tru_ && fal_);
return expr_->has_aa_term(des, scope)
|| tru_->has_aa_term(des, scope)
|| fal_->has_aa_term(des, scope);
return expr_->is_constant(m)
&& tru_->is_constant(m)
&& fal_->is_constant(m);
}
PEUnary::PEUnary(char op, PExpr*ex)
@@ -309,8 +295,8 @@ PEUnary::~PEUnary()
{
}
bool PEUnary::has_aa_term(Design*des, NetScope*scope) const
bool PEUnary::is_constant(Module*m) const
{
assert(expr_);
return expr_->has_aa_term(des, scope);
return expr_->is_constant(m);
}
+234 -119
View File
@@ -36,6 +36,9 @@ class NetScope;
* The PExpr class hierarchy supports the description of
* expressions. The parser can generate expression objects from the
* source, possibly reducing things that it knows how to reduce.
*
* The elaborate_net method is used by structural elaboration to build
* up a netlist interpretation of the expression.
*/
class PExpr : public LineInfo {
@@ -46,15 +49,11 @@ class PExpr : public LineInfo {
virtual void dump(ostream&) const;
// This method tests whether the expression contains any
// references to automatically allocated variables.
virtual bool has_aa_term(Design*des, NetScope*scope) const;
// This method tests the width that the expression wants to
// be. It is used by elaboration of assignments to figure out
// the width of the expression.
//
// The "min" is the width of the local context, so is the
// The "min" is the width of the local context, so it the
// minimum width that this function should return. Initially
// this is the same as the lval width.
//
@@ -67,22 +66,13 @@ class PExpr : public LineInfo {
// the subexpression should not make l-value related
// optimizations.
//
// The expr_type is an output argument that gives the
// calculated type for the expression.
//
// The unsized_flag is set to true if the expression is
// The unsigned_flag is set to true if the expression is
// unsized and therefore expandable. This happens if a
// sub-expression is an unsized literal. Some expressions make
// special use of that.
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag);
// After the test_width method is complete, these methods
// return valid results.
ivl_variable_type_t expr_type() const { return expr_type_; }
unsigned expr_width() const { return expr_width_; }
bool&unsized_flag) const;
// During the elaborate_sig phase, we may need to scan
// expressions to find implicit net declarations.
@@ -108,6 +98,17 @@ class PExpr : public LineInfo {
// evaluation of parameters.
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
// This method elaborate the expression as gates, for use in a
// continuous assign or other wholly structural context.
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0 =Link::STRONG,
Link::strength_t drive1 =Link::STRONG)
const;
// This method elaborates the expression as gates, but
// restricted for use as l-values of continuous assignments.
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
@@ -137,12 +138,11 @@ class PExpr : public LineInfo {
// expressions that must be structurally "identical".
virtual bool is_the_same(const PExpr*that) const;
protected:
// The derived class test_width methods should fill these in.
ivl_variable_type_t expr_type_;
unsigned expr_width_;
static void suppress_binary_operand_sign_if_needed_(NetExpr*lp, NetExpr*rp);
// Return true if this expression is a valid constant
// expression. the Module pointer is needed to find parameter
// identifiers and any other module specific interpretations
// of expressions.
virtual bool is_constant(Module*) const;
private: // not implemented
PExpr(const PExpr&);
@@ -160,22 +160,24 @@ class PEConcat : public PExpr {
virtual verinum* eval_const(Design*des, NetScope*sc) const;
virtual void dump(ostream&) const;
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag);
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
virtual NetEConcat*elaborate_pexpr(Design*des, NetScope*) const;
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const;
virtual bool is_constant(Module*) const;
private:
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
bool bidirectional_flag) const;
@@ -206,8 +208,6 @@ class PEEvent : public PExpr {
virtual void dump(ostream&) const;
virtual bool has_aa_term(Design*des, NetScope*scope) const;
private:
edge_t type_;
PExpr *expr_;
@@ -229,14 +229,21 @@ class PEFNumber : public PExpr {
any rounding that is needed to get the value. */
virtual verinum* eval_const(Design*des, NetScope*sc) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag);
/* A PEFNumber is a constant, so this returns true. */
virtual bool is_constant(Module*) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual void dump(ostream&) const;
private:
@@ -255,13 +262,9 @@ class PEIdent : public PExpr {
void append_name(perm_string);
virtual void dump(ostream&) const;
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag);
bool&unsized_flag) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
@@ -275,6 +278,15 @@ class PEIdent : public PExpr {
NetScope*scope,
bool is_force) const;
// Structural r-values are OK.
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
@@ -283,6 +295,7 @@ class PEIdent : public PExpr {
// only applies to Ident expressions.
NetNet* elaborate_port(Design*des, NetScope*sc) const;
virtual bool is_constant(Module*) const;
verinum* eval_const(Design*des, NetScope*sc) const;
const pform_name_t& path() const { return path_; }
@@ -302,19 +315,17 @@ class PEIdent : public PExpr {
private:
NetAssign_*elaborate_lval_net_word_(Design*, NetScope*, NetNet*) const;
bool elaborate_lval_net_bit_(Design*, NetScope*, NetAssign_*) const;
bool elaborate_lval_net_part_(Design*, NetScope*, NetAssign_*) const;
bool elaborate_lval_net_idx_(Design*, NetScope*, NetAssign_*,
index_component_t::ctype_t) const;
private:
NetExpr*elaborate_expr_param_(Design*des,
NetScope*scope,
const NetExpr*par,
NetScope*found,
const NetExpr*par_msb,
const NetExpr*par_lsb,
int expr_wid) const;
NetExpr*elaborate_expr_param(Design*des,
NetScope*scope,
const NetExpr*par,
NetScope*found,
const NetExpr*par_msb,
const NetExpr*par_lsb) const;
NetExpr*elaborate_expr_param_part_(Design*des,
NetScope*scope,
const NetExpr*par,
@@ -354,6 +365,38 @@ class PEIdent : public PExpr {
NetESignal*net,
NetScope*found) const;
public:
NetNet* elaborate_net_array_(Design*des, NetScope*scope,
NetNet*sig, unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
NetNet* elaborate_net_net_(Design*des, NetScope*scope,
NetNet*sig, unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
NetNet* elaborate_net_net_idx_up_(Design*des, NetScope*scope,
NetNet*sig, unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
NetNet* elaborate_net_bitmux_(Design*des, NetScope*scope,
NetNet*sig,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
private:
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
bool bidirectional_flag) const;
@@ -362,6 +405,8 @@ class PEIdent : public PExpr {
bool eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
long&midx, long&lidx) const;
NetNet*process_select_(Design*des, NetScope*scope, NetNet*sig) const;
};
class PENumber : public PExpr {
@@ -375,9 +420,15 @@ class PENumber : public PExpr {
virtual void dump(ostream&) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag);
bool&unsized_flag) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
int expr_width, bool) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
@@ -388,6 +439,7 @@ class PENumber : public PExpr {
virtual verinum* eval_const(Design*des, NetScope*sc) const;
virtual bool is_the_same(const PExpr*that) const;
virtual bool is_constant(Module*) const;
private:
verinum*const value_;
@@ -411,14 +463,22 @@ class PEString : public PExpr {
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag);
bool&unsized_flag) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
int expr_width, bool) const;
virtual NetEConst*elaborate_pexpr(Design*des, NetScope*sc) const;
verinum* eval_const(Design*, NetScope*) const;
virtual bool is_constant(Module*) const;
private:
char*text_;
};
@@ -431,22 +491,47 @@ class PEUnary : public PExpr {
virtual void dump(ostream&out) const;
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag);
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
virtual bool is_constant(Module*) const;
private:
NetExpr* elaborate_expr_bits_(NetExpr*operand, int expr_wid) const;
NetNet* elab_net_uminus_const_logic_(Design*des, NetScope*scope,
NetEConst*expr,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
NetNet* elab_net_uminus_const_real_(Design*des, NetScope*scope,
NetECReal*expr,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
NetNet* elab_net_unary_real_(Design*des, NetScope*scope,
NetExpr*expr,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
private:
char op_;
@@ -459,17 +544,23 @@ class PEBinary : public PExpr {
explicit PEBinary(char op, PExpr*l, PExpr*r);
~PEBinary();
virtual void dump(ostream&out) const;
virtual bool is_constant(Module*) const;
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual void dump(ostream&out) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag);
bool&unsized_flag) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
@@ -483,13 +574,54 @@ class PEBinary : public PExpr {
NetExpr*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetExpr*elaborate_eval_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetExpr*elaborate_expr_base_bits_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetExpr*elaborate_expr_base_div_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetExpr*elaborate_expr_base_lshift_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetExpr*elaborate_expr_base_rshift_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetExpr*elaborate_expr_base_mult_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetExpr*elaborate_expr_base_add_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
static void suppress_operand_sign_if_needed_(NetExpr*lp, NetExpr*rp);
private:
NetNet* elaborate_net_add_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_bit_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_cmp_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_div_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_mod_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_log_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_mul_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_pow_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_shift_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
};
/*
@@ -504,31 +636,10 @@ class PEBComp : public PEBinary {
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&flag);
bool&flag) const;
NetExpr* elaborate_expr(Design*des, NetScope*scope,
int expr_width, bool sys_task_arg) const;
NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
};
/*
* This derived class is for handling logical expressions: && and ||.
*/
class PEBLogic : public PEBinary {
public:
explicit PEBLogic(char op, PExpr*l, PExpr*r);
~PEBLogic();
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&flag);
NetExpr* elaborate_expr(Design*des, NetScope*scope,
int expr_width, bool sys_task_arg) const;
NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
};
class PEBShift : public PEBinary {
@@ -538,11 +649,7 @@ class PEBShift : public PEBinary {
~PEBShift();
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&flag);
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
unsigned min, unsigned lval, bool&flag) const;
};
/*
@@ -555,18 +662,23 @@ class PETernary : public PExpr {
explicit PETernary(PExpr*e, PExpr*t, PExpr*f);
~PETernary();
virtual bool is_constant(Module*) const;
virtual void dump(ostream&out) const;
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag);
bool&unsized_flag) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetETernary*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
virtual NetETernary*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
@@ -584,42 +696,45 @@ class PETernary : public PExpr {
*/
class PECallFunction : public PExpr {
public:
explicit PECallFunction(const pform_name_t&n, const vector<PExpr *> &parms);
// Call of system function (name is not hierarchical)
explicit PECallFunction(perm_string n, const vector<PExpr *> &parms);
explicit PECallFunction(perm_string n);
// svector versions. Should be removed!
explicit PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms);
// Call of system function (name is not hierarchical)
explicit PECallFunction(perm_string n, const svector<PExpr *> &parms);
explicit PECallFunction(perm_string n);
~PECallFunction();
virtual void dump(ostream &) const;
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
int expr_wid, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag);
bool&unsized_flag) const;
private:
pform_name_t path_;
vector<PExpr *> parms_;
svector<PExpr *> parms_;
bool check_call_matches_definition_(Design*des, NetScope*dscope) const;
NetExpr* elaborate_sfunc_(Design*des, NetScope*scope, int expr_wid) const;
NetExpr* elaborate_access_func_(Design*des, NetScope*scope, int expr_wid) const;
NetNet* elaborate_net_sfunc_(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
unsigned test_width_sfunc_(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag);
bool&unsized_flag) const;
};
#endif
+1 -2
View File
@@ -21,10 +21,9 @@
#include "PTask.h"
PFunction::PFunction(perm_string name, PScope*parent, bool is_auto__)
PFunction::PFunction(perm_string name, PScope*parent)
: PScope(name, parent), ports_(0), statement_(0)
{
is_auto_ = is_auto__;
return_type_.type = PTF_NONE;
}
+7 -14
View File
@@ -1,7 +1,7 @@
#ifndef __PGate_H
#define __PGate_H
/*
* Copyright (c) 1998-2008 Stephen Williams ([email protected])
* Copyright (c) 1998-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
@@ -18,6 +18,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PGate.h,v 1.32 2006/04/10 00:37:42 steve Exp $"
#endif
# include "svector.h"
# include "StringHeap.h"
@@ -80,7 +83,7 @@ class PGate : public LineInfo {
bool as_net_flag =false) const;
unsigned pin_count() const { return pins_? pins_->count() : 0; }
PExpr*pin(unsigned idx) const { return (*pins_)[idx]; }
const PExpr*pin(unsigned idx) const { return (*pins_)[idx]; }
strength_t strength0() const;
strength_t strength1() const;
@@ -167,16 +170,8 @@ class PGBuiltin : public PGate {
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
private:
unsigned calculate_array_count_(Design*, NetScope*,
long&high, long&low) const;
unsigned calculate_output_count_(void) const;
NetNode* create_gate_for_output_(Design*, NetScope*,
perm_string gate_name,
unsigned instance_width) const;
Type type_;
PExpr*msb_;
PExpr*lsb_;
};
@@ -237,17 +232,15 @@ class PGModule : public PGate {
PExpr*msb_;
PExpr*lsb_;
friend class delayed_elaborate_scope_mod_instances;
void elaborate_mod_(Design*, Module*mod, NetScope*scope) const;
void elaborate_udp_(Design*, PUdp *udp, NetScope*scope) const;
void elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const;
void elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*sc) const;
bool elaborate_sig_mod_(Design*des, NetScope*scope, Module*mod) const;
bool elaborate_sig_udp_(Design*des, NetScope*scope, PUdp*udp) const;
NetNet*resize_net_to_port_(Design*des, NetScope*scope,
NetNet*sig, unsigned port_wid,
NetNet::PortType dir, bool as_signed) const;
NetNet::PortType dir) const;
};
#endif
+14 -1
View File
@@ -27,14 +27,27 @@ PGenerate::PGenerate(unsigned id)
: id_number(id)
{
parent = 0;
lexical_scope = 0;
}
PGenerate::~PGenerate()
{
}
PWire* PGenerate::get_wire(perm_string name) const
{
map<perm_string,PWire*>::const_iterator obj = wires.find(name);
if (obj == wires.end())
return 0;
else
return (*obj).second;
}
void PGenerate::add_gate(PGate*gate)
{
gates.push_back(gate);
}
void PGenerate::add_behavior(PProcess*proc)
{
behaviors.push_back(proc);
}
+13 -17
View File
@@ -1,7 +1,7 @@
#ifndef __PGenerate_H
#define __PGenerate_H
/*
* Copyright (c) 2006-2008 Stephen Williams ([email protected])
* Copyright (c) 2006 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
@@ -18,11 +18,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PGenerate.h,v 1.4 2007/06/02 03:42:12 steve Exp $"
#endif
# include "LineInfo.h"
# include "StringHeap.h"
# include "HName.h"
# include "PScope.h"
# include <list>
# include <map>
# include "pform_types.h"
@@ -30,9 +32,7 @@
class Design;
class NetScope;
class PExpr;
class PFunction;
class PProcess;
class PTask;
class PGate;
class PWire;
@@ -49,10 +49,10 @@ 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 LineInfo, public LexicalScope {
class PGenerate : public LineInfo {
public:
explicit PGenerate(unsigned id_number);
PGenerate(unsigned id_number);
~PGenerate();
// Generate schemes have an ID number, for when the scope is
@@ -60,12 +60,8 @@ class PGenerate : public LineInfo, public LexicalScope {
const unsigned id_number;
perm_string scope_name;
// This is used during parsing to stack lexical scopes within
// this generate scheme.
PScope*lexical_scope;
enum scheme_t {GS_NONE, GS_LOOP, GS_CONDIT, GS_ELSE,
GS_CASE, GS_CASE_ITEM, GS_NBLOCK};
GS_CASE, GS_CASE_ITEM};
scheme_t scheme_type;
// generate loops have an index variable and three
@@ -75,15 +71,16 @@ class PGenerate : public LineInfo, public LexicalScope {
PExpr*loop_test;
PExpr*loop_step;
map<perm_string,PWire*>wires;
PWire* get_wire(perm_string name) const;
list<PGate*> gates;
void add_gate(PGate*);
// Tasks instantiated within this scheme.
map<perm_string,PTask*> tasks;
map<perm_string,PFunction*>funcs;
list<PProcess*> behaviors;
void add_behavior(PProcess*behave);
// Generate schemes can contain further generate schemes.
list<PGenerate*> generate_schemes;
list<PGenerate*> generates;
PGenerate*parent;
// This method is called by the elaboration of a module to
@@ -102,7 +99,6 @@ class PGenerate : public LineInfo, public LexicalScope {
bool generate_scope_loop_(Design*des, NetScope*container);
bool generate_scope_condit_(Design*des, NetScope*container, bool else_flag);
bool generate_scope_case_(Design*des, NetScope*container);
bool generate_scope_nblock_(Design*des, NetScope*container);
// Elaborate_scope within a generated scope.
void elaborate_subscope_(Design*des, NetScope*scope);
+3 -8
View File
@@ -19,13 +19,8 @@
# include "PScope.h"
PScope::PScope(perm_string n, PScope*parent)
: name_(n), parent_(parent)
{
}
PScope::PScope(perm_string n)
: name_(n), parent_(0)
PScope::PScope(perm_string n, PScope*p)
: name_(n), parent_(p)
{
}
@@ -33,7 +28,7 @@ PScope::~PScope()
{
}
PWire* LexicalScope::wires_find(perm_string name)
PWire* PScope::wires_find(perm_string name)
{
map<perm_string,PWire*>::const_iterator cur = wires.find(name);
if (cur == wires.end())
+14 -71
View File
@@ -19,15 +19,11 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "LineInfo.h"
# include "StringHeap.h"
# include "pform_types.h"
# include "ivl_target.h"
# include <map>
class PEvent;
class PExpr;
class AProcess;
class PProcess;
class PWire;
@@ -39,74 +35,10 @@ class NetScope;
* represents lexical scope. For example, a module, a function/task, a
* named block is derived from a PScope.
*
* NOTE: This is not the same concept as the "scope" of an elaborated
* NOTE: This is note the same concept as the "scope" of an elaborated
* hierarchy. That is represented by NetScope objects after elaboration.
*/
class LexicalScope {
public:
explicit LexicalScope() { }
// A virtual destructor is so that dynamic_cast can work.
virtual ~LexicalScope() { }
struct range_t {
// True if this is an exclude
bool exclude_flag;
// lower bound
// If low_open_flag is false and low_expr=0, then use -inf
bool low_open_flag;
PExpr*low_expr;
// upper bound
// If high_open_flag is false and high_expr=0, then use +inf
bool high_open_flag;
PExpr*high_expr;
// Next range description in list
struct range_t*next;
};
/* 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 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;
PExpr*msb;
PExpr*lsb;
bool signed_flag;
// Value expression
PExpr*expr;
// If there are range constraints, list them here
range_t*range;
};
map<perm_string,param_expr_t>parameters;
map<perm_string,param_expr_t>localparams;
// Named events in the scope.
map<perm_string,PEvent*>events;
// Nets and variables (wires) in the scope
map<perm_string,PWire*>wires;
PWire* wires_find(perm_string name);
// Behaviors (processes) in this scope
list<PProcess*> behaviors;
list<AProcess*> analog_behaviors;
protected:
void dump_parameters_(ostream&out, unsigned indent) const;
void dump_localparams_(ostream&out, unsigned indent) const;
void dump_events_(ostream&out, unsigned indent) const;
void dump_wires_(ostream&out, unsigned indent) const;
private:
};
class PScope : public LexicalScope {
class PScope {
public:
// When created, a scope has a name and a parent. The name is
@@ -118,13 +50,24 @@ class PScope : public LexicalScope {
// modules. Scopes for tasks and functions point to their
// containing module.
PScope(perm_string name, PScope*parent);
PScope(perm_string name);
virtual ~PScope();
perm_string pscope_name() const { return name_; }
PScope* pscope_parent() { return parent_; }
// Nets an variables (wires) in the scope
map<perm_string,PWire*>wires;
PWire* wires_find(perm_string name);
// Named events in the scope.
map<perm_string,PEvent*>events;
// Behaviors (processes) in this scope
list<PProcess*> behaviors;
protected:
void dump_wires_(ostream&out, unsigned indent) const;
bool elaborate_sig_wires_(Design*des, NetScope*scope) const;
bool elaborate_behaviors_(Design*des, NetScope*scope) const;
+29 -2
View File
@@ -21,10 +21,9 @@
# include "PTask.h"
PTask::PTask(perm_string name, PScope*parent, bool is_auto__)
PTask::PTask(perm_string name, PScope*parent)
: PScope(name, parent), ports_(0), statement_(0)
{
is_auto_ = is_auto__;
}
PTask::~PTask()
@@ -42,3 +41,31 @@ void PTask::set_statement(Statement*s)
assert(statement_ == 0);
statement_ = s;
}
/*
* $Log: PTask.cc,v $
* Revision 1.7 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.6 2001/07/25 03:10:48 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.5 2001/04/19 03:04:47 steve
* Spurious assert of empty statemnt.
*
* Revision 1.4 2001/01/13 22:20:08 steve
* Parse parameters within nested scopes.
*
* Revision 1.3 2000/02/23 02:56:53 steve
* Macintosh compilers do not support ident.
*
* Revision 1.2 1999/07/24 02:11:19 steve
* Elaborate task input ports.
*
* Revision 1.1 1999/07/03 02:12:51 steve
* Elaborate user defined tasks.
*
*/
+2 -8
View File
@@ -51,7 +51,7 @@ struct PTaskFuncArg {
class PTask : public PScope, public LineInfo {
public:
explicit PTask(perm_string name, PScope*parent, bool is_auto);
explicit PTask(perm_string name, PScope*parent);
~PTask();
void set_ports(svector<PWire *>*p);
@@ -69,14 +69,11 @@ class PTask : public PScope, public LineInfo {
// Elaborate the statement to finish off the task definition.
void elaborate(Design*des, NetScope*scope) const;
bool is_auto() const { return is_auto_; };
void dump(ostream&, unsigned) const;
private:
svector<PWire*>*ports_;
Statement*statement_;
bool is_auto_;
private: // Not implemented
PTask(const PTask&);
@@ -93,7 +90,7 @@ class PTask : public PScope, public LineInfo {
class PFunction : public PScope, public LineInfo {
public:
explicit PFunction(perm_string name, PScope*parent, bool is_auto);
explicit PFunction(perm_string name, PScope*parent);
~PFunction();
void set_ports(svector<PWire *>*p);
@@ -108,15 +105,12 @@ class PFunction : public PScope, public LineInfo {
/* Elaborate the behavioral statement. */
void elaborate(Design *des, NetScope*) const;
bool is_auto() const { return is_auto_; };
void dump(ostream&, unsigned) const;
private:
PTaskFuncArg return_type_;
svector<PWire *> *ports_;
Statement *statement_;
bool is_auto_;
};
#endif
+2 -2
View File
@@ -198,13 +198,13 @@ void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
}
}
void PWire::set_discipline(ivl_discipline_t d)
void PWire::set_discipline(discipline_t*d)
{
assert(discipline_ == 0);
discipline_ = d;
}
ivl_discipline_t PWire::get_discipline(void) const
discipline_t* PWire::get_discipline(void) const
{
return discipline_;
}
+7 -3
View File
@@ -18,6 +18,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PWire.h,v 1.21 2007/05/24 04:07:11 steve Exp $"
#endif
# include "netlist.h"
# include "LineInfo.h"
@@ -33,6 +36,7 @@ class ostream;
class PExpr;
class Design;
class discipline_t;
/*
* The different type of PWire::set_range() calls.
@@ -78,8 +82,8 @@ class PWire : public LineInfo {
void set_memory_idx(PExpr*ldx, PExpr*rdx);
void set_discipline(ivl_discipline_t);
ivl_discipline_t get_discipline(void) const;
void set_discipline(discipline_t*);
discipline_t* get_discipline(void) const;
map<perm_string,PExpr*> attributes;
@@ -111,7 +115,7 @@ class PWire : public LineInfo {
PExpr*lidx_;
PExpr*ridx_;
ivl_discipline_t discipline_;
discipline_t*discipline_;
private: // not implemented
PWire(const PWire&);
+29 -11
View File
@@ -12,7 +12,10 @@ home page at <http://www.icarus.com/eda/verilog>.
Icarus Verilog is not aimed at being a simulator in the traditional
sense, but a compiler that generates code employed by back-end
tools.
tools. These back-end tools currently include a simulator engine
called VVP, an XNF (Xilinx Netlist Format) generator and an EDIF FPGA
netlist generator. In the future, backends are expected for EDIF/LPM,
structural Verilog, VHDL, etc.
For instructions on how to run Icarus Verilog,
see the ``iverilog'' man page.
@@ -85,6 +88,10 @@ 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 behavior:
--without-ipal
This turns off support for Icarus PAL, whether ipal
libraries are installed or not.
--prefix=<root>
The default is /usr/local, which causes the tool suite to
be compiled for install in /usr/local/bin,
@@ -95,16 +102,27 @@ configure script that modify its behavior:
common to use --prefix=/opt. You can configure for a non-root
install with --prefix=$HOME.
--enable-suffix
--enable-suffix=<your-suffix>
--disable-suffix
Enable/disable changing the names of install files to use
a suffix string so that this version or install can co-
exist with other versions. This renames the installed
commands (iverilog, iverilog-vpi, vvp) and the installed
library files and include directory so that installations
with the same prefix but different suffix are guaranteed
to not interfere with each other.
--enable-vvp32 (experimental)
If compiling on AMD64 systems, this enables the
compilation of 32bit compatible vvp (vvp32) and the vpi
modules that match.
2.2.1 Special AMD64 Instructions
(The Icarus Verilog RPM for x86_64 is build using these instructions.)
If you are building for Linux/AMD64 (a.k.a x86_64) then to get the
most out of your install, first make sure you have both 64bit and
32bit development libraries installed. Then configure with this
somewhat more complicated command:
./configure libdir64='$(prefix)/lib64' vpidir1=vpi64 vpidir2=. --enable-vvp32
This reflects the convention on AMD64 systems that 64bit libraries go
into lib64 directories. The "--enable-vvp32" also turns on 32bit
compatibility files. A 32bit version of vvp (vvp32) will be created,
as well as 32bit versions of the development libraries and bundled VPI
libraries.
2.3 (Optional) Testing
+56 -37
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2008 Stephen Williams ([email protected])
* Copyright (c) 1998-1999 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
@@ -16,6 +16,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: Statement.cc,v 1.30 2007/05/24 04:07:11 steve Exp $"
#endif
# include "config.h"
@@ -26,20 +29,20 @@ Statement::~Statement()
{
}
PAssign_::PAssign_(PExpr*lval__, PExpr*ex, bool is_constant)
: event_(0), count_(0), lval_(lval__), rval_(ex), is_constant_(is_constant)
PAssign_::PAssign_(PExpr*lval, PExpr*ex)
: event_(0), lval_(lval), rval_(ex)
{
delay_ = 0;
}
PAssign_::PAssign_(PExpr*lval__, PExpr*de, PExpr*ex)
: event_(0), count_(0), lval_(lval__), rval_(ex), is_constant_(false)
PAssign_::PAssign_(PExpr*lval, PExpr*de, PExpr*ex)
: event_(0), lval_(lval), rval_(ex)
{
delay_ = de;
}
PAssign_::PAssign_(PExpr*lval__, PExpr*cnt, PEventStatement*ev, PExpr*ex)
: event_(ev), count_(cnt), lval_(lval__), rval_(ex), is_constant_(false)
PAssign_::PAssign_(PExpr*lval, PEventStatement*ev, PExpr*ex)
: event_(ev), lval_(lval), rval_(ex)
{
delay_ = 0;
}
@@ -50,23 +53,18 @@ PAssign_::~PAssign_()
delete rval_;
}
PAssign::PAssign(PExpr*lval__, PExpr*ex)
: PAssign_(lval__, ex, false)
PAssign::PAssign(PExpr*lval, PExpr*ex)
: PAssign_(lval, ex)
{
}
PAssign::PAssign(PExpr*lval__, PExpr*d, PExpr*ex)
: PAssign_(lval__, d, ex)
PAssign::PAssign(PExpr*lval, PExpr*d, PExpr*ex)
: PAssign_(lval, d, ex)
{
}
PAssign::PAssign(PExpr*lval__, PExpr*cnt, PEventStatement*d, PExpr*ex)
: PAssign_(lval__, cnt, d, ex)
{
}
PAssign::PAssign(PExpr*lval__, PExpr*ex, bool is_constant)
: PAssign_(lval__, ex, is_constant)
PAssign::PAssign(PExpr*lval, PEventStatement*d, PExpr*ex)
: PAssign_(lval, d, ex)
{
}
@@ -74,18 +72,13 @@ PAssign::~PAssign()
{
}
PAssignNB::PAssignNB(PExpr*lval__, PExpr*ex)
: PAssign_(lval__, ex, false)
PAssignNB::PAssignNB(PExpr*lval, PExpr*ex)
: PAssign_(lval, ex)
{
}
PAssignNB::PAssignNB(PExpr*lval__, PExpr*d, PExpr*ex)
: PAssign_(lval__, d, ex)
{
}
PAssignNB::PAssignNB(PExpr*lval__, PExpr*cnt, PEventStatement*d, PExpr*ex)
: PAssign_(lval__, cnt, d, ex)
PAssignNB::PAssignNB(PExpr*lval, PExpr*d, PExpr*ex)
: PAssign_(lval, d, ex)
{
}
@@ -99,7 +92,7 @@ PBlock::PBlock(perm_string n, PScope*parent, BL_TYPE t)
}
PBlock::PBlock(BL_TYPE t)
: PScope(perm_string()), bl_type_(t)
: PScope(perm_string(),0), bl_type_(t)
{
}
@@ -228,15 +221,6 @@ void PEventStatement::set_statement(Statement*st)
statement_ = st;
}
bool PEventStatement::has_aa_term(Design*des, NetScope*scope)
{
bool flag = false;
for (unsigned idx = 0 ; idx < expr_.count() ; idx += 1) {
flag = expr_[idx]->has_aa_term(des, scope) || flag;
}
return flag;
}
PForce::PForce(PExpr*l, PExpr*r)
: lval_(l), expr_(r)
{
@@ -314,3 +298,38 @@ PWhile::~PWhile()
delete cond_;
delete statement_;
}
/*
* $Log: Statement.cc,v $
* Revision 1.30 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.29 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items.
*
* Revision 1.28 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.27 2002/04/21 22:31:02 steve
* Redo handling of assignment internal delays.
* Leave it possible for them to be calculated
* at run time.
*
* Revision 1.26 2002/04/21 04:59:07 steve
* Add support for conbinational events by finding
* the inputs to expressions and some statements.
* Get case and assignment statements working.
*
* Revision 1.25 2001/12/03 04:47:14 steve
* Parser and pform use hierarchical names as hname_t
* objects instead of encoded strings.
*
* Revision 1.24 2001/11/22 06:20:59 steve
* Use NetScope instead of string for scope path.
*
* Revision 1.23 2001/07/25 03:10:48 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*/
+9 -23
View File
@@ -20,7 +20,6 @@
*/
# include <string>
# include "ivl_target.h"
# include "svector.h"
# include "StringHeap.h"
# include "PDelays.h"
@@ -47,14 +46,16 @@ class NetScope;
class PProcess : public LineInfo {
public:
PProcess(ivl_process_type_t t, Statement*st)
enum Type { PR_INITIAL, PR_ALWAYS };
PProcess(Type t, Statement*st)
: type_(t), statement_(st) { }
virtual ~PProcess();
bool elaborate(Design*des, NetScope*scope) const;
ivl_process_type_t type() const { return type_; }
Type type() const { return type_; }
Statement*statement() { return statement_; }
map<perm_string,PExpr*> attributes;
@@ -62,7 +63,7 @@ class PProcess : public LineInfo {
virtual void dump(ostream&out, unsigned ind) const;
private:
ivl_process_type_t type_;
Type type_;
Statement*statement_;
};
@@ -81,8 +82,6 @@ class Statement : public LineInfo {
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
map<perm_string,PExpr*> attributes;
};
/*
@@ -92,27 +91,23 @@ class Statement : public LineInfo {
*/
class PAssign_ : public Statement {
public:
explicit PAssign_(PExpr*lval, PExpr*ex, bool is_constant);
explicit PAssign_(PExpr*lval, PExpr*ex);
explicit PAssign_(PExpr*lval, PExpr*de, PExpr*ex);
explicit PAssign_(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
explicit PAssign_(PExpr*lval, PEventStatement*de, PExpr*ex);
virtual ~PAssign_() =0;
const PExpr* lval() const { return lval_; }
PExpr* rval() const { return rval_; }
const PExpr* rval() const { return rval_; }
protected:
NetAssign_* elaborate_lval(Design*, NetScope*scope) const;
NetExpr* elaborate_rval_(Design*, NetScope*, unsigned lv_width,
ivl_variable_type_t type) const;
PExpr* delay_;
PEventStatement*event_;
PExpr* count_;
private:
PExpr* lval_;
PExpr* rval_;
bool is_constant_;
};
class PAssign : public PAssign_ {
@@ -120,8 +115,7 @@ class PAssign : public PAssign_ {
public:
explicit PAssign(PExpr*lval, PExpr*ex);
explicit PAssign(PExpr*lval, PExpr*de, PExpr*ex);
explicit PAssign(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
explicit PAssign(PExpr*lval, PExpr*ex, bool is_constant);
explicit PAssign(PExpr*lval, PEventStatement*de, PExpr*ex);
~PAssign();
virtual void dump(ostream&out, unsigned ind) const;
@@ -135,7 +129,6 @@ class PAssignNB : public PAssign_ {
public:
explicit PAssignNB(PExpr*lval, PExpr*ex);
explicit PAssignNB(PExpr*lval, PExpr*de, PExpr*ex);
explicit PAssignNB(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
~PAssignNB();
virtual void dump(ostream&out, unsigned ind) const;
@@ -340,15 +333,10 @@ class PEventStatement : public Statement {
void set_statement(Statement*st);
virtual void dump(ostream&out, unsigned ind) const;
// Call this with a NULL statement only. It is used to print
// the event expression for inter-assignment event controls.
virtual void dump_inline(ostream&out) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
bool has_aa_term(Design*des, NetScope*scope);
// This method is used to elaborate, but attach a previously
// elaborated statement to the event.
NetProc* elaborate_st(Design*des, NetScope*scope, NetProc*st) const;
@@ -360,8 +348,6 @@ class PEventStatement : public Statement {
Statement*statement_;
};
ostream& operator << (ostream&o, const PEventStatement&obj);
class PForce : public Statement {
public:
Vendored
-17
View File
@@ -24,23 +24,6 @@ fi
AC_SUBST(ident_support)
])# AC_CPP_IDENT
# AX_ENABLE_SUFFIX
# ----------------
# Create the configure option --enable-suffix[=suffix] to generate suffix
# strings for the installed commands. This allows for shared installs of
# different builds. Remember to change the default suffix string to some
# value appropriate for the current version.
AC_DEFUN([AX_ENABLE_SUFFIX],
[AC_ARG_ENABLE([suffix],[Set the installation command suffix],[true],[enable_suffix=no])
if test X$enable_suffix = Xyes; then
install_suffix='-0.9'
elif test X$enable_suffix = Xno; then
install_suffix=''
else
install_suffix="$enable_suffix"
fi
AC_SUBST(install_suffix)
])# AX_ENABLE_SUFFIX
# _AX_C_UNDERSCORES_MATCH_IFELSE(PATTERN, ACTION-IF-MATCH, ACTION-IF-NOMATCH)
# ------------------------------
+31 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2008 Stephen Williams ([email protected])
* Copyright (c) 2002 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
@@ -16,6 +16,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: async.cc,v 1.7 2004/01/18 23:26:54 steve Exp $"
#endif
# include "config.h"
@@ -84,8 +87,34 @@ bool NetProc::is_asynchronous()
bool NetProcTop::is_asynchronous()
{
if (type_ == IVL_PR_INITIAL)
if (type_ == NetProcTop::KINITIAL)
return false;
return statement_->is_asynchronous();
}
/*
* $Log: async.cc,v $
* Revision 1.7 2004/01/18 23:26:54 steve
* The is_combinational function really need not recurse.
*
* Revision 1.6 2003/12/20 00:33:39 steve
* More thorough check that NetEvWait is asynchronous.
*
* Revision 1.5 2003/09/04 20:28:05 steve
* Support time0 resolution of combinational threads.
*
* Revision 1.4 2002/08/18 22:07:16 steve
* Detect temporaries in sequential block synthesis.
*
* Revision 1.3 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.2 2002/07/04 00:24:16 steve
* initial statements are not asynchronous.
*
* Revision 1.1 2002/06/30 02:21:31 steve
* Add structure for asynchronous logic synthesis.
*
*/
+1 -1
View File
@@ -9,7 +9,7 @@
echo "Autoconf in root..."
autoconf -f
for dir in vpi vvp tgt-vvp tgt-fpga tgt-stub tgt-vhdl libveriuser cadpli
for dir in vpip vpi vvp tgt-vvp tgt-fpga tgt-stub libveriuser cadpli
do
echo "Autoconf in $dir..."
( cd ./$dir ; autoconf -f --include=.. )
+4 -6
View File
@@ -20,8 +20,6 @@ SHELL = /bin/sh
VERSION = 0.9.devel
suffix = @install_suffix@
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
@@ -32,7 +30,7 @@ bindir = @bindir@
libdir = @libdir@
includedir = $(prefix)/include
vpidir = @libdir@/ivl$(suffix)
vpidir = @libdir@/ivl
CC = @CC@
INSTALL = @INSTALL@
@@ -78,13 +76,13 @@ distclean: clean
install: all installdirs $(vpidir)/cadpli.vpl $(INSTALL32)
$(vpidir)/cadpli.vpl: ./cadpli.vpl
$(INSTALL_PROGRAM) ./cadpli.vpl $(DESTDIR)$(vpidir)/cadpli.vpl
$(INSTALL_PROGRAM) ./cadpli.vpl $(vpidir)/cadpli.vpl
installdirs: ../mkinstalldirs
$(srcdir)/../mkinstalldirs $(DESTDIR)$(vpidir)
$(srcdir)/../mkinstalldirs $(vpidir)
uninstall: $(UNINSTALL32)
rm -f $(DESTDIR)$(vpidir)/cadpli.vpl
rm -f $(vpidir)/cadpli.vpl
uninstall32:
-2
View File
@@ -10,8 +10,6 @@ AC_SUBST(EXEEXT)
# Combined check for Microsoft-related bogosities; sets WIN32 if found
AX_WIN32
AX_ENABLE_SUFFIX
AC_PROG_INSTALL
AC_CHECK_HEADERS(malloc.h)
+11 -11
View File
@@ -35,16 +35,16 @@ typedef shl_t ivl_dll_t;
#endif
#if defined(__MINGW32__)
static __inline__ ivl_dll_t ivl_dlopen(const char *name)
static inline ivl_dll_t ivl_dlopen(const char *name)
{ return (void *)LoadLibrary(name); }
static __inline__ void *ivl_dlsym(ivl_dll_t dll, const char *nm)
static inline void *ivl_dlsym(ivl_dll_t dll, const char *nm)
{ return (void *)GetProcAddress((HINSTANCE)dll,nm);}
static __inline__ void ivl_dlclose(ivl_dll_t dll)
static inline void ivl_dlclose(ivl_dll_t dll)
{ (void)FreeLibrary((HINSTANCE)dll);}
static __inline__ const char *dlerror(void)
static inline const char *dlerror(void)
{
static char msg[256];
unsigned long err = GetLastError();
@@ -61,10 +61,10 @@ static __inline__ const char *dlerror(void)
}
#elif defined(HAVE_DLFCN_H)
static __inline__ ivl_dll_t ivl_dlopen(const char*name)
static inline ivl_dll_t ivl_dlopen(const char*name)
{ return dlopen(name,RTLD_LAZY); }
static __inline__ void* ivl_dlsym(ivl_dll_t dll, const char*nm)
static inline void* ivl_dlsym(ivl_dll_t dll, const char*nm)
{
void*sym = dlsym(dll, nm);
/* Not found? try without the leading _ */
@@ -73,24 +73,24 @@ static __inline__ void* ivl_dlsym(ivl_dll_t dll, const char*nm)
return sym;
}
static __inline__ void ivl_dlclose(ivl_dll_t dll)
static inline void ivl_dlclose(ivl_dll_t dll)
{ dlclose(dll); }
#elif defined(HAVE_DL_H)
static __inline__ ivl_dll_t ivl_dlopen(const char*name)
static inline ivl_dll_t ivl_dlopen(const char*name)
{ return shl_load(name, BIND_IMMEDIATE, 0); }
static __inline__ void* ivl_dlsym(ivl_dll_t dll, const char*nm)
static inline void* ivl_dlsym(ivl_dll_t dll, const char*nm)
{
void*sym;
int rc = shl_findsym(&dll, nm, TYPE_PROCEDURE, &sym);
return (rc == 0) ? sym : 0;
}
static __inline__ void ivl_dlclose(ivl_dll_t dll)
static inline void ivl_dlclose(ivl_dll_t dll)
{ shl_unload(dll); }
static __inline__ const char*dlerror(void)
static inline const char*dlerror(void)
{ return strerror( errno ); }
#endif
-1
View File
@@ -87,7 +87,6 @@ extern bool debug_eval_tree;
extern bool debug_elaborate;
extern bool debug_synth2;
extern bool debug_optimizer;
extern bool debug_automatic;
/* Path to a directory useful for finding subcomponents. */
extern const char*basedir;
+1 -1
View File
@@ -93,4 +93,4 @@
* junk, and support gcc 3.0. (Stephan Boettcher)
*
*/
#endif /* __config_H */
#endif // __config_H
+1 -3
View File
@@ -92,8 +92,6 @@ AC_C_BIGENDIAN
# $host
AX_ENABLE_SUFFIX
AX_LD_EXTRALIBS
# Compiler option for position independent code, needed when making shared objects.
@@ -124,6 +122,6 @@ AX_C_UNDERSCORES_TRAILING
AX_CPP_IDENT
# XXX disable tgt-fpga for the moment
AC_CONFIG_SUBDIRS(vvp vpi tgt-stub tgt-null tgt-vvp tgt-vhdl libveriuser cadpli)
AC_CONFIG_SUBDIRS(vvp vpi tgt-stub tgt-null tgt-vvp libveriuser cadpli)
AC_OUTPUT(Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
+1 -1
View File
@@ -3,7 +3,7 @@
`ifdef CONSTANTS_VAMS
`else
`define CONSTANTS_VAMS 1
// M_ is a mathematical constant
`define M_E 2.7182818284590452354
`define M_LOG2E 1.4426950408889634074
+34 -24
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2008 Stephen Williams ([email protected])
* Copyright (c) 1998-2005 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
@@ -739,8 +739,7 @@ v }
}
}
#if 0
static void replace_with_mos(Design*des, NetMux*obj, NetLogic::TYPE type)
static void replace_with_bufif(Design*des, NetMux*obj, NetLogic::TYPE type)
{
NetScope*scope = obj->scope();
NetLogic*tmp = new NetLogic(obj->scope(),
@@ -750,7 +749,7 @@ static void replace_with_mos(Design*des, NetMux*obj, NetLogic::TYPE type)
des->add_node(tmp);
connect(obj->pin_Result(), tmp->pin(0));
connect(obj->pin_Data(type==NetLogic::PMOS? 0 : 1), tmp->pin(1));
connect(obj->pin_Data(type==NetLogic::BUFIF0? 0 : 1), tmp->pin(1));
if (obj->width() == 1) {
/* Special case that the expression is 1 bit
@@ -781,11 +780,10 @@ static void replace_with_mos(Design*des, NetMux*obj, NetLogic::TYPE type)
delete obj;
}
#endif
/*
* This detects the case where the mux selects between a value and
* Vz. In this case, replace the device with a mos with the sel
* Vz. In this case, replace the device with a bufif with the sel
* input used to enable the output.
*/
void cprop_functor::lpm_mux(Design*des, NetMux*obj)
@@ -795,34 +793,45 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
if (obj->sel_width() != 1)
return;
#if 0
/*
* This is slower than the actual MUXZ so we are skipping this for now.
* If we had a half mux functor this could be faster and more compact
* so I'm leaving the code for future reference.
*/
/* If the first input is all constant Vz, then replace the
NetMux with an array of NMOS devices, with the enable
NetMux with an array of BUFIF1 devices, with the enable
connected to the select input. */
if (obj->pin_Data(0).nexus()->drivers_constant() &&
obj->pin_Data(0).nexus()->driven_value() == verinum::Vz) {
replace_with_mos(des, obj, NetLogic::NMOS);
bool flag = true;
if (! obj->pin_Data(0).nexus()->drivers_constant()) {
flag = false;
}
if (flag && obj->pin_Data(0).nexus()->driven_value() != verinum::Vz) {
flag = false;
}
if (flag) {
replace_with_bufif(des, obj, NetLogic::BUFIF1);
count += 1;
return;
}
/* If instead the second input is all constant Vz, replace the
NetMux with an array of PMOS devices. */
if (obj->pin_Data(1).nexus()->drivers_constant() &&
obj->pin_Data(1).nexus()->driven_value() == verinum::Vz) {
replace_with_mos(des, obj, NetLogic::PMOS);
NetMux with an array of BUFIF0 devices. */
flag = true;
if (! obj->pin_Data(1).nexus()->drivers_constant()) {
flag = false;
}
if (flag && obj->pin_Data(1).nexus()->driven_value() != verinum::Vz) {
flag = false;
}
if (flag) {
replace_with_bufif(des, obj, NetLogic::BUFIF0);
count += 1;
return;
}
#endif
/* If the select input is constant, then replace with a BUFZ */
bool flag = obj->pin_Sel().nexus()->drivers_constant();
flag = obj->pin_Sel().nexus()->drivers_constant();
verinum::V sel_val = flag? obj->pin_Sel().nexus()->driven_value() : verinum::Vx;
if ((sel_val != verinum::Vz) && (sel_val != verinum::Vx)) {
NetBUFZ*tmp = new NetBUFZ(obj->scope(), obj->name(), obj->width());
@@ -888,7 +897,7 @@ void cprop_dc_functor::lpm_const(Design*des, NetConst*obj)
for (Link*clnk = nex->first_nlink()
; clnk ; clnk = clnk->next_nlink()) {
NetPins*cur;
NetObj*cur;
unsigned pin;
clnk->cur_link(cur, pin);
@@ -914,7 +923,7 @@ void cprop_dc_functor::lpm_const(Design*des, NetConst*obj)
for (Link*clnk = nex->first_nlink()
; clnk ; clnk = clnk->next_nlink()) {
NetPins*cur;
NetObj*cur;
unsigned pin;
clnk->cur_link(cur, pin);
@@ -965,3 +974,4 @@ void cprop(Design*des)
cprop_dc_functor dc;
des->functor(&dc);
}
+16 -138
View File
@@ -27,7 +27,6 @@
# include <iomanip>
# include "netlist.h"
# include "compiler.h"
# include "discipline.h"
# include "ivl_assert.h"
static ostream& operator<< (ostream&o, NetBlock::Type t)
@@ -188,10 +187,6 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
o << " inout";
break;
}
if (ivl_discipline_t dis = get_discipline())
o << " discipline=" << dis->name();
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
if (scope())
o << " scope=" << scope_path(scope());
@@ -241,14 +236,11 @@ void NetNode::dump_node(ostream&o, unsigned ind) const
/* This is the generic dumping of all the signals connected to each
pin of the object. The "this" object is not printed, only the
signals connected to this. */
void NetPins::dump_node_pins(ostream&o, unsigned ind, const char**pin_names) const
void NetObj::dump_node_pins(ostream&o, unsigned ind) const
{
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
o << setw(ind) << "" << idx;
if (pin_names && pin_names[idx])
o << " " << pin_names[idx];
else
o << " pin" << idx;
o << setw(ind) << "" << idx << " " << pin(idx).get_name()
<< "<" << pin(idx).get_inst() << ">";
switch (pin(idx).get_dir()) {
case Link::PASSIVE:
@@ -297,14 +289,7 @@ void NetAddSub::dump_node(ostream&o, unsigned ind) const
o << setw(ind) << "" << "Adder (NetAddSub): " << name()
<< " width=" << width() << " pin_count=" << pin_count()
<< endl;
static const char* pin_names[] = {
"Cout ",
"DataA ",
"DataB ",
"Result"
};
dump_node_pins(o, ind+4, pin_names);
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
@@ -317,22 +302,6 @@ void NetArrayDq::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
void NetCastInt::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Cast to int. (NetCastInt): " <<
name() << " width=" << width() << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetCastReal::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Cast to real (NetCastReal): " <<
name() << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetCLShift::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Combinatorial shift (NetCLShift): " <<
@@ -343,9 +312,7 @@ void NetCLShift::dump_node(ostream&o, unsigned ind) const
void NetCompare::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_COMPARE (NetCompare "
<< (get_signed()? "signed" : "unsigned") << "): "
<< name() << endl;
o << setw(ind) << "" << "LPM_COMPARE (NetCompare): " << name() << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
@@ -579,14 +546,8 @@ void NetReplicate::dump_node(ostream&o, unsigned ind) const
void NetSignExtend::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "NetSignExtend: " << name();
if (rise_time())
o << " #(" << *rise_time()
<< "," << *fall_time()
<< "," << *decay_time() << ")";
else
o << " #(.,.,.)";
o << " output width=" << width_ << endl;
o << setw(ind) << "" << "NetSignExtend: "
<< name() << " output width=" << width_ << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
@@ -702,11 +663,11 @@ void NetUDP::dump_node(ostream&o, unsigned ind) const
void NetProcTop::dump(ostream&o, unsigned ind) const
{
switch (type_) {
case IVL_PR_INITIAL:
case NetProcTop::KINITIAL:
o << "initial /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
break;
case IVL_PR_ALWAYS:
case NetProcTop::KALWAYS:
o << "always /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
break;
@@ -720,28 +681,6 @@ void NetProcTop::dump(ostream&o, unsigned ind) const
statement_->dump(o, ind+2);
}
void NetAnalogTop::dump(ostream&o, unsigned ind) const
{
switch (type_) {
case IVL_PR_INITIAL:
o << "analog initial /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
break;
case IVL_PR_ALWAYS:
o << "analog /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
break;
}
statement_->dump(o, ind+2);
}
void NetAlloc::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "// allocate storage : " << scope_path(scope_) << endl;
}
void NetAssign_::dump_lval(ostream&o) const
{
if (sig_) {
@@ -793,11 +732,6 @@ void NetAssignNB::dump(ostream&o, unsigned ind) const
if (const NetExpr*de = get_delay())
o << "#(" << *de << ") ";
if (count_)
o << "repeat(" << *count_ << ") ";
if (event_) {
o << *event_;
}
o << *rval() << ";" << endl;
@@ -885,15 +819,6 @@ void NetCondit::dump(ostream&o, unsigned ind) const
}
}
void NetContribution::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "";
lval_->dump(o);
o << " <+ ";
rval_->dump(o);
o << ";" << endl;
}
void NetDeassign::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "deassign ";
@@ -951,25 +876,6 @@ void NetEvWait::dump(ostream&o, unsigned ind) const
o << setw(ind+2) << "" << "/* noop */ ;" << endl;
}
ostream& operator << (ostream&out, const NetEvWait&obj)
{
obj.dump_inline(out);
return out;
}
void NetEvWait::dump_inline(ostream&o) const
{
o << "@(";
if (nevents() > 0)
o << event(0)->name();
for (unsigned idx = 1 ; idx < nevents() ; idx += 1)
o << " or " << event(idx)->name();
o << ") ";
}
void NetForce::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "force ";
@@ -983,11 +889,6 @@ void NetForever::dump(ostream&o, unsigned ind) const
statement_->dump(o, ind+2);
}
void NetFree::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "// free storage : " << scope_path(scope_) << endl;
}
void NetFuncDef::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "function definition for " << scope_path(scope_) << endl;
@@ -1081,7 +982,6 @@ void NetScope::dump(ostream&o) const
o << " generate block";
break;
}
if (is_auto()) o << " (automatic)";
o << endl;
for (unsigned idx = 0 ; idx < attr_cnt() ; idx += 1)
@@ -1098,8 +998,6 @@ void NetScope::dump(ostream&o) const
; pp != parameters.end() ; pp ++) {
o << " parameter ";
o << pp->second.type << " ";
if ((*pp).second.signed_flag)
o << "signed ";
@@ -1149,7 +1047,7 @@ void NetScope::dump(ostream&o) const
/* Dump the saved defparam assignments here. */
{
list<pair<pform_name_t,NetExpr*> >::const_iterator pp;
map<pform_name_t,NetExpr*>::const_iterator pp;
for (pp = defparams.begin()
; pp != defparams.end() ; pp ++ ) {
o << " defparam " << (*pp).first << " = " <<
@@ -1157,15 +1055,6 @@ void NetScope::dump(ostream&o) const
}
}
{
list<pair<list<hname_t>,NetExpr*> >::const_iterator pp;
for (pp = defparams_later.begin()
; pp != defparams_later.end() ; pp ++ ) {
o << " defparam(later) " << pp->first << " = " <<
*(pp->second) << ";" << endl;
}
}
/* Dump the events in this scope. */
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_) {
o << " event " << cur->name() << "; nprobe="
@@ -1174,9 +1063,12 @@ void NetScope::dump(ostream&o) const
}
// Dump the signals,
for (signals_map_iter_t cur = signals_map_.begin()
; cur != signals_map_.end() ; cur ++) {
cur->second->dump_net(o, 4);
if (signals_) {
NetNet*cur = signals_->sig_next_;
do {
cur->dump_net(o, 4);
cur = cur->sig_next_;
} while (cur != signals_->sig_next_);
}
// Dump specparams
@@ -1265,18 +1157,6 @@ void NetExpr::dump(ostream&o) const
o << "(?" << typeid(*this).name() << "?)";
}
void NetEAccess::dump(ostream&o) const
{
o << nature_->name() << "." << nature_->access() << "(";
assert(branch_);
if (branch_->pin(0).is_linked())
o << branch_->pin(0).nexus()->name();
o << ", ";
if (branch_->pin(1).is_linked())
o << branch_->pin(1).nexus()->name();
o << ")";
}
void NetEBinary::dump(ostream&o) const
{
if (op_ == 'm' || op_ == 'M') {
@@ -1517,6 +1397,4 @@ void Design::dump(ostream&o) const
for (const NetProcTop*idx = procs_ ; idx ; idx = idx->next_)
idx->dump(o, 0);
for (const NetAnalogTop*idx = aprocs_ ; idx ; idx = idx->next_)
idx->dump(o, 0);
}
-149
View File
@@ -1,149 +0,0 @@
Developer Quick Start for Icarus Verilog
The documentation for getting, building and installing Icarus Verilog
is kept and maintained at the iverilog documentation wiki at
<http://iverilog.wikia.com>. See the Installation Guide for getting
the current source from the git repository (and how to use the git
repository) and see the Developer Guide for instructions on
participating in the Icarus Verilog development process. That
information will not be repeated here.
What this documentation *will* cover is the gross structure of the
Icarus Verilog compiler source. This will help orient you to the
source code itself, so that you can find the global parts where you
can look for even better detail.
* Compiler Components
- The compiler driver (driver/)
This is the binary that is installed as "iverilog". This program takes
the command line arguments and assembles invocations of all the other
subcommands to perform the steps of compilation.
- The preprocessor (ivlpp/)
This implements the Verilog pre-processor. In Icarus Verilog, the
compiler directives `define, `include, `ifdef and etc. are implemented
in an external program. The ivlpp/ directory contains the source for
this program.
- The core compiler (this directory)
The "ivl" program is the core that does all the Verilog compiler
processing that is not handled elsewhere. This is the main core of the
Icarus Verilog compiler, not the runtime. See below for more details
on the core itself.
- The loadable code generators (tgt-*/)
This core compiler, after it is finished with parsing and semantic
analysis, uses loadable code generators to emit code for supported
targets. The tgt-*/ directories contains the source for the target
code generators that are bundled with Icarus Verilog. The tgt-vvp/
directory in particular contains the code generator for the vvp
runtime.
* Runtime Components
- The vvp runtime (vvp/)
This program implements the runtime environment for Icarus
Verilog. It implements the "vvp" command described in the user
documentation. See the vvp/ subdirectory for further developer
documentation.
- The system tasks implementations (vpi/)
The standard Verilog system tasks are implemented using VPI (PLI-2)
and the source is in this subdirectory.
- The PLI-1 compatibility library (libveriuser/)
The Icarus Verilog support for the deprecated PLI-1 is in this
subdirectory. The vvp runtime does not directly support the
PLI-1. Instead, the libveriuser library emulates it using the builtin
PLI-2 support.
- The Cadence PLI module compatibility module (cadpli/)
It is possible in some specialized situations to load and execute
PLI-1 code written for Verilog-XL. This directory contains the source
for the module that provides the Cadence PLI interface.
* The Core Compiler
The "ivl" binary is the core compiler that does the heavy lifting of
compiling the Verilog source (including libraries) and generating the
output. This is the most complex component of the Icarus Verilog
compilation system.
The process in the abstract starts with the Verilog lexical analysis
and parsing to generate an internal "pform". The pform is then
translated by elaboration into the "netlist" form. The netlist is
processed by some functors (which include some optimizations and
optional synthesis) then is translated into the ivl_target internal
form. And finally, the ivl_target form is passed via the ivl_target.h
API to the code generators.
- Lexical Analysis
Lexical analysis and parsing use the tools "flex", "gperf", and
"bison". The "flex" input file "lexor.lex" recognizes the tokens in
the input stream. This is called "lexical analysis". The lexical
analyzer also does some processing of compiler directives that are not
otherwise taken care of by the external preprocessor. The lexical
analyzer uses a table of keywords that is generated using the "gperf"
program and the input file "lexor_keywords.gperf". This table allows
the lexical analyzer to efficiently check input words with the rather
large set of potential keywords.
- Parsing
The parser input file "parse.y" is passed to the "bison" program to
generate the parser. The parser uses the functions in parse*.h,
parse*.cc, pform.h, and pform*.cc to generate the pform from the
stream of input tokens. The pform is what compiler writers call a
"decorated parse tree".
The pform itself is described by the classes in the header files
"PScope.h", "Module.h", "PGenerate.h", "Statement.h", and
"PExpr.h". The implementations of the classes in those header files
are in the similarly named C++ files.
- Elaboration
Elaboration transforms the pform to the netlist form. Elaboration is
conceptually divided into several major steps: Scope elaboration,
parameter overrides and defparam propagation, signal elaboration, and
statement and expression elaboration.
The elaboration of scopes and parameter overrides and defparam
propagation are conceptually separate, but are in practice
intermingled. The elaboration of scopes scans the pform to find and
instantiate all the scopes of the design. New scopes are created by
instantiation of modules (starting with the root instances) by user
defined tasks and functions, named blocks, and generate schemes. The
elaborate_scope methods implement scope elaboration, and the
elab_scope.cc source file has the implementations of those
methods.
The elaborate.cc source file contains the initial calls to the
elaborate_scope for the root scopes to get the process started. In
particular, see the "elaborate" function near the bottom of the
elaborate.cc source file. The calls to Design::make_root_scope create
the initial root scopes, and the creation and enqueue of the
elaborate_root_scope_t work items primes the scope elaboration work
list.
Intermingled in the work list are defparms work items that call the
Design::run_defparams and Design::evaluate_parameters methods that
override and evaluate parameters. The override and evaluation of
parameters must be intermingled with the elaboration of scopes because
the exact values of parameters may impact the scopes created (imagine
generate schemes and instance arrays) and the created scopes in turn
create new parameters that need override and evaluation.
+6 -6
View File
@@ -19,8 +19,8 @@
# include "discipline.h"
nature_t::nature_t(perm_string name__, perm_string access__)
: name_(name__), access_(access__)
nature_t::nature_t(perm_string name, perm_string access)
: name_(name), access_(access)
{
}
@@ -28,12 +28,12 @@ nature_t::~nature_t()
{
}
ivl_discipline_s::ivl_discipline_s(perm_string name__, ivl_dis_domain_t domain__,
nature_t*pot, nature_t*flow__)
: name_(name__), domain_(domain__), potential_(pot), flow_(flow__)
discipline_t::discipline_t(perm_string name, ddomain_t domain,
nature_t*pot, nature_t*flow)
: name_(name), domain_(domain), potential_(pot), flow_(flow)
{
}
ivl_discipline_s::~ivl_discipline_s()
discipline_t::~discipline_t()
{
}
+11 -13
View File
@@ -28,10 +28,10 @@
# include "StringHeap.h"
# include <iostream>
# include <map>
# include "ivl_target.h"
# include "LineInfo.h"
extern std::ostream& operator << (std::ostream&, ivl_dis_domain_t);
typedef enum { DD_NONE, DD_DISCRETE, DD_CONTINUOUS } ddomain_t;
extern std::ostream& operator << (std::ostream&, ddomain_t);
class nature_t : public LineInfo {
public:
@@ -47,31 +47,29 @@ class nature_t : public LineInfo {
perm_string access_;
};
class ivl_discipline_s : public LineInfo {
class discipline_t : public LineInfo {
public:
explicit ivl_discipline_s (perm_string name, ivl_dis_domain_t dom,
nature_t*pot, nature_t*flow);
~ivl_discipline_s();
explicit discipline_t (perm_string name, ddomain_t dom,
nature_t*pot, nature_t*flow);
~discipline_t();
perm_string name() const { return name_; }
ivl_dis_domain_t domain() const { return domain_; }
ddomain_t domain() const { return domain_; }
const nature_t*potential() const { return potential_; }
const nature_t*flow() const { return flow_; }
private:
perm_string name_;
ivl_dis_domain_t domain_;
ddomain_t domain_;
nature_t*potential_;
nature_t*flow_;
private: // not implemented
ivl_discipline_s(const ivl_discipline_s&);
ivl_discipline_s& operator = (const ivl_discipline_s&);
discipline_t(const discipline_t&);
discipline_t& operator = (const discipline_t&);
};
extern map<perm_string,nature_t*> natures;
extern map<perm_string,ivl_discipline_t> disciplines;
// Map access function name to the nature that it accesses.
extern map<perm_string,nature_t*> access_function_nature;
extern map<perm_string,discipline_t*> disciplines;
#endif
+4 -9
View File
@@ -20,8 +20,6 @@ SHELL = /bin/sh
VERSION = 0.9.devel
suffix = @install_suffix@
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
@@ -29,8 +27,6 @@ datarootdir = @datarootdir@
VPATH = $(srcdir)
suffix = @install_suffix@
bindir = $(exec_prefix)/bin
libdir = $(exec_prefix)/lib
includedir = $(prefix)/include
@@ -69,7 +65,6 @@ main.o: main.c config.h
config.h: config.h.in
sed -e 's;@IVLCC@;@CC@;' -e 's;@IVLCXX@;@CXX@;' \
-e 's;@SUFFIX@;$(suffix);g' \
-e 's;@IVLCFLAGS@;@CXXFLAGS@;' \
-e 's;@SHARED@;@shared@;' $< > $@
@@ -78,13 +73,13 @@ res.o: res.rc
windres -i res.rc -o res.o
#
install: all installdirs $(bindir)/iverilog-vpi$(suffix)@EXEEXT@
install: all installdirs $(bindir)/iverilog-vpi@EXEEXT@
$(bindir)/iverilog-vpi$(suffix)@EXEEXT@: ./iverilog-vpi@EXEEXT@
$(INSTALL_PROGRAM) ./iverilog-vpi@EXEEXT@ $(bindir)/iverilog-vpi$(suffix)@EXEEXT@
$(bindir)/iverilog-vpi@EXEEXT@: ./iverilog-vpi@EXEEXT@
$(INSTALL_PROGRAM) ./iverilog-vpi@EXEEXT@ $(bindir)/iverilog-vpi@EXEEXT@
installdirs: ../mkinstalldirs
$(srcdir)/../mkinstalldirs $(bindir)
uninstall:
rm -f $(bindir)/iverilog-vpi$(suffix)@EXEEXT@
rm -f $(bindir)/iverilog-vpi@EXEEXT@
+1 -2
View File
@@ -5,5 +5,4 @@
#define IVERILOG_VPI_CXX "@IVLCXX@"
#define IVERILOG_VPI_CFLAGS " @IVLCFLAGS@"
#define IVERILOG_VPI_LDFLAGS "@SHARED@"
#define IVERILOG_VPI_LDLIBS "-lveriuser@SUFFIX@ -lvpi@SUFFIX@"
#define IVERILOG_SUFFIX "@SUFFIX@"
#define IVERILOG_VPI_LDLIBS "-lveriuser -lvpi"
+8 -8
View File
@@ -87,9 +87,9 @@ static void myExit(int exitVal)
static void usage()
{
fprintf(stderr,"usage: iverilog-vpi" IVERILOG_SUFFIX " [src and obj files]...\n");
fprintf(stderr," or iverilog-vpi" IVERILOG_SUFFIX " -mingw=dir\n");
fprintf(stderr," or iverilog-vpi" IVERILOG_SUFFIX " -ivl=dir\n");
fprintf(stderr,"usage: iverilog-vpi [src and obj files]...\n");
fprintf(stderr," or iverilog-vpi -mingw=dir\n");
fprintf(stderr," or iverilog-vpi -ivl=dir\n");
myExit(1);
}
@@ -384,7 +384,7 @@ static int parse(int argc, char *argv[])
/* Check for the --install-dir option */
else if (stricmp("--install-dir", argv[idx]) == 0) {
setup_ivl_environment();
printf("%s\\\\lib\\\\ivl" IVERILOG_SUFFIX "\\\\.\n", gstr.pIVL);
printf("%s\\\\lib\\\\ivl\\\\.\n", gstr.pIVL);
myExit(0);
}
/* This is different than iverilog-vpi.sh, we don't
@@ -444,14 +444,14 @@ static void checkIvlDir(char *root)
initDynString(&path);
assign(&path,gstr.pIVL);
appendBackSlash(&path);
append(&path,"bin\\vvp" IVERILOG_SUFFIX ".exe");
append(&path,"bin\\vvp.exe");
irv = _stat(path,&stat_buf);
deInitDynString(path);
if (irv) {
fprintf(stderr,"error: %s does not appear to be the valid root directory of\n",root);
fprintf(stderr," Icarus Verilog. Use the -ivl option of iverilog-vpi" IVERILOG_SUFFIX " to\n");
fprintf(stderr," Icarus Verilog. Use the -ivl option of iverilog-vpi.exe to\n");
fprintf(stderr," point to the Icarus Verilog root directory. For a Windows\n");
fprintf(stderr," command shell the option would be something like -ivl=c:\\iverilog\n");
fprintf(stderr," For a Cygwin shell the option would be something like\n");
@@ -503,7 +503,7 @@ static void setup_ivl_environment()
SetRegistryKey(IVL_REGKEY_IVL,gstr.pIVL);
} else if (!GetRegistryKey(IVL_REGKEY_IVL,&gstr.pIVL)) {
fprintf(stderr,"error: can not locate the Icarus Verilog root directory, use the -ivl option\n");
fprintf(stderr," of iverilog-vpi" IVERILOG_SUFFIX " to point to the Icarus Verilog root directory.\n");
fprintf(stderr," of iverilog-vpi.exe to point to the Icarus Verilog root directory.\n");
fprintf(stderr," For a Windows command shell the option would be something like\n");
fprintf(stderr," -ivl=c:\\iverilog For a Cygwin shell the option would be something\n");
fprintf(stderr," like -ivl=c:\\\\iverilog\n");
@@ -516,7 +516,7 @@ static void setup_ivl_environment()
append(&gstr.pCFLAGS,gstr.pIVL);
appendBackSlash(&gstr.pCFLAGS);
append(&gstr.pCFLAGS, "\\");
append(&gstr.pCFLAGS,"include" IVERILOG_SUFFIX);
append(&gstr.pCFLAGS,"include");
/* Build up the LDFLAGS option string */
assign(&gstr.pLDLIBS,"-L");
+15 -17
View File
@@ -20,8 +20,6 @@ SHELL = /bin/sh
VERSION = 0.9.devel
suffix = @install_suffix@
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
@@ -70,7 +68,7 @@ cfparse.h cfparse.c: cfparse.y
main.o: main.c globals.h ../version.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c -DIVL_ROOT='"@libdir@/ivl$(suffix)"' -DIVL_INC='"@includedir@"' -DIVL_LIB='"@libdir@"' -DDLLIB='"@DLLIB@"' $(srcdir)/main.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c -DIVL_ROOT='"@libdir@/ivl"' -DIVL_INC='"@includedir@"' -DIVL_LIB='"@libdir@"' -DDLLIB='"@DLLIB@"' $(srcdir)/main.c
build_string.o: build_string.c globals.h
cflexor.o: cflexor.c cfparse.h cfparse_misc.h globals.h
@@ -84,35 +82,35 @@ iverilog.pdf: iverilog.ps
ifeq (@MINGW32@,yes)
ifeq ($(MAN),none)
INSTALL_DOC = $(mandir)/man1/iverilog$(suffix).1
INSTALL_DOC = $(mandir)/man1/iverilog.1
else
ifeq ($(PS2PDF),none)
INSTALL_DOC = $(mandir)/man1/iverilog$(suffix).1
INSTALL_DOC = $(mandir)/man1/iverilog.1
else
INSTALL_DOC = $(prefix)/iverilog$(suffix).pdf $(mandir)/man1/iverilog$(suffix).1
INSTALL_DOC = $(prefix)/iverilog.pdf $(mandir)/man1/iverilog.1
all: iverilog.pdf
endif
endif
INSTALL_DOCDIR = $(mandir)/man1
else
INSTALL_DOC = $(mandir)/man1/iverilog$(suffix).1
INSTALL_DOC = $(mandir)/man1/iverilog.1
INSTALL_DOCDIR = $(mandir)/man1
endif
install: all installdirs $(bindir)/iverilog$(suffix)@EXEEXT@ $(INSTALL_DOC)
install: all installdirs $(bindir)/iverilog@EXEEXT@ $(INSTALL_DOC)
$(bindir)/iverilog$(suffix)@EXEEXT@: ./iverilog@EXEEXT@
$(INSTALL_PROGRAM) ./iverilog@EXEEXT@ $(DESTDIR)$(bindir)/iverilog$(suffix)@EXEEXT@
$(bindir)/iverilog@EXEEXT@: ./iverilog@EXEEXT@
$(INSTALL_PROGRAM) ./iverilog@EXEEXT@ $(bindir)/iverilog@EXEEXT@
$(mandir)/man1/iverilog$(suffix).1: $(srcdir)/iverilog.man
$(INSTALL_DATA) $(srcdir)/iverilog.man $(DESTDIR)$(mandir)/man1/iverilog$(suffix).1
$(mandir)/man1/iverilog.1: $(srcdir)/iverilog.man
$(INSTALL_DATA) $(srcdir)/iverilog.man $(mandir)/man1/iverilog.1
$(prefix)/iverilog$(suffix).pdf: iverilog.pdf
$(INSTALL_DATA) iverilog.pdf $(prefix)/iverilog$(suffix).pdf
$(prefix)/iverilog.pdf: iverilog.pdf
$(INSTALL_DATA) iverilog.pdf $(prefix)/iverilog.pdf
installdirs: ../mkinstalldirs
$(srcdir)/../mkinstalldirs $(DESTDIR)$(bindir) $(DESTDIR)$(INSTALL_DOCDIR)
$(srcdir)/../mkinstalldirs $(bindir) $(INSTALL_DOCDIR)
uninstall:
rm -f $(DESTDIR)$(bindir)/iverilog$(suffix)@EXEEXT@
rm -f $(DESTDIR)$(mandir)/man1/iverilog$(suffix).1 $(DESTDIR)$(prefix)/iverilog$(suffix).pdf
rm -f $(bindir)/iverilog@EXEEXT@
rm -f $(mandir)/man1/iverilog.1 $(prefix)/iverilog.pdf
+1 -1
View File
@@ -149,7 +149,7 @@ int cmdfile_stack_ptr = 0;
cflval.text = trim_trailing_white(yytext, 0);
BEGIN(0);
return TOK_STRING; }
/* Fallback match. */
. { return yytext[0]; }
+11 -7
View File
@@ -14,7 +14,7 @@ iverilog - Icarus Verilog compiler
\fIiverilog\fP is a compiler that translates Verilog source code into
executable programs for simulation, or other netlist formats for
further processing. The currently supported targets are \fIvvp\fP for
simulation, and \fIfpga\fP for synthesis. Other target
simulation, and \fIxnf\fP and \fIfpga\fP for synthesis. Other target
types are added as code generators are implemented.
.SH OPTIONS
@@ -212,18 +212,17 @@ 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.
.TP 8
.B xnf
This is the Xilinx Netlist Format used by many tools for placing
devices in FPGAs or other programmable devices. This target is
obsolete, use the \fBfpga\fP target instead.
.TP 8
.B fpga
This is a synthesis target that supports a variety of fpga devices,
mostly by EDIF format output. The Icarus Verilog fpga code generator
can generate complete designs or EDIF macros that can in turn be
imported into larger designs by other tools. The \fBfpga\fP target
implies the synthesis \fB-S\fP flag.
.TP 8
.B vhdl
This target produces a VHDL translation of the Verilog netlist. The
output is a single file containing VHDL entities corresponding to
the modules in the Verilog source code. Note that only a subset of
the Verilog language is supported. See the wiki for more information.
.SH "WARNING TYPES"
These are the types of warnings that can be selected by the \fB-W\fP
@@ -413,6 +412,11 @@ To compile and run explicitly using the vvp runtime:
iverilog -ohello.vvp -tvvp hello.v
To compile hello.v to a file in XNF-format called hello.xnf
iverilog -txnf -ohello.xnf hello.v
.SH "AUTHOR"
.nf
Steve Williams ([email protected])
+77 -142
View File
@@ -51,7 +51,6 @@ const char HELP[] =
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <sys/types.h>
@@ -107,7 +106,7 @@ const char*npath = 0;
const char*targ = "vvp";
const char*depfile = 0;
const char*generation = "2005";
const char*generation = "2x";
const char*gen_specify = "specify";
const char*gen_xtypes = "xtypes";
const char*gen_icarus = "icarus-misc";
@@ -260,113 +259,18 @@ static const char*my_tempfile(const char*str, FILE**fout)
return pathbuf;
}
static int t_version_only(void)
{
remove(source_path);
free(source_path);
fflush(0);
snprintf(tmp, sizeof tmp, "%s%civlpp -V", pbase, sep);
system(tmp);
fflush(0);
snprintf(tmp, sizeof tmp, "%s%civl -V -C%s -C%s", pbase, sep,
iconfig_path, iconfig_common_path);
system(tmp);
if ( ! getenv("IVERILOG_ICONFIG")) {
remove(iconfig_path);
free(iconfig_path);
remove(defines_path);
free(defines_path);
remove(compiled_defines_path);
free(compiled_defines_path);
}
return 0;
}
static void build_preprocess_command(int e_flag)
{
snprintf(tmp, sizeof tmp, "%s%civlpp %s%s -F%s -f%s -p%s ",
pbase,sep, verbose_flag?" -v":"",
e_flag?"":" -L", defines_path, source_path,
compiled_defines_path);
}
static int t_preprocess_only(void)
{
int rc;
char*cmd;
unsigned ncmd;
build_preprocess_command(1);
ncmd = strlen(tmp);
cmd = malloc(ncmd+1);
strcpy(cmd, tmp);
if (strcmp(opath,"-") != 0) {
snprintf(tmp, sizeof tmp, " > %s", opath);
cmd = realloc(cmd, ncmd+strlen(tmp)+1);
strcpy(cmd+ncmd, tmp);
ncmd += strlen(tmp);
}
if (verbose_flag)
printf("preprocess: %s\n", cmd);
rc = system(cmd);
remove(source_path);
free(source_path);
if ( ! getenv("IVERILOG_ICONFIG")) {
remove(iconfig_path);
free(iconfig_path);
remove(defines_path);
free(defines_path);
remove(compiled_defines_path);
free(compiled_defines_path);
}
if (rc != 0) {
if (WIFEXITED(rc)) {
fprintf(stderr, "errors preprocessing Verilog program.\n");
return WEXITSTATUS(rc);
}
fprintf(stderr, "Command signaled: %s\n", cmd);
free(cmd);
return -1;
}
free(cmd);
return 0;
}
/*
* This is the default target type. It looks up the bits that are
* needed to run the command from the configuration file (which is
* already parsed for us) so we can handle must of the generic cases.
*/
static int t_compile()
static int t_default(char*cmd, unsigned ncmd)
{
unsigned rc;
/* Start by building the preprocess command line. */
build_preprocess_command(0);
size_t ncmd = strlen(tmp);
char*cmd = malloc(ncmd + 1);
strcpy(cmd, tmp);
#ifdef __MINGW32__
unsigned ncmd_start = ncmd;
#else
int rtn;
#endif
/* Build the ivl command and pipe it to the preprocessor. */
snprintf(tmp, sizeof tmp, " | %s/ivl", base);
rc = strlen(tmp);
cmd = realloc(cmd, ncmd+rc+1);
@@ -419,33 +323,28 @@ static int t_compile()
rc = system(cmd);
if ( ! getenv("IVERILOG_ICONFIG")) {
remove(source_path);
free(source_path);
remove(iconfig_path);
free(iconfig_path);
remove(defines_path);
free(defines_path);
remove(compiled_defines_path);
free(compiled_defines_path);
}
#ifdef __MINGW32__ /* MinGW just returns the exit status, so return it! */
free(cmd);
return rc;
#else
rtn = 0;
if (rc != 0) {
if (rc == 127) {
fprintf(stderr, "Failed to execute: %s\n", cmd);
rtn = 1;
} else if (WIFEXITED(rc)) {
rtn = WEXITSTATUS(rc);
} else {
fprintf(stderr, "Command signaled: %s\n", cmd);
rtn = -1;
return 1;
}
if (WIFEXITED(rc))
return WEXITSTATUS(rc);
fprintf(stderr, "Command signaled: %s\n", cmd);
return -1;
}
free(cmd);
return rtn;
return 0;
#endif
}
@@ -606,7 +505,7 @@ int process_generation(const char*name)
" 2005 -- IEEE1364-2005\n"
"Other generation flags:\n"
" specify | no-specify\n"
" verilog-ams | no-verilog-ams\n"
" verilog-ams | no-verinlog-ams\n"
" std-include | no-std-include\n"
" xtypes | no-xtypes\n"
" icarus-misc | no-icarus-misc\n"
@@ -623,7 +522,7 @@ int process_generation(const char*name)
void add_sft_file(const char *module)
{
char *file;
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)
@@ -633,6 +532,8 @@ void add_sft_file(const char *module)
int main(int argc, char **argv)
{
char*cmd;
unsigned ncmd;
int e_flag = 0;
int version_flag = 0;
int opt, idx, rc;
@@ -752,7 +653,7 @@ int main(int argc, char **argv)
case 'c':
case 'f':
add_cmd_file(optarg);
break;
break;
case 'D':
process_define(optarg);
break;
@@ -771,9 +672,9 @@ int main(int argc, char **argv)
if (rc != 0)
return -1;
break;
case 'h':
fprintf(stderr, "%s\n", HELP);
return 1;
case 'h':
fprintf(stderr, "%s\n", HELP);
return 1;
case 'I':
process_include_dir(optarg);
@@ -846,6 +747,9 @@ int main(int argc, char **argv)
printf("Icarus Verilog version " VERSION " (" VERSION_TAG ")\n\n");
printf("Copyright 1998-2008 Stephen Williams\n");
puts(NOTICE);
if (version_flag)
return 0;
}
/* Make a common conf file path to reflect the target. */
@@ -860,18 +764,9 @@ int main(int argc, char **argv)
how to handle them. */
fprintf(iconfig_file, "sys_func:%s%csystem.sft\n", base, sep);
/* If verilog-2005 is enabled or icarus-misc or verilog-ams,
* then include the v2005_math library. */
if (strcmp(generation, "2005") == 0 ||
strcmp(gen_icarus, "icarus-misc") == 0 ||
strcmp(gen_verilog_ams, "verilog-ams") == 0) {
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) {
/* If verilog-ams is enabled, then include the va_math module
as well. */
if (strcmp(gen_verilog_ams,"verilog-ams") == 0) {
fprintf(iconfig_file, "sys_func:%s%cva_math.sft\n", base, sep);
fprintf(iconfig_file, "module:va_math\n");
}
@@ -928,11 +823,60 @@ int main(int argc, char **argv)
fclose(defines_file);
defines_file = 0;
if (source_count == 0 && !version_flag) {
if (source_count == 0) {
fprintf(stderr, "%s: no source files.\n\n%s\n", argv[0], HELP);
return 1;
}
/* Start building the preprocess command line. */
sprintf(tmp, "%s%civlpp %s%s -F%s -f%s -p%s ", pbase,sep,
verbose_flag?" -v":"",
e_flag?"":" -L", defines_path, source_path,
compiled_defines_path);
ncmd = strlen(tmp);
cmd = malloc(ncmd + 1);
strcpy(cmd, tmp);
/* If the -E flag was given on the command line, then all we
do is run the preprocessor and put the output where the
user wants it. */
if (e_flag) {
int rc;
if (strcmp(opath,"-") != 0) {
sprintf(tmp, " > %s", opath);
cmd = realloc(cmd, ncmd+strlen(tmp)+1);
strcpy(cmd+ncmd, tmp);
ncmd += strlen(tmp);
}
if (verbose_flag)
printf("preprocess: %s\n", cmd);
rc = system(cmd);
remove(source_path);
fclose(iconfig_file);
if ( ! getenv("IVERILOG_ICONFIG")) {
remove(iconfig_path);
remove(defines_path);
remove(compiled_defines_path);
}
if (rc != 0) {
if (WIFEXITED(rc)) {
fprintf(stderr, "errors preprocessing Verilog program.\n");
return WEXITSTATUS(rc);
}
fprintf(stderr, "Command signaled: %s\n", cmd);
return -1;
}
return 0;
}
fprintf(iconfig_file, "iwidth:%u\n", integer_width);
/* Write the preprocessor command needed to preprocess a
@@ -944,16 +888,7 @@ int main(int argc, char **argv)
/* Done writing to the iconfig file. Close it now. */
fclose(iconfig_file);
/* If we're only here for the version output, then we're done. */
if (version_flag)
return t_version_only();
return t_default(cmd, ncmd);
/* If the -E flag was given on the command line, then all we
do is run the preprocessor and put the output where the
user wants it. */
if (e_flag)
return t_preprocess_only();
/* Otherwise, this is a full compile. */
return t_compile();
return 0;
}
+2 -20
View File
@@ -21,16 +21,6 @@
# include "netlist.h"
# include <cassert>
# include <stdlib.h>
# include "ivl_assert.h"
NetEAccess* NetEAccess::dup_expr() const
{
NetEAccess*tmp = new NetEAccess(branch_, nature_);
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetEBComp* NetEBComp::dup_expr() const
{
@@ -94,8 +84,8 @@ NetESFunc* NetESFunc::dup_expr() const
tmp->cast_signed(has_sign());
for (unsigned idx = 0 ; idx < nparms() ; idx += 1) {
assert(parm(idx));
tmp->parm(idx, parm(idx)->dup_expr());
assert(tmp->parm(idx));
tmp->parm(idx, tmp->parm(idx)->dup_expr());
}
tmp->set_line(*this);
@@ -138,14 +128,6 @@ NetEUFunc* NetEUFunc::dup_expr() const
return tmp;
}
NetEUBits* NetEUBits::dup_expr() const
{
NetEUBits*tmp = new NetEUBits(op_, expr_->dup_expr());
assert(tmp);
tmp->set_line(*this);
return tmp;
}
NetEUnary* NetEUnary::dup_expr() const
{
NetEUnary*tmp = new NetEUnary(op_, expr_->dup_expr());
+2 -1
View File
@@ -115,7 +115,7 @@ NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
const NetExpr*par = 0;
NetEvent* eve = 0;
symbol_search(this, des, scope, path_, sig, mem, par, eve);
symbol_search(des, scope, path_, sig, mem, par, eve);
if (mem != 0) {
@@ -211,3 +211,4 @@ NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
* Check lvalue of procedural continuous assign (PR#29)
*
*/
+305 -1246
View File
File diff suppressed because it is too large Load Diff
+103 -72
View File
@@ -152,7 +152,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
const NetExpr*par = 0;
NetEvent* eve = 0;
symbol_search(this, des, scope, path_, reg, par, eve);
symbol_search(des, scope, path_, reg, par, eve);
if (reg == 0) {
cerr << get_fileline() << ": error: Could not find variable ``"
<< path_ << "'' in ``" << scope_path(scope) <<
@@ -208,18 +208,101 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
return 0;
}
long msb, lsb;
NetExpr*mux;
if (use_sel == index_component_t::SEL_BIT) {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_bit_(des, scope, lv);
return lv;
const index_component_t&index_tail = name_tail.index.back();
ivl_assert(*this, index_tail.msb != 0);
ivl_assert(*this, index_tail.lsb == 0);
/* If there is only a single select expression, it is a
bit select. Evaluate the constant value and treat it
as a part select with a bit width of 1. If the
expression it not constant, then return the
expression as a mux. */
NetExpr*index_expr = elab_and_eval(des, scope, index_tail.msb, -1);
if (NetEConst*index_con = dynamic_cast<NetEConst*> (index_expr)) {
msb = index_con->value().as_long();
lsb = index_con->value().as_long();
mux = 0;
} else {
msb = 0;
lsb = 0;
mux = index_expr;
}
} else {
/* No select expressions, so presume a part select the
width of the register. */
msb = reg->msb();
lsb = reg->lsb();
mux = 0;
}
ivl_assert(*this, use_sel == index_component_t::SEL_NONE);
/* No select expressions. */
NetAssign_*lv;
if (mux) {
/* If there is a non-constant bit select, make a
NetAssign_ to the target reg and attach a
bmux to select the target bit. */
lv = new NetAssign_(reg);
/* Correct the mux for the range of the vector. */
if (reg->msb() < reg->lsb())
mux = make_sub_expr(reg->lsb(), mux);
else if (reg->lsb() != 0)
mux = make_add_expr(mux, - reg->lsb());
lv->set_part(mux, 1);
} else if (msb == reg->msb() && lsb == reg->lsb()) {
/* No bit select, and part select covers the entire
vector. Simplest case. */
lv = new NetAssign_(reg);
} else {
/* If the bit/part select is constant, then make the
NetAssign_ only as wide as it needs to be and connect
only to the selected bits of the reg. */
unsigned loff = reg->sb_to_idx(lsb);
unsigned moff = reg->sb_to_idx(msb);
unsigned wid = moff - loff + 1;
if (moff < loff) {
cerr << get_fileline() << ": error: part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is reversed." << endl;
des->errors += 1;
return 0;
}
/* If the part select extends beyond the extreme of the
variable, then report an error. Note that loff is
converted to normalized form so is relative the
variable pins. */
if ((wid + loff) > reg->vector_width()) {
cerr << get_fileline() << ": error: bit/part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is out of range." << endl;
des->errors += 1;
return 0;
}
lv = new NetAssign_(reg);
lv->set_part(new NetEConst(verinum(loff)), wid);
}
NetAssign_*lv = new NetAssign_(reg);
return lv;
}
@@ -291,67 +374,10 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
return lv;
}
bool PEIdent::elaborate_lval_net_bit_(Design*des,
NetScope*scope,
NetAssign_*lv) const
{
const name_component_t&name_tail = path_.back();
const index_component_t&index_tail = name_tail.index.back();
ivl_assert(*this, index_tail.msb != 0);
ivl_assert(*this, index_tail.lsb == 0);
NetNet*reg = lv->sig();
// Bit selects have a single select expression. Evaluate the
// constant value and treat it as a part select with a bit
// width of 1.
NetExpr*mux = elab_and_eval(des, scope, index_tail.msb, -1);
long lsb = 0;
if (NetEConst*index_con = dynamic_cast<NetEConst*> (mux)) {
lsb = index_con->value().as_long();
mux = 0;
}
if (mux) {
// Non-constant bit mux. Correct the mux for the range
// of the vector, then set the l-value part select expression.
if (reg->msb() < reg->lsb())
mux = make_sub_expr(reg->lsb(), mux);
else if (reg->lsb() != 0)
mux = make_add_expr(mux, - reg->lsb());
lv->set_part(mux, 1);
} else if (lsb == reg->msb() && lsb == reg->lsb()) {
// Constant bit mux that happens to select the only bit
// of the l-value. Don't bother with any select at all.
} else {
// Constant bit select that does something useful.
long loff = reg->sb_to_idx(lsb);
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;
}
lv->set_part(new NetEConst(verinum(loff)), 1);
}
return true;
}
bool PEIdent::elaborate_lval_net_part_(Design*des,
NetScope*scope,
NetAssign_*lv) const
{
// The range expressions of a part select must be
// constant. The calculate_parts_ function calculates the
// values into msb and lsb.
long msb, lsb;
bool flag = calculate_parts_(des, scope, msb, lsb);
if (!flag)
@@ -362,14 +388,17 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
if (msb == reg->msb() && lsb == reg->lsb()) {
/* Part select covers the entire vector. Simplest case. */
/* No bit select, and part select covers the entire
vector. Simplest case. */
} else {
/* Get the canonical offsets into the vector. */
long loff = reg->sb_to_idx(lsb);
long moff = reg->sb_to_idx(msb);
long wid = moff - loff + 1;
/* If the bit/part select is constant, then make the
NetAssign_ only as wide as it needs to be and connect
only to the selected bits of the reg. */
unsigned loff = reg->sb_to_idx(lsb);
unsigned moff = reg->sb_to_idx(msb);
unsigned wid = moff - loff + 1;
if (moff < loff) {
cerr << get_fileline() << ": error: part select "
@@ -379,15 +408,17 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
return false;
}
/* If the part select extends beyond the extremes of the
/* If the part select extends beyond the extreme of the
variable, then report an error. Note that loff is
converted to normalized form so is relative the
variable pins. */
if (loff < 0 || moff >= (signed)reg->vector_width()) {
cerr << get_fileline() << ": warning: Part select "
if ((wid + loff) > reg->vector_width()) {
cerr << get_fileline() << ": error: bit/part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is out of range." << endl;
des->errors += 1;
return false;
}
lv->set_part(new NetEConst(verinum(loff)), wid);
+3097 -52
View File
File diff suppressed because it is too large Load Diff
+3 -174
View File
@@ -57,52 +57,6 @@ NetExpr*PEBinary::elaborate_pexpr (Design*des, NetScope*scope) const
return tmp;
}
NetExpr*PEBComp::elaborate_pexpr(Design*des, NetScope*scope) const
{
NetExpr*lp = left_->elaborate_pexpr(des, scope);
NetExpr*rp = right_->elaborate_pexpr(des, scope);
if ((lp == 0) || (rp == 0)) {
delete lp;
delete rp;
return 0;
}
suppress_binary_operand_sign_if_needed_(lp, rp);
NetEBComp*tmp = new NetEBComp(op_, lp, rp);
tmp->set_line(*this);
bool flag = tmp->set_width(1);
if (flag == false) {
cerr << get_fileline() << ": internal error: "
"expression bit width of comparison != 1." << endl;
des->errors += 1;
}
return tmp;
}
NetExpr*PEBLogic::elaborate_pexpr(Design*des, NetScope*scope) const
{
NetExpr*lp = left_->elaborate_pexpr(des, scope);
NetExpr*rp = right_->elaborate_pexpr(des, scope);
if ((lp == 0) || (rp == 0)) {
delete lp;
delete rp;
return 0;
}
NetEBLogic*tmp = new NetEBLogic(op_, lp, rp);
tmp->set_line(*this);
bool flag = tmp->set_width(1);
if (flag == false) {
cerr << get_fileline() << ": internal error: "
"expression bit width of comparison != 1." << endl;
des->errors += 1;
}
return tmp;
}
/*
* Event though parameters are not generally sized, parameter
* expressions can include concatenation expressions. This requires
@@ -178,13 +132,13 @@ NetExpr*PEFNumber::elaborate_pexpr(Design*des, NetScope*scope) const
*/
NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
{
pform_name_t oldpath = path_;
pform_name_t path = path_;
name_component_t name_tail = path_.back();
oldpath.pop_back();
path.pop_back();
NetScope*pscope = scope;
if (path_.size() > 0) {
list<hname_t> tmp = eval_scope_path(des, scope, oldpath);
list<hname_t> tmp = eval_scope_path(des, scope, path);
pscope = des->find_scope(scope, tmp);
}
@@ -313,128 +267,3 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
return tmp;
}
NetExpr* PECallFunction::elaborate_pexpr(Design*des, NetScope*scope) const
{
/* Only $clog2 and the builtin mathematical functions can
* be a constant system function. */
perm_string nm = peek_tail_name(path_);
if (nm[0] == '$' && (generation_flag >= GN_VER2005 ||
gn_icarus_misc_flag || gn_verilog_ams_flag)) {
if (nm == "$clog2" ||
nm == "$ln" ||
nm == "$log10" ||
nm == "$exp" ||
nm == "$sqrt" ||
nm == "$floor" ||
nm == "$ceil" ||
nm == "$sin" ||
nm == "$cos" ||
nm == "$tan" ||
nm == "$asin" ||
nm == "$acos" ||
nm == "$atan" ||
nm == "$sinh" ||
nm == "$cosh" ||
nm == "$tanh" ||
nm == "$asinh" ||
nm == "$acosh" ||
nm == "$atanh") {
if (parms_.size() != 1 || parms_[0] == 0) {
cerr << get_fileline() << ": error: " << nm
<< " takes a single argument." << endl;
des->errors += 1;
return 0;
}
NetExpr*arg = parms_[0]->elaborate_pexpr(des, scope);
if (arg == 0) return 0;
NetESFunc*rtn;
if (nm == "$clog2") {
rtn = new NetESFunc(nm, IVL_VT_BOOL, integer_width, 1);
} else {
rtn = new NetESFunc(nm, IVL_VT_REAL, 1, 1);
}
rtn->set_line(*this);
rtn->cast_signed(true);
rtn->parm(0, arg);
return rtn;
}
if (nm == "$pow" ||
nm == "$atan2" ||
nm == "$hypot") {
if (parms_.size() != 2 || parms_[0] == 0 || parms_[1] == 0) {
cerr << get_fileline() << ": error: " << nm
<< " takes two arguments." << endl;
des->errors += 1;
return 0;
}
NetExpr*arg0 = parms_[0]->elaborate_pexpr(des, scope);
NetExpr*arg1 = parms_[1]->elaborate_pexpr(des, scope);
if (arg0 == 0 || arg1 == 0) return 0;
NetESFunc*rtn = new NetESFunc(nm, IVL_VT_REAL, 1, 2);
rtn->set_line(*this);
rtn->cast_signed(true);
rtn->parm(0, arg0);
rtn->parm(1, arg1);
return rtn;
}
/* These are only available with verilog-ams or icarus-misc. */
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
(nm == "$log" || nm == "$abs")) {
if (parms_.size() != 1 || parms_[0] == 0) {
cerr << get_fileline() << ": error: " << nm
<< " takes a single argument." << endl;
des->errors += 1;
return 0;
}
NetExpr*arg = parms_[0]->elaborate_pexpr(des, scope);
if (arg == 0) return 0;
NetESFunc*rtn;
if (nm == "$log") {
rtn = new NetESFunc(nm, IVL_VT_REAL, 1, 1);
} else {
/* This can return either a real or an arbitrary
* width vector, so set things to fail if this
* does not get replaced with a constant during
* elaboration. */
rtn = new NetESFunc(nm, IVL_VT_NO_TYPE, 0, 1);
}
rtn->set_line(*this);
rtn->cast_signed(true);
rtn->parm(0, arg);
return rtn;
}
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
(nm == "$min" || nm == "$max")) {
if (parms_.size() != 2 || parms_[0] == 0 || parms_[1] == 0) {
cerr << get_fileline() << ": error: " << nm
<< " takes two arguments." << endl;
des->errors += 1;
return 0;
}
NetExpr*arg0 = parms_[0]->elaborate_pexpr(des, scope);
NetExpr*arg1 = parms_[1]->elaborate_pexpr(des, scope);
if (arg0 == 0 || arg1 == 0) return 0;
/* See $log above for why this has no type or width. */
NetESFunc*rtn = new NetESFunc(nm, IVL_VT_NO_TYPE, 0, 2);
rtn->set_line(*this);
rtn->cast_signed(true);
rtn->parm(0, arg0);
rtn->parm(1, arg1);
return rtn;
}
cerr << get_fileline() << ": error: this is not a constant "
"system function (" << *this << ")." << endl;
des->errors += 1;
return 0;
}
/* Constant user function code goes here. */
cerr << get_fileline() << ": sorry: constant user functions are not "
"currently supported." << endl;
des->errors += 1;
return 0;
}
+159 -448
View File
@@ -40,55 +40,20 @@
# include "PTask.h"
# include "PWire.h"
# include "Statement.h"
# include "AStatement.h"
# include "netlist.h"
# include "util.h"
# include <typeinfo>
# include <assert.h>
# include "ivl_assert.h"
typedef map<perm_string,LexicalScope::param_expr_t>::const_iterator mparm_it_t;
static void collect_scope_parameters_(NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t>&parameters)
{
for (mparm_it_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) {
NetEParam*tmp = new NetEParam;
tmp->set_line(*((*cur).second.expr));
tmp->cast_signed( (*cur).second.signed_flag );
scope->set_parameter((*cur).first, tmp, (*cur).second.type,
0, 0, false, 0, (*cur).second);
}
}
static void collect_scope_localparams_(NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t>&localparams)
{
for (mparm_it_t cur = localparams.begin()
; cur != localparams.end() ; cur ++) {
NetEParam*tmp = new NetEParam;
tmp->set_line(*((*cur).second.expr));
if ((*cur).second.msb)
tmp->cast_signed( (*cur).second.signed_flag );
scope->set_parameter((*cur).first, tmp, (*cur).second.type,
0, 0, false, 0, (*cur).second);
}
}
static void elaborate_parm_item_(perm_string name,
const LexicalScope::param_expr_t&cur,
Design*des, NetScope*scope)
void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur,
Design*des, NetScope*scope)
{
PExpr*ex = cur.expr;
assert(ex);
NetExpr*val = ex->elaborate_pexpr(des, scope);
if (val == 0) return;
NetExpr*msb = 0;
NetExpr*lsb = 0;
bool signed_flag = cur.signed_flag;
@@ -106,8 +71,21 @@ static void elaborate_parm_item_(perm_string name,
assert(lsb);
}
if (signed_flag) {
/* If explicitly signed, then say so. */
val->cast_signed(true);
} else if (cur.msb) {
/* If there is a range, then the signedness comes
from the type and not the expression. */
val->cast_signed(signed_flag);
} else {
/* otherwise, let the expression describe
itself. */
signed_flag = val->has_sign();
}
NetScope::range_t*range_list = 0;
for (LexicalScope::range_t*range = cur.range ; range ; range = range->next) {
for (Module::range_t*range = cur.range ; range ; range = range->next) {
NetScope::range_t*tmp = new NetScope::range_t;
tmp->exclude_flag = range->exclude_flag;
tmp->low_open_flag = range->low_open_flag;
@@ -140,186 +118,13 @@ static void elaborate_parm_item_(perm_string name,
range_list = tmp;
}
/* Set the parameter expression to 0 if the evaluation failed. */
if (val == 0) {
val = scope->set_parameter(name, val, cur.type, msb, lsb,
signed_flag, range_list, cur);
delete val;
return;
}
if (signed_flag) {
/* If explicitly signed, then say so. */
val->cast_signed(true);
} else if (cur.msb) {
/* If there is a range, then the signedness comes
from the type and not the expression. */
val->cast_signed(signed_flag);
} else {
/* otherwise, let the expression describe
itself. */
signed_flag = val->has_sign();
}
val = scope->set_parameter(name, val, cur.type, msb, lsb, signed_flag,
range_list, cur);
val = scope->set_parameter(name, val, cur.type, msb, lsb, signed_flag, range_list, cur);
assert(val);
delete val;
}
static void elaborate_scope_parameters_(Design*des, NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t>&parameters)
{
for (mparm_it_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) {
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
}
}
static void elaborate_scope_localparams_(Design*des, NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t>&localparams)
{
for (mparm_it_t cur = localparams.begin()
; cur != localparams.end() ; cur ++) {
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
}
}
static void replace_scope_parameters_(NetScope*scope, const LineInfo&loc,
const Module::replace_t&replacements)
{
for (Module::replace_t::const_iterator cur = replacements.begin()
; cur != replacements.end() ; cur ++) {
NetExpr*val = (*cur).second;
if (val == 0) {
cerr << loc.get_fileline() << ": internal error: "
<< "Missing expression in parameter replacement for "
<< (*cur).first;
}
assert(val);
if (debug_scopes) {
cerr << loc.get_fileline() << ": debug: "
<< "Replace " << (*cur).first
<< " with expression " << *val
<< " from " << val->get_fileline() << "." << endl;
cerr << loc.get_fileline() << ": : "
<< "Type=" << val->expr_type() << endl;
}
bool flag = scope->replace_parameter((*cur).first, val);
if (! flag) {
cerr << val->get_fileline() << ": warning: parameter "
<< (*cur).first << " not found in "
<< scope_path(scope) << "." << endl;
}
}
}
static void elaborate_scope_events_(Design*des, NetScope*scope,
const map<perm_string,PEvent*>&events)
{
for (map<perm_string,PEvent*>::const_iterator et = events.begin()
; et != events.end() ; et ++ ) {
(*et).second->elaborate_scope(des, scope);
}
}
static void elaborate_scope_tasks(Design*des, NetScope*scope,
const LineInfo&loc,
const map<perm_string,PTask*>&tasks)
{
typedef map<perm_string,PTask*>::const_iterator tasks_it_t;
for (tasks_it_t cur = tasks.begin()
; cur != tasks.end() ; cur ++ ) {
hname_t use_name( (*cur).first );
if (scope->child(use_name)) {
cerr << loc.get_fileline() << ": error: task/scope name "
<< use_name << " already used in this context."
<< endl;
des->errors += 1;
continue;
}
NetScope*task_scope = new NetScope(scope, use_name,
NetScope::TASK);
task_scope->is_auto((*cur).second->is_auto());
task_scope->set_line((*cur).second);
if (debug_scopes)
cerr << cur->second->get_fileline() << ": debug: "
<< "Elaborate task scope " << scope_path(task_scope) << endl;
(*cur).second->elaborate_scope(des, task_scope);
}
}
static void elaborate_scope_funcs(Design*des, NetScope*scope,
const LineInfo&loc,
const map<perm_string,PFunction*>&funcs)
{
typedef map<perm_string,PFunction*>::const_iterator funcs_it_t;
for (funcs_it_t cur = funcs.begin()
; cur != funcs.end() ; cur ++ ) {
hname_t use_name( (*cur).first );
if (scope->child(use_name)) {
cerr << loc.get_fileline() << ": error: function/scope name "
<< use_name << " already used in this context."
<< endl;
des->errors += 1;
continue;
}
NetScope*func_scope = new NetScope(scope, use_name,
NetScope::FUNC);
func_scope->is_auto((*cur).second->is_auto());
func_scope->set_line((*cur).second);
if (debug_scopes)
cerr << cur->second->get_fileline() << ": debug: "
<< "Elaborate function scope " << scope_path(func_scope) << endl;
(*cur).second->elaborate_scope(des, func_scope);
}
}
class generate_schemes_work_item_t : public elaborator_work_item_t {
public:
generate_schemes_work_item_t(Design*des__, NetScope*scope, Module*mod)
: elaborator_work_item_t(des__), scope_(scope), mod_(mod)
{ }
void elaborate_runrun()
{
if (debug_scopes)
cerr << mod_->get_fileline() << ": debug: "
<< "Processing generate schemes for "
<< scope_path(scope_) << endl;
// Generate schemes can create new scopes in the form of
// generated code. Scan the generate schemes, and *generate*
// new scopes, which is slightly different from simple
// elaboration.
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = mod_->generate_schemes.begin()
; cur != mod_->generate_schemes.end() ; cur ++ ) {
(*cur) -> generate_scope(des, scope_);
}
}
private:
// The scope_ is the scope that contains the generate scheme
// we are to work on. the mod_ is the Module definition for
// that scope, and contains the parsed generate schemes.
NetScope*scope_;
Module*mod_;
};
bool Module::elaborate_scope(Design*des, NetScope*scope,
const replace_t&replacements)
const replace_t&replacements) const
{
if (debug_scopes) {
cerr << get_fileline() << ": debug: Elaborate scope "
@@ -337,25 +142,81 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
// the pform and just place a NetEParam placeholder in the
// place of the elaborated expression.
// Scan the parameters in the module, and create stub parameter
// entries in the scope for the parameter names.
typedef map<perm_string,param_expr_t>::const_iterator mparm_it_t;
typedef map<pform_name_t,PExpr*>::const_iterator pform_parm_it_t;
collect_scope_parameters_(scope, parameters);
collect_scope_localparams_(scope, localparams);
// This loop scans the parameters in the module, and creates
// stub parameter entries in the scope for the parameter name.
for (mparm_it_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) {
NetEParam*tmp = new NetEParam;
tmp->set_line(*((*cur).second.expr));
tmp->cast_signed( (*cur).second.signed_flag );
scope->set_parameter((*cur).first, tmp, (*cur).second.type,
0, 0, false, 0, (*cur).second);
}
for (mparm_it_t cur = localparams.begin()
; cur != localparams.end() ; cur ++) {
NetEParam*tmp = new NetEParam;
tmp->set_line(*((*cur).second.expr));
if ((*cur).second.msb)
tmp->cast_signed( (*cur).second.signed_flag );
scope->set_parameter((*cur).first, tmp, (*cur).second.type,
0, 0, false, 0, (*cur).second);
}
// Now scan the parameters again, this time elaborating them
// for use as parameter values. This is after the previous
// scan so that local parameter names can be used in the
// r-value expressions.
elaborate_scope_parameters_(des, scope, parameters);
for (mparm_it_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) {
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
}
/* run parameter replacements that were collected from the
containing scope and meant for me. */
replace_scope_parameters_(scope, *this, replacements);
for (replace_t::const_iterator cur = replacements.begin()
; cur != replacements.end() ; cur ++) {
elaborate_scope_localparams_(des, scope, localparams);
NetExpr*val = (*cur).second;
if (val == 0) {
cerr << get_fileline() << ": internal error: "
<< "Missing expression in parameter replacement for "
<< (*cur).first;
}
assert(val);
if (debug_scopes) {
cerr << get_fileline() << ": debug: "
<< "Replace " << (*cur).first
<< " with expression " << *val
<< " from " << val->get_fileline() << "." << endl;
cerr << get_fileline() << ": : "
<< "Type=" << val->expr_type() << endl;
}
bool flag = scope->replace_parameter((*cur).first, val);
if (! flag) {
cerr << val->get_fileline() << ": warning: parameter "
<< (*cur).first << " not found in "
<< scope_path(scope) << "." << endl;
}
}
for (mparm_it_t cur = localparams.begin()
; cur != localparams.end() ; cur ++) {
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
}
// Run through the defparams for this module, elaborate the
// expressions in this context and save the result is a table
@@ -367,17 +228,15 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
// here because the parameter receiving the assignment may be
// in a scope not discovered by this pass.
typedef list<Module::named_expr_t>::const_iterator defparms_iter_t;
for (defparms_iter_t cur = defparms.begin()
; cur != defparms.end() ; cur ++) {
for (pform_parm_it_t cur = defparms.begin()
; cur != defparms.end() ; cur ++ ) {
PExpr*ex = cur->second;
PExpr*ex = (*cur).second;
assert(ex);
NetExpr*val = ex->elaborate_pexpr(des, scope);
if (val == 0) continue;
scope->defparams.push_back(make_pair(cur->first, val));
scope->defparams[(*cur).first] = val;
}
// Evaluate the attributes. Evaluate them in the scope of the
@@ -390,29 +249,66 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
delete[]attr;
// Generate schemes need to have their scopes elaborated, but
// we cannot do that until defparams are run, so push it off
// into an elaborate work item.
if (debug_scopes)
cerr << get_fileline() << ": debug: "
<< "Schedule generates within " << scope_path(scope)
<< " for elaboration after defparams." << endl;
// Generate schemes can create new scopes in the form of
// generated code. Scan the generate schemes, and *generate*
// new scopes, which is slightly different from simple
// elaboration.
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++ ) {
(*cur) -> generate_scope(des, scope);
}
des->elaboration_work_list.push_back(new generate_schemes_work_item_t(des, scope, this));
// Tasks introduce new scopes, so scan the tasks in this
// module. Create a scope for the task and pass that to the
// elaborate_scope method of the PTask for detailed
// processing.
elaborate_scope_tasks(des, scope, *this, tasks);
typedef map<perm_string,PTask*>::const_iterator tasks_it_t;
for (tasks_it_t cur = tasks_.begin()
; cur != tasks_.end() ; cur ++ ) {
hname_t use_name( (*cur).first );
if (scope->child(use_name)) {
cerr << get_fileline() << ": error: task/scope name "
<< use_name << " already used in this context."
<< endl;
des->errors += 1;
continue;
}
NetScope*task_scope = new NetScope(scope, use_name,
NetScope::TASK);
task_scope->set_line((*cur).second);
(*cur).second->elaborate_scope(des, task_scope);
}
// Functions are very similar to tasks, at least from the
// perspective of scopes. So handle them exactly the same
// way.
elaborate_scope_funcs(des, scope, *this, funcs);
typedef map<perm_string,PFunction*>::const_iterator funcs_it_t;
for (funcs_it_t cur = funcs_.begin()
; cur != funcs_.end() ; cur ++ ) {
hname_t use_name( (*cur).first );
if (scope->child(use_name)) {
cerr << get_fileline() << ": error: function/scope name "
<< use_name << " already used in this context."
<< endl;
des->errors += 1;
continue;
}
NetScope*func_scope = new NetScope(scope, use_name,
NetScope::FUNC);
func_scope->set_line((*cur).second);
(*cur).second->elaborate_scope(des, func_scope);
}
// Gates include modules, which might introduce new scopes, so
// scan all of them to create those scopes.
@@ -442,7 +338,11 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
// elaboration, so do it now. This allows for normal
// elaboration to reference these events.
elaborate_scope_events_(des, scope, events);
for (map<perm_string,PEvent*>::const_iterator et = events.begin()
; et != events.end() ; et ++ ) {
(*et).second->elaborate_scope(des, scope);
}
return des->errors == 0;
}
@@ -461,9 +361,7 @@ bool PGenerate::generate_scope(Design*des, NetScope*container)
case GS_CASE:
return generate_scope_case_(des, container);
case GS_NBLOCK:
return generate_scope_nblock_(des, container);
return true;
case GS_CASE_ITEM:
cerr << get_fileline() << ": internal error: "
@@ -524,12 +422,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
container->genvar_tmp_val = genvar;
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
NetEConst*test = dynamic_cast<NetEConst*>(test_ex);
if (test == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar"
<< " conditional expression: " << *loop_test << endl;
des->errors += 1;
return false;
}
assert(test);
while (test->value().as_long()) {
// The actual name of the scope includes the genvar so
@@ -576,12 +469,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
// Calculate the step for the loop variable.
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1);
NetEConst*step = dynamic_cast<NetEConst*>(step_ex);
if (step == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar"
<< " step expression: " << *loop_step << endl;
des->errors += 1;
return false;
}
assert(step);
if (debug_scopes)
cerr << get_fileline() << ": debug: genvar step from "
<< genvar << " to " << step->value().as_long() << endl;
@@ -606,12 +494,7 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
{
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
NetEConst*test = dynamic_cast<NetEConst*> (test_ex);
if (test == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar"
<< " conditional expression: " << *loop_test << endl;
des->errors += 1;
return false;
}
assert(test);
// If the condition evaluates as false, then do not create the
// scope.
@@ -653,12 +536,10 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
{
NetExpr*case_value_ex = elab_and_eval(des, container, loop_test, -1);
NetEConst*case_value_co = dynamic_cast<NetEConst*>(case_value_ex);
if (case_value_co == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar case"
<< " expression: " << *loop_test << endl;
des->errors += 1;
return false;
}
assert(case_value_co);
// The name of the scope to generate, whatever that item is.
hname_t use_name (scope_name);
if (debug_scopes)
cerr << get_fileline() << ": debug: Generate case "
@@ -667,8 +548,8 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
PGenerate*default_item = 0;
typedef list<PGenerate*>::const_iterator generator_it_t;
generator_it_t cur = generate_schemes.begin();
while (cur != generate_schemes.end()) {
generator_it_t cur = generates.begin();
while (cur != generates.end()) {
PGenerate*item = *cur;
assert( item->scheme_type == PGenerate::GS_CASE_ITEM );
@@ -697,7 +578,7 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
delete case_value_co;
case_value_co = 0;
PGenerate*item = (cur == generate_schemes.end())? default_item : *cur;
PGenerate*item = (cur == generates.end())? default_item : *cur;
if (item == 0) {
cerr << get_fileline() << ": debug: "
<< "No generate items found" << endl;
@@ -709,9 +590,6 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
<< "Generate case matches item at "
<< item->get_fileline() << endl;
// The name of the scope to generate, whatever that item is.
hname_t use_name (item->scope_name);
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
@@ -720,29 +598,6 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
return true;
}
bool PGenerate::generate_scope_nblock_(Design*des, NetScope*container)
{
hname_t use_name (scope_name);
if (container->child(use_name)) {
cerr << get_fileline() << ": error: block/scope name "
<< scope_name << " already used in this context."
<< endl;
des->errors += 1;
return false;
}
if (debug_scopes)
cerr << get_fileline() << ": debug: Generate named block "
<< ": Generate scope=" << use_name << endl;
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
elaborate_subscope_(des, scope);
return true;
}
void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
{
// Scan the generated scope for nested generate schemes,
@@ -750,24 +605,11 @@ void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
// from simple elaboration.
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++ ) {
for (generate_it_t cur = generates.begin()
; cur != generates.end() ; cur ++ ) {
(*cur) -> generate_scope(des, scope);
}
// Scan the localparams in this scope, and create stub parameter
// entries in the scope for the parameter names.
collect_scope_localparams_(scope, localparams);
// Now scan the localparams again, this time elaborating them
// for use as parameter values.
elaborate_scope_localparams_(des, scope, localparams);
// Scan through all the task and function declarations in this
// scope.
elaborate_scope_tasks(des, scope, *this, tasks);
elaborate_scope_funcs(des, scope, *this, funcs);
// Scan the generated scope for gates that may create
// their own scopes.
typedef list<PGate*>::const_iterator pgate_list_it_t;
@@ -776,54 +618,10 @@ void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
(*cur) ->elaborate_scope(des, scope);
}
typedef list<PProcess*>::const_iterator proc_it_t;
for (proc_it_t cur = behaviors.begin()
; cur != behaviors.end() ; cur ++ ) {
(*cur) -> statement() -> elaborate_scope(des, scope);
}
// Scan through all the named events in this scope.
elaborate_scope_events_(des, scope, events);
// Save the scope that we created, for future use.
scope_list_.push_back(scope);
}
class delayed_elaborate_scope_mod_instances : public elaborator_work_item_t {
public:
delayed_elaborate_scope_mod_instances(Design*des__,
const PGModule*obj,
Module*mod,
NetScope*sc)
: elaborator_work_item_t(des__), obj_(obj), mod_(mod), sc_(sc)
{ }
~delayed_elaborate_scope_mod_instances() { }
virtual void elaborate_runrun();
private:
const PGModule*obj_;
Module*mod_;
NetScope*sc_;
};
void delayed_elaborate_scope_mod_instances::elaborate_runrun()
{
if (debug_scopes)
cerr << obj_->get_fileline() << ": debug: "
<< "Resume scope elaboration of instances of "
<< mod_->mod_name() << "." << endl;
obj_->elaborate_scope_mod_instances_(des, mod_, sc_);
}
/*
* Here we handle the elaborate scope of a module instance. The caller
* has already figured out that this "gate" is a module, and has found
* the module definition. The "sc" argument is the scope that will
* contain this instance.
*/
void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
{
if (get_name() == "") {
@@ -870,36 +668,6 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
return;
}
if (msb_ || lsb_) {
// If there are expressions to evaluate in order to know
// the actual number of instances that will be
// instantiated, then we have to delay further scope
// elaboration until after defparams (above me) are
// run. Do that by appending a work item to the
// elaboration work list.
if (debug_scopes)
cerr << get_fileline() << ": debug: delay elaborate_scope"
<< " of array of " << get_name()
<< " in scope " << scope_path(sc) << "." << endl;
elaborator_work_item_t*tmp
= new delayed_elaborate_scope_mod_instances(des, this, mod, sc);
des->elaboration_work_list.push_back(tmp);
} else {
// If there are no expressions that need to be evaluated
// to elaborate the scope of this next instances, then
// get right to it.
elaborate_scope_mod_instances_(des, mod, sc);
}
}
/*
* This method is called to process a module instantiation after basic
* sanity testing is already complete.
*/
void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*sc) const
{
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_, -1) : 0;
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1) : 0;
NetEConst*msb = dynamic_cast<NetEConst*> (mse);
@@ -987,16 +755,16 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
assert(parms_ == 0);
list<perm_string>::const_iterator cur
= mod->param_names.begin();
unsigned jdx = 0;
unsigned idx = 0;
for (;;) {
if (jdx >= overrides_->count())
if (idx >= overrides_->count())
break;
if (cur == mod->param_names.end())
break;
replace[*cur] = (*overrides_)[jdx];
replace[*cur] = (*overrides_)[idx];
jdx += 1;
idx += 1;
cur ++;
}
}
@@ -1005,8 +773,8 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
// so the mapping into the replace list is much easier.
if (parms_) {
assert(overrides_ == 0);
for (unsigned jdx = 0 ; jdx < nparms_ ; jdx += 1)
replace[parms_[jdx].name] = parms_[jdx].parm;
for (unsigned idx = 0 ; idx < nparms_ ; idx += 1)
replace[parms_[idx].name] = parms_[idx].parm;
}
@@ -1066,25 +834,6 @@ void PFunction::elaborate_scope(Design*des, NetScope*scope) const
{
assert(scope->type() == NetScope::FUNC);
// Scan the parameters in the function, and create stub parameter
// entries in the scope for the parameter names.
collect_scope_parameters_(scope, parameters);
collect_scope_localparams_(scope, localparams);
// Now scan the parameters again, this time elaborating them
// for use as parameter values. This is after the previous
// scan so that local parameter names can be used in the
// r-value expressions.
elaborate_scope_parameters_(des, scope, parameters);
elaborate_scope_localparams_(des, scope, localparams);
// Scan through all the named events in this scope.
elaborate_scope_events_(des, scope, events);
if (statement_)
statement_->elaborate_scope(des, scope);
}
@@ -1093,25 +842,6 @@ void PTask::elaborate_scope(Design*des, NetScope*scope) const
{
assert(scope->type() == NetScope::TASK);
// Scan the parameters in the task, and create stub parameter
// entries in the scope for the parameter names.
collect_scope_parameters_(scope, parameters);
collect_scope_localparams_(scope, localparams);
// Now scan the parameters again, this time elaborating them
// for use as parameter values. This is after the previous
// scan so that local parameter names can be used in the
// r-value expressions.
elaborate_scope_parameters_(des, scope, parameters);
elaborate_scope_localparams_(des, scope, localparams);
// Scan through all the named events in this scope.
elaborate_scope_events_(des, scope, events);
if (statement_)
statement_->elaborate_scope(des, scope);
}
@@ -1148,30 +878,11 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
? NetScope::FORK_JOIN
: NetScope::BEGIN_END);
my_scope->set_line(get_file(), get_lineno());
my_scope->is_auto(scope->is_auto());
// Scan the parameters in the scope, and create stub parameter
// entries in the scope for the parameter names.
collect_scope_parameters_(my_scope, parameters);
collect_scope_localparams_(my_scope, localparams);
// Now scan the parameters again, this time elaborating them
// for use as parameter values. This is after the previous
// scan so that local parameter names can be used in the
// r-value expressions.
elaborate_scope_parameters_(des, my_scope, parameters);
elaborate_scope_localparams_(des, my_scope, localparams);
// Scan through all the named events in this scope.
elaborate_scope_events_(des, my_scope, events);
}
for (unsigned idx = 0 ; idx < list_.count() ; idx += 1)
list_[idx] -> elaborate_scope(des, my_scope);
}
/*
+61 -104
View File
@@ -108,49 +108,13 @@ bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const
return flag;
}
static void elaborate_sig_funcs(Design*des, NetScope*scope,
const map<perm_string,PFunction*>&funcs)
{
typedef map<perm_string,PFunction*>::const_iterator mfunc_it_t;
for (mfunc_it_t cur = funcs.begin()
; cur != funcs.end() ; cur ++) {
hname_t use_name ( (*cur).first );
NetScope*fscope = scope->child(use_name);
if (scope == 0) {
cerr << (*cur).second->get_fileline() << ": internal error: "
<< "Child scope for function " << (*cur).first
<< " missing in " << scope_path(scope) << "." << endl;
des->errors += 1;
continue;
}
(*cur).second->elaborate_sig(des, fscope);
}
}
static void elaborate_sig_tasks(Design*des, NetScope*scope,
const map<perm_string,PTask*>&tasks)
{
typedef map<perm_string,PTask*>::const_iterator mtask_it_t;
for (mtask_it_t cur = tasks.begin()
; cur != tasks.end() ; cur ++) {
NetScope*tscope = scope->child( hname_t((*cur).first) );
assert(tscope);
(*cur).second->elaborate_sig(des, tscope);
}
}
bool Module::elaborate_sig(Design*des, NetScope*scope) const
{
bool flag = true;
// Scan all the ports of the module, and make sure that each
// is connected to wires that have port declarations.
for (unsigned idx = 0 ; idx < ports.size() ; idx += 1) {
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
Module::port_t*pp = ports[idx];
if (pp == 0)
continue;
@@ -159,7 +123,7 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
// expression are all identifiers that should reference
// wires within the scope.
map<perm_string,PWire*>::const_iterator wt;
for (unsigned cc = 0 ; cc < pp->expr.size() ; cc += 1) {
for (unsigned cc = 0 ; cc < pp->expr.count() ; cc += 1) {
pform_name_t port_path (pp->expr[cc]->path());
// A concatenated wire of a port really should not
// have any hierarchy.
@@ -218,12 +182,38 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
flag &= (*gt)->elaborate_sig(des, scope);
}
typedef map<perm_string,PFunction*>::const_iterator mfunc_it_t;
for (mfunc_it_t cur = funcs_.begin()
; cur != funcs_.end() ; cur ++) {
hname_t use_name ( (*cur).first );
NetScope*fscope = scope->child(use_name);
if (scope == 0) {
cerr << (*cur).second->get_fileline() << ": internal error: "
<< "Child scope for function " << (*cur).first
<< " missing in " << scope_path(scope) << "." << endl;
des->errors += 1;
continue;
}
(*cur).second->elaborate_sig(des, fscope);
}
// After all the wires are elaborated, we are free to
// elaborate the ports of the tasks defined within this
// module. Run through them now.
elaborate_sig_funcs(des, scope, funcs);
elaborate_sig_tasks(des, scope, tasks);
typedef map<perm_string,PTask*>::const_iterator mtask_it_t;
for (mtask_it_t cur = tasks_.begin()
; cur != tasks_.end() ; cur ++) {
NetScope*tscope = scope->child( hname_t((*cur).first) );
assert(tscope);
(*cur).second->elaborate_sig(des, tscope);
}
// initial and always blocks may contain begin-end and
// fork-join blocks that can introduce scopes. Therefore, I
@@ -266,7 +256,7 @@ bool PEIdent::elaborate_sig(Design*des, NetScope*scope) const
if (error_implicit)
return true;
symbol_search(this, des, scope, path_, sig, par, eve);
symbol_search(des, scope, path_, sig, par, eve);
if (eve != 0)
return false;
@@ -361,11 +351,11 @@ bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
continue;
flag = tmp->elaborate_sig(des, scope) && flag;
}
NetScope::scope_vec_t instance = scope->instance_arrays[get_name()];
for (unsigned idx = 0 ; idx < instance.size() ; idx += 1) {
for (unsigned idx = 0 ; idx < instance.count() ; idx += 1) {
// I know a priori that the elaborate_scope created the scope
// already, so just look it up as a child of the current scope.
NetScope*my_scope = instance[idx];
@@ -425,8 +415,8 @@ bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
<< scope_path(container) << "." << endl;
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++) {
for (generate_it_t cur = generates.begin()
; cur != generates.end() ; cur ++) {
PGenerate*item = *cur;
if (! item->scope_list_.empty()) {
flag &= item->elaborate_sig(des, container);
@@ -471,12 +461,9 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
cur->elaborate_sig(des, scope);
}
elaborate_sig_funcs(des, scope, funcs);
elaborate_sig_tasks(des, scope, tasks);
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++ ) {
for (generate_it_t cur = generates.begin()
; cur != generates.end() ; cur ++ ) {
(*cur) -> elaborate_sig(des, scope);
}
@@ -589,17 +576,9 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
break;
default:
if (ports_) {
cerr << get_fileline() << ": internal error: I don't know "
<< "how to deal with return type of function "
<< scope->basename() << "." << endl;
} else {
/* If we do not have any ports or a return type this
* is probably a bad function definition. */
cerr << get_fileline() << ": error: Bad definition for "
<< "function " << scope->basename() << "?" << endl;
return;
}
cerr << get_fileline() << ": internal error: I don't know how "
<< "to deal with return type of function "
<< scope->basename() << "." << endl;
}
svector<NetNet*>ports (ports_? ports_->count() : 0);
@@ -813,19 +792,16 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (port_set_ || net_set_) {
long pmsb = 0, plsb = 0, nmsb = 0, nlsb = 0;
bool bad_lsb = false, bad_msb = false;
/* If they exist get the port definition MSB and LSB */
if (port_set_ && port_msb_ != 0) {
NetExpr*texpr = elab_and_eval(des, scope, port_msb_, -1);
if (! eval_as_long(pmsb, texpr)) {
cerr << port_msb_->get_fileline() << ": error: "
"Range expressions must be constant." << endl;
cerr << port_msb_->get_fileline() << " : "
"This MSB expression violates the rule: "
<< *port_msb_ << endl;
"Unable to evaluate MSB constant expression ``"
<< *port_msb_ << "''." << endl;
des->errors += 1;
bad_msb = true;
return 0;
}
delete texpr;
@@ -834,12 +810,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (! eval_as_long(plsb, texpr)) {
cerr << port_lsb_->get_fileline() << ": error: "
"Range expressions must be constant." << endl;
cerr << port_lsb_->get_fileline() << " : "
"This LSB expression violates the rule: "
<< *port_lsb_ << endl;
"Unable to evaluate LSB constant expression ``"
<< *port_lsb_ << "''." << endl;
des->errors += 1;
bad_lsb = true;
return 0;
}
delete texpr;
@@ -851,17 +825,15 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (port_lsb_ == 0) assert(port_msb_ == 0);
/* If they exist get the net/etc. definition MSB and LSB */
if (net_set_ && net_msb_ != 0 && !bad_msb && !bad_lsb) {
if (net_set_ && net_msb_ != 0) {
NetExpr*texpr = elab_and_eval(des, scope, net_msb_, -1);
if (! eval_as_long(nmsb, texpr)) {
cerr << net_msb_->get_fileline() << ": error: "
"Range expressions must be constant." << endl;
cerr << net_msb_->get_fileline() << " : "
"This MSB expression violates the rule: "
<< *net_msb_ << endl;
"Unable to evaluate MSB constant expression ``"
<< *net_msb_ << "''." << endl;
des->errors += 1;
bad_msb = true;
return 0;
}
delete texpr;
@@ -870,12 +842,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (! eval_as_long(nlsb, texpr)) {
cerr << net_lsb_->get_fileline() << ": error: "
"Range expressions must be constant." << endl;
cerr << net_lsb_->get_fileline() << " : "
"This LSB expression violates the rule: "
<< *net_lsb_ << endl;
"Unable to evaluate LSB constant expression ``"
<< *net_lsb_ << "''." << endl;
des->errors += 1;
bad_lsb = true;
return 0;
}
delete texpr;
@@ -928,10 +898,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
}
}
/* Attempt to recover from errors. */
if (bad_lsb) nlsb = 0;
if (bad_msb) nmsb = nlsb;
lsb = nlsb;
msb = nmsb;
if (nmsb > nlsb)
@@ -976,18 +942,16 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
delete lexp;
if (!const_flag) {
cerr << get_fileline() << ": error: The indices "
cerr << get_fileline() << ": internal error: The indices "
<< "are not constant for array ``"
<< name_ << "''." << endl;
des->errors += 1;
/* Attempt to recover from error, */
array_s0 = 0;
array_e0 = 0;
} else {
array_s0 = lval.as_long();
array_e0 = rval.as_long();
}
return 0;
}
array_dimensions = 1;
array_s0 = lval.as_long();
array_e0 = rval.as_long();
}
/* If the net type is supply0 or supply1, replace it
@@ -1026,11 +990,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal "
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name_;
if (array_dimensions > 0) {
cerr << " [" << array_s0 << ":" << array_e0 << "]" << endl;
}
cerr << " in scope " << scope_path(scope) << endl;
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name_
<< " in scope " << scope_path(scope) << endl;
}
@@ -1055,10 +1016,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
sig->set_signed(get_signed());
sig->set_isint(get_isint());
if (ivl_discipline_t dis = get_discipline()) {
sig->set_discipline(dis);
}
if (pull)
connect(sig->pin(0), pull->pin(0));
-26
View File
@@ -1,26 +0,0 @@
/*
* Copyright (c) 2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "config.h"
# include "AStatement.h"
# include <cstdlib>
# include <iostream>
+727 -1169
View File
File diff suppressed because it is too large Load Diff
-64
View File
@@ -1,64 +0,0 @@
/*
* Copyright (c) 2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "config.h"
# include "AStatement.h"
# include "netlist.h"
# include "netmisc.h"
# include "util.h"
# include <typeinfo>
NetProc* AContrib::elaborate(Design*des, NetScope*scope) const
{
NetExpr*lval = elab_and_eval(des, scope, lval_, -1);
NetExpr*rval = elab_and_eval(des, scope, rval_, -1);
NetContribution*st = new NetContribution(lval, rval);
st->set_line(*this);
return st;
}
bool AProcess::elaborate(Design*des, NetScope*scope) const
{
NetProc*statement = statement_->elaborate(des, scope);
if (statement == 0)
return false;
NetAnalogTop*top = new NetAnalogTop(scope, type_, statement);
// Evaluate the attributes for this process, if there
// are any. These attributes are to be attached to the
// NetProcTop object.
struct attrib_list_t*attrib_list = 0;
unsigned attrib_list_n = 0;
attrib_list = evaluate_attributes(attributes, attrib_list_n, des, scope);
for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1)
top->attribute(attrib_list[adx].key,
attrib_list[adx].val);
delete[]attrib_list;
top->set_line(*this);
des->add_process(top);
return true;
}
+32 -50
View File
@@ -72,16 +72,6 @@ bool NetCaseCmp::emit_node(struct target_t*tgt) const
return true;
}
bool NetCastInt::emit_node(struct target_t*tgt) const
{
return tgt->lpm_cast_int(this);
}
bool NetCastReal::emit_node(struct target_t*tgt) const
{
return tgt->lpm_cast_real(this);
}
bool NetCLShift::emit_node(struct target_t*tgt) const
{
tgt->lpm_clshift(this);
@@ -190,28 +180,16 @@ bool NetProcTop::emit(struct target_t*tgt) const
return tgt->process(this);
}
bool NetAnalogTop::emit(struct target_t*tgt) const
{
cerr << get_fileline() << ": sorry: "
<< "I don't know how to emit for analog processes." << endl;
return false;
}
bool NetProc::emit_proc(struct target_t*tgt) const
{
cerr << "EMIT: Proc type? " << typeid(*this).name() << endl;
return false;
}
bool NetAlloc::emit_proc(struct target_t*tgt) const
{
tgt->proc_alloc(this);
return true;
}
bool NetAssign::emit_proc(struct target_t*tgt) const
{
return tgt->proc_assign(this);
tgt->proc_assign(this);
return true;
}
bool NetAssignNB::emit_proc(struct target_t*tgt) const
@@ -262,12 +240,6 @@ bool NetForever::emit_proc(struct target_t*tgt) const
return true;
}
bool NetFree::emit_proc(struct target_t*tgt) const
{
tgt->proc_free(this);
return true;
}
bool NetPDelay::emit_proc(struct target_t*tgt) const
{
return tgt->proc_delay(this);
@@ -380,20 +352,23 @@ void NetScope::emit_scope(struct target_t*tgt) const
for (NetScope*cur = sub_ ; cur ; cur = cur->sib_)
cur->emit_scope(tgt);
for (signals_map_iter_t cur = signals_map_.begin()
; cur != signals_map_.end() ; cur ++) {
tgt->signal(cur->second);
}
if (signals_) {
NetNet*cur = signals_->sig_next_;
do {
tgt->signal(cur);
cur = cur->sig_next_;
} while (cur != signals_->sig_next_);
// Run the signals again, but this time to connect the
// delay paths. This is done as a second pass because
// the paths reference other signals that may be later
// in the list. We can do it here because delay paths are
// always connected within the scope.
for (signals_map_iter_t cur = signals_map_.begin()
; cur != signals_map_.end() ; cur ++) {
tgt->signal_paths(cur->second);
/* Run the signals again, but this time to connect the
delay paths. This is done as a second pass because
the paths reference other signals that may be later
in the list. We can do it here becase delay paths are
always connected within the scope. */
cur = signals_->sig_next_;
do {
tgt->signal_paths(cur);
cur = cur->sig_next_;
} while (cur != signals_->sig_next_);
}
}
@@ -463,8 +438,6 @@ int Design::emit(struct target_t*tgt) const
bool proc_rc = true;
for (const NetProcTop*idx = procs_ ; idx ; idx = idx->next_)
proc_rc &= idx->emit(tgt);
for (const NetAnalogTop*idx = aprocs_ ; idx ; idx = idx->next_)
proc_rc &= idx->emit(tgt);
rc = tgt->end_design(this);
@@ -478,11 +451,6 @@ int Design::emit(struct target_t*tgt) const
return rc;
}
void NetEAccess::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_access_func(this);
}
void NetEBinary::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_binary(this);
@@ -558,3 +526,17 @@ void NetEUnary::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_unary(this);
}
int emit(const Design*des, const char*type)
{
for (unsigned idx = 0 ; target_table[idx] ; idx += 1) {
const struct target*tgt = target_table[idx];
if (strcmp(tgt->name, type) == 0)
return des->emit(tgt->meth);
}
cerr << "error: Code generator type " << type
<< " not found." << endl;
return -1;
}
+1 -1
View File
@@ -185,7 +185,7 @@ verinum* PEIdent::eval_const(Design*des, NetScope*scope) const
return new verinum(scope->genvar_tmp_val);
}
symbol_search(this, des, scope, path_, net, expr, eve);
symbol_search(des, scope, path_, net, expr, eve);
if (expr == 0)
return 0;
+6 -10
View File
@@ -53,19 +53,14 @@ attrib_list_t* evaluate_attributes(const map<perm_string,PExpr*>&att,
/* If the attribute value is given in the source, then
evaluate it as a constant. If the value is not
given, then assume the value is 1. */
verinum*tmp = 0;
if (exp) {
verinum*tmp;
if (exp)
tmp = exp->eval_const(des, scope);
if (tmp == 0) {
cerr << exp->get_fileline() << ": error: ``"
<< *exp << "'' is not a constant expression."
<< endl;
des->errors += 1;
}
}
if (tmp == 0)
else
tmp = new verinum(1);
if (tmp == 0)
cerr << "internal error: no result for " << *exp << endl;
assert(tmp);
table[idx].val = *tmp;
@@ -111,3 +106,4 @@ attrib_list_t* evaluate_attributes(const map<perm_string,PExpr*>&att,
* of complex attributes attached to gates.
*
*/
+55 -434
View File
@@ -22,8 +22,6 @@
# include <iostream>
# include <cstdlib>
# include <cstring>
# include <math.h>
# include "netlist.h"
# include "ivl_assert.h"
@@ -133,19 +131,6 @@ NetExpr* NetEBAdd::eval_tree(int prune_to_width)
verinum lval = lc->value();
verinum rval = rc->value();
if (lval.len() < expr_width())
lval = pad_to_width(lval, expr_width());
if (rval.len() < expr_width())
rval = pad_to_width(rval, expr_width());
if (se->expr_width() > this->expr_width()) {
cerr << get_fileline() << ": internal error: "
<< "expr_width()=" << expr_width()
<< ", sub expr_width()=" << se->expr_width()
<< ", sub expression=" << *se << endl;
}
ivl_assert(*this, se->expr_width() <= this->expr_width());
verinum val;
if (op_ == se->op_) {
/* (a + lval) + rval --> a + (rval+lval) */
@@ -157,15 +142,6 @@ NetExpr* NetEBAdd::eval_tree(int prune_to_width)
val = rval - lval;
}
// Since we padded the operands above to be the minimum
// width, the val should also be at least expr_width().
ivl_assert(*this, val.len() >= expr_width());
if (val.len() > expr_width()) {
verinum tmp (val, expr_width());
tmp.has_sign(val.has_sign());
val = tmp;
}
NetEConst*tmp = new NetEConst(val);
left_ = se->left_->dup_expr();
delete se;
@@ -362,15 +338,19 @@ NetEConst* NetEBComp::eval_leeq_real_(NetExpr*le, NetExpr*ri, bool eq_flag)
switch (le->expr_type()) {
case IVL_VT_REAL:
rtmp = dynamic_cast<NetECReal*> (le);
if (rtmp == 0) return 0;
if (rtmp == 0)
return 0;
lv = rtmp->value().as_double();
break;
case IVL_VT_LOGIC:
case IVL_VT_BOOL:
vtmp = dynamic_cast<NetEConst*> (le);
if (vtmp == 0) return 0;
lv = vtmp->value().as_double();
if (vtmp == 0)
return 0;
lv = vtmp->value().as_long();
break;
default:
@@ -379,18 +359,23 @@ NetEConst* NetEBComp::eval_leeq_real_(NetExpr*le, NetExpr*ri, bool eq_flag)
assert(0);
}
switch (ri->expr_type()) {
case IVL_VT_REAL:
rtmp = dynamic_cast<NetECReal*> (ri);
if (rtmp == 0) return 0;
if (rtmp == 0)
return 0;
rv = rtmp->value().as_double();
break;
case IVL_VT_LOGIC:
case IVL_VT_BOOL:
vtmp = dynamic_cast<NetEConst*> (ri);
if (vtmp == 0) return 0;
rv = vtmp->value().as_double();
if (vtmp == 0)
return 0;
rv = vtmp->value().as_long();
break;
default:
@@ -494,6 +479,19 @@ NetEConst* NetEBComp::eval_gt_()
return tmp;
}
/* Compare with a real value. Do it as double precision. */
if (right_->expr_type() == IVL_VT_REAL) {
NetECReal*tmp = dynamic_cast<NetECReal*>(right_);
if (tmp == 0)
return 0;
double rr = tmp->value().as_double();
double ll = lv.has_sign()? lv.as_long() : lv.as_ulong();
verinum result ((ll > rr)? verinum::V1 : verinum::V0, 1, true);
return new NetEConst(result);
}
/* Now go on to the normal test of the values. */
NetEConst*r = dynamic_cast<NetEConst*>(right_);
if (r == 0) return 0;
@@ -532,6 +530,19 @@ NetEConst* NetEBComp::eval_gteq_()
return tmp;
}
/* Compare with a real value. Do it as double precision. */
if (right_->expr_type() == IVL_VT_REAL) {
NetECReal*tmp = dynamic_cast<NetECReal*>(right_);
if (tmp == 0)
return 0;
double rr = tmp->value().as_double();
double ll = lv.has_sign()? lv.as_long() : lv.as_ulong();
verinum result ((ll >= rr)? verinum::V1 : verinum::V0, 1, true);
return new NetEConst(result);
}
/* Now go on to the normal test of the values. */
NetEConst*r = dynamic_cast<NetEConst*>(right_);
if (r == 0) return 0;
@@ -550,73 +561,8 @@ NetEConst* NetEBComp::eval_gteq_()
}
}
/*
* Evaluate <A>==<B> or <A>!=<B>. The equality operator checks all the
* bits and returns true(false) if there are any bits in the vector
* that are defined (0 or 1) and different. If all the defined bits
* are equal, but there are are x/z bits, then the situation is
* ambiguous so the result is x.
*/
NetEConst* NetEBComp::eval_eqeq_real_(NetExpr*le, NetExpr*ri, bool ne_flag)
{
NetEConst*vtmp;
NetECReal*rtmp;
double lv, rv;
switch (le->expr_type()) {
case IVL_VT_REAL:
rtmp = dynamic_cast<NetECReal*> (le);
if (rtmp == 0) return 0;
lv = rtmp->value().as_double();
break;
case IVL_VT_LOGIC:
case IVL_VT_BOOL:
vtmp = dynamic_cast<NetEConst*> (le);
if (vtmp == 0) return 0;
lv = vtmp->value().as_double();
break;
default:
cerr << get_fileline() << ": internal error: "
<< "Unexpected expression type? " << le->expr_type() << endl;
assert(0);
}
switch (ri->expr_type()) {
case IVL_VT_REAL:
rtmp = dynamic_cast<NetECReal*> (ri);
if (rtmp == 0) return 0;
rv = rtmp->value().as_double();
break;
case IVL_VT_LOGIC:
case IVL_VT_BOOL:
vtmp = dynamic_cast<NetEConst*> (ri);
if (vtmp == 0) return 0;
rv = vtmp->value().as_double();
break;
default:
cerr << get_fileline() << ": internal error: "
<< "Unexpected expression type? " << ri->expr_type() << endl;
assert(0);
}
verinum result(((lv == rv) ^ ne_flag) ? verinum::V1 : verinum::V0, 1);
vtmp = new NetEConst(result);
vtmp->set_line(*this);
return vtmp;
}
NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
{
if (right_->expr_type() == IVL_VT_REAL)
return eval_eqeq_real_(right_, left_, ne_flag);
if (left_->expr_type() == IVL_VT_REAL)
return eval_eqeq_real_(right_, left_, ne_flag);
NetEConst*l = dynamic_cast<NetEConst*>(left_);
if (l == 0) return 0;
NetEConst*r = dynamic_cast<NetEConst*>(right_);
@@ -635,14 +581,11 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
for (unsigned idx = 0 ; idx < top ; idx += 1) {
bool x_bit_present = false;
switch (lv.get(idx)) {
case verinum::Vx:
case verinum::Vz:
res = verinum::Vx;
x_bit_present = true;
break;
default:
@@ -654,20 +597,17 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
case verinum::Vx:
case verinum::Vz:
res = verinum::Vx;
x_bit_present = true;
break;
default:
break;
}
if (x_bit_present)
continue;
if (rv.get(idx) != lv.get(idx)) {
res = ne_res;
if (res == verinum::Vx)
break;
}
if (rv.get(idx) != lv.get(idx))
res = ne_res;
}
if (res != verinum::Vx) {
@@ -826,9 +766,9 @@ NetExpr* NetEBDiv::eval_tree(int prune_to_width)
verireal lval = lc->value();
if (NetECReal*rcr = dynamic_cast<NetECReal*>(right_)) {
if (NetECReal*rc = dynamic_cast<NetECReal*>(right_)) {
NetECReal*tmp = 0;
verireal rval = rcr->value();
verireal rval = rc->value();
switch (op_) {
case '/':
@@ -871,10 +811,8 @@ NetExpr* NetEBDiv::eval_tree(int prune_to_width)
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
if (rc == 0) return 0;
// Make sure the expression is evaluated at the
// expression width.
verinum lval = pad_to_width(lc->value(), expr_width());
verinum rval = pad_to_width(rc->value(), expr_width());
verinum lval = lc->value();
verinum rval = rc->value();
NetExpr*tmp = 0;
switch (op_) {
@@ -1215,11 +1153,6 @@ NetEConst* NetEConcat::eval_tree(int prune_to_width)
val = verinum(val.as_string());
}
// Normally, concatenations are unsigned. However, the
// $signed() function works by marking the expression as
// signed, so we really have to check.
val.has_sign( this->has_sign() );
NetEConst*res = new NetEConst(val);
res->set_width(val.len());
return res;
@@ -1406,7 +1339,7 @@ NetExpr* NetETernary::eval_tree(int prune_to_width)
case C_0:
eval_expr(false_val_);
if (debug_eval_tree) {
cerr << get_fileline() << ": debug: Evaluate ternary with "
<< "constant condition value: ";
print_ternary_cond(cond_);
@@ -1604,7 +1537,6 @@ NetEConst* NetEUReduce::eval_tree(int prune_to_width)
verinum val = rval->value();
verinum::V res;
bool invert = false;
switch (op_) {
@@ -1633,8 +1565,6 @@ NetEConst* NetEUReduce::eval_tree(int prune_to_width)
break;
}
case 'A':
invert = true;
case '&': {
res = verinum::V1;
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
@@ -1642,8 +1572,6 @@ NetEConst* NetEUReduce::eval_tree(int prune_to_width)
break;
}
case 'N':
invert = true;
case '|': {
res = verinum::V0;
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
@@ -1651,8 +1579,6 @@ NetEConst* NetEUReduce::eval_tree(int prune_to_width)
break;
}
case 'X':
invert = true;
case '^': {
/* Reduction XOR. */
unsigned ones = 0, unknown = 0;
@@ -1668,321 +1594,16 @@ NetEConst* NetEUReduce::eval_tree(int prune_to_width)
break;
}
if (unknown) res = verinum::Vx;
else if (ones%2) res = verinum::V1;
else res = verinum::V0;
break;
if (unknown)
return new NetEConst(verinum(verinum::Vx,1,true));
if (ones%2)
return new NetEConst(verinum(verinum::V1,1,true));
return new NetEConst(verinum(verinum::V0,1,true));
}
default:
return 0;
}
if (invert) res = ~res;
return new NetEConst(verinum(res, 1));
}
NetExpr* evaluate_clog2(NetExpr*&arg_)
{
eval_expr(arg_);
NetEConst*tmpi = dynamic_cast<NetEConst *>(arg_);
NetECReal*tmpr = dynamic_cast<NetECReal *>(arg_);
if (tmpi || tmpr) {
verinum arg;
if (tmpi) {
arg = tmpi->value();
} else {
arg = verinum(tmpr->value().as_double(), true);
}
/* If we have an x in the verinum we return 'bx. */
if (!arg.is_defined()) {
verinum tmp (verinum::Vx, integer_width);
tmp.has_sign(true);
NetEConst*rtn = new NetEConst(tmp);
return rtn;
}
bool is_neg = false;
uint64_t res = 0;
if (arg.is_negative()) {
is_neg = true;
// If the length is not defined, then work with
// the trimmed version of the number.
if (! arg.has_len())
arg = trim_vnum(arg);
}
arg.has_sign(false); // $unsigned()
if (!arg.is_zero()) {
arg = arg - verinum((uint64_t)1, 1);
while (!arg.is_zero()) {
res += 1;
arg = arg >> 1;
}
}
if (is_neg && res < integer_width)
res = integer_width;
verinum tmp (res, integer_width);
NetEConst*rtn = new NetEConst(tmp);
return rtn;
}
return 0;
}
NetExpr* evaluate_math_one_arg(NetExpr*&arg_, const char*name)
{
eval_expr(arg_);
NetEConst*tmpi = dynamic_cast<NetEConst *>(arg_);
NetECReal*tmpr = dynamic_cast<NetECReal *>(arg_);
if (tmpi || tmpr) {
double arg;
if (tmpi) {
arg = tmpi->value().as_double();
} else {
arg = tmpr->value().as_double();
}
if (strcmp(name, "$ln") == 0) {
return new NetECReal(verireal(log(arg)));
} else if (strcmp(name, "$log") == 0) {
return new NetECReal(verireal(log10(arg)));
} else if (strcmp(name, "$log10") == 0) {
return new NetECReal(verireal(log10(arg)));
} else if (strcmp(name, "$exp") == 0) {
return new NetECReal(verireal(exp(arg)));
} else if (strcmp(name, "$sqrt") == 0) {
return new NetECReal(verireal(sqrt(arg)));
} else if (strcmp(name, "$floor") == 0) {
return new NetECReal(verireal(floor(arg)));
} else if (strcmp(name, "$ceil") == 0) {
return new NetECReal(verireal(ceil(arg)));
} else if (strcmp(name, "$sin") == 0) {
return new NetECReal(verireal(sin(arg)));
} else if (strcmp(name, "$cos") == 0) {
return new NetECReal(verireal(cos(arg)));
} else if (strcmp(name, "$tan") == 0) {
return new NetECReal(verireal(tan(arg)));
} else if (strcmp(name, "$asin") == 0) {
return new NetECReal(verireal(asin(arg)));
} else if (strcmp(name, "$acos") == 0) {
return new NetECReal(verireal(acos(arg)));
} else if (strcmp(name, "$atan") == 0) {
return new NetECReal(verireal(atan(arg)));
} else if (strcmp(name, "$sinh") == 0) {
return new NetECReal(verireal(sinh(arg)));
} else if (strcmp(name, "$cosh") == 0) {
return new NetECReal(verireal(cosh(arg)));
} else if (strcmp(name, "$tanh") == 0) {
return new NetECReal(verireal(tanh(arg)));
} else if (strcmp(name, "$asinh") == 0) {
return new NetECReal(verireal(asinh(arg)));
} else if (strcmp(name, "$acosh") == 0) {
return new NetECReal(verireal(acosh(arg)));
} else if (strcmp(name, "$atanh") == 0) {
return new NetECReal(verireal(atanh(arg)));
}
}
return 0;
}
NetExpr* evaluate_math_two_args(NetExpr*&arg0_, NetExpr*&arg1_, const char*name)
{
eval_expr(arg0_);
eval_expr(arg1_);
NetEConst*tmpi0 = dynamic_cast<NetEConst *>(arg0_);
NetECReal*tmpr0 = dynamic_cast<NetECReal *>(arg0_);
NetEConst*tmpi1 = dynamic_cast<NetEConst *>(arg1_);
NetECReal*tmpr1 = dynamic_cast<NetECReal *>(arg1_);
if ((tmpi0 || tmpr0) && (tmpi1 || tmpr1)) {
double arg0, arg1;
if (tmpi0) {
arg0 = tmpi0->value().as_double();
} else {
arg0 = tmpr0->value().as_double();
}
if (tmpi1) {
arg1 = tmpi1->value().as_double();
} else {
arg1 = tmpr1->value().as_double();
}
if (strcmp(name, "$pow") == 0) {
return new NetECReal(verireal(pow(arg0, arg1)));
} else if (strcmp(name, "$atan2") == 0) {
return new NetECReal(verireal(atan2(arg0, arg1)));
} else if (strcmp(name, "$hypot") == 0) {
return new NetECReal(verireal(hypot(arg0, arg1)));
}
}
return 0;
}
NetExpr* evaluate_abs(NetExpr*&arg_)
{
eval_expr(arg_);
NetEConst*tmpi = dynamic_cast<NetEConst *>(arg_);
if (tmpi) {
verinum arg = tmpi->value();
if (arg.is_negative()) {
arg = v_not(arg) + verinum(1);
}
return new NetEConst(arg);
}
NetECReal*tmpr = dynamic_cast<NetECReal *>(arg_);
if (tmpr) {
double arg = tmpr->value().as_double();
return new NetECReal(verireal(fabs(arg)));
}
return 0;
}
NetExpr* evaluate_min_max(NetExpr*&arg0_, NetExpr*&arg1_, const char*name)
{
eval_expr(arg0_);
eval_expr(arg1_);
NetEConst*tmpi0 = dynamic_cast<NetEConst *>(arg0_);
NetECReal*tmpr0 = dynamic_cast<NetECReal *>(arg0_);
NetEConst*tmpi1 = dynamic_cast<NetEConst *>(arg1_);
NetECReal*tmpr1 = dynamic_cast<NetECReal *>(arg1_);
if (tmpi0 && tmpi1) {
verinum arg0 = tmpi0->value();
verinum arg1 = tmpi1->value();
if (strcmp(name, "$min") == 0) {
return new NetEConst( arg0 < arg1 ? arg0 : arg1);
} else if (strcmp(name, "$max") == 0) {
return new NetEConst( arg0 < arg1 ? arg1 : arg0);
}
}
if ((tmpi0 || tmpr0) && (tmpi1 || tmpr1)) {
double arg0, arg1;
if (tmpi0) {
arg0 = tmpi0->value().as_double();
} else {
arg0 = tmpr0->value().as_double();
}
if (tmpi1) {
arg1 = tmpi1->value().as_double();
} else {
arg1 = tmpr1->value().as_double();
}
if (strcmp(name, "$min") == 0) {
return new NetECReal(verireal(arg0 < arg1 ? arg0 : arg1));
} else if (strcmp(name, "$max") == 0) {
return new NetECReal(verireal(arg0 < arg1 ? arg1 : arg0));
}
}
return 0;
}
NetExpr* NetESFunc::eval_tree(int prune_to_width)
{
/* If we are not targeting at least Verilog-2005, Verilog-AMS
* or using the Icarus misc flag then we do not support these
* functions as constant. */
if (generation_flag < GN_VER2005 &&
!gn_icarus_misc_flag && !gn_verilog_ams_flag) {
return 0;
}
const char*nm = name();
NetExpr*rtn = 0;
/* Only $clog2 and the builtin mathematical functions can
* be a constant system function. */
if (strcmp(nm, "$clog2") == 0 ||
strcmp(nm, "$ln") == 0 ||
strcmp(nm, "$log10") == 0 ||
strcmp(nm, "$exp") == 0 ||
strcmp(nm, "$sqrt") == 0 ||
strcmp(nm, "$floor") == 0 ||
strcmp(nm, "$ceil") == 0 ||
strcmp(nm, "$sin") == 0 ||
strcmp(nm, "$cos") == 0 ||
strcmp(nm, "$tan") == 0 ||
strcmp(nm, "$asin") == 0 ||
strcmp(nm, "$acos") == 0 ||
strcmp(nm, "$atan") == 0 ||
strcmp(nm, "$sinh") == 0 ||
strcmp(nm, "$cosh") == 0 ||
strcmp(nm, "$tanh") == 0 ||
strcmp(nm, "$asinh") == 0 ||
strcmp(nm, "$acosh") == 0 ||
strcmp(nm, "$atanh") == 0) {
if (nparms() != 1 || parm(0) == 0) {
cerr << get_fileline() << ": error: " << nm
<< " takes a single argument." << endl;
return 0;
}
NetExpr*arg = parm(0)->dup_expr();
if (strcmp(nm, "$clog2") == 0) {
rtn = evaluate_clog2(arg);
} else {
rtn = evaluate_math_one_arg(arg, nm);
}
delete arg;
}
if (strcmp(nm, "$pow") == 0 ||
strcmp(nm, "$atan2") == 0 ||
strcmp(nm, "$hypot") == 0) {
if (nparms() != 2 || parm(0) == 0 || parm(1) == 0) {
cerr << get_fileline() << ": error: " << nm
<< " takes two arguments." << endl;
return 0;
}
NetExpr*arg0 = parm(0)->dup_expr();
NetExpr*arg1 = parm(1)->dup_expr();
rtn = evaluate_math_two_args(arg0, arg1, nm);
delete arg0;
delete arg1;
}
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
(strcmp(nm, "$log") == 0 || strcmp(nm, "$abs") == 0)) {
if (nparms() != 1 || parm(0) == 0) {
cerr << get_fileline() << ": error: " << nm
<< " takes a single argument." << endl;
return 0;
}
NetExpr*arg = parm(0)->dup_expr();
if (strcmp(nm, "$log") == 0) {
rtn = evaluate_math_one_arg(arg, nm);
} else {
rtn = evaluate_abs(arg);
}
delete arg;
}
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
(strcmp(nm, "$min") == 0 || strcmp(nm, "$max") == 0)) {
if (nparms() != 2 || parm(0) == 0 || parm(1) == 0) {
cerr << get_fileline() << ": error: " << nm
<< " takes two arguments." << endl;
return 0;
}
NetExpr*arg0 = parm(0)->dup_expr();
NetExpr*arg1 = parm(1)->dup_expr();
rtn = evaluate_min_max(arg0, arg1, nm);
delete arg0;
delete arg1;
}
if (rtn != 0) {
rtn->set_line(*this);
if (debug_eval_tree) {
cerr << get_fileline() << ": debug: Evaluate constant "
<< nm << "." << endl;
}
}
return rtn;
}
+1 -1
View File
@@ -154,7 +154,7 @@
*
* The POST_MAP compiler directive causes the GSR manipulations
* included in the test bench to be compiled in, to simulate the chip
* startup. Other than that, the test bench runs the post-map design
* startup. Other then that, the test bench runs the post-map design
* the same way the pre-synthesis design works.
*
* Run this design with the command:
+162 -360
View File
@@ -20,56 +20,56 @@
# include "config.h"
# include "compiler.h"
# include <cstdlib>
# include <iostream>
# include "netlist.h"
# include "netmisc.h"
# include "ivl_assert.h"
static NetNet* convert_to_real_const(Design*des, NetScope*scope, NetEConst*expr)
NetNet* convert_to_real_const(Design*des, NetExpr*expr, NetExpr*obj)
{
verireal vrl(expr->value().as_double());
NetECReal rlval(vrl);
NetNet* sig = rlval.synthesize(des, scope);
NetNet* sig;
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
verireal vrl(tmp->value().as_double());
NetECReal rlval(vrl);
sig = rlval.synthesize(des);
} else {
cerr << obj->get_fileline() << ": sorry: Cannot convert "
"bit based value (" << *expr << ") to real." << endl;
des->errors += 1;
sig = 0;
}
return sig;
}
/* Note that lsig, rsig and real_args are references. */
static bool process_binary_args(Design*des, NetScope*scope,
NetExpr*left, NetExpr*right,
NetNet*&lsig, NetNet*&rsig, bool&real_args,
NetExpr*obj)
bool process_binary_args(Design*des, NetExpr*left, NetExpr*right,
NetNet*&lsig, NetNet*&rsig, bool&real_args,
NetExpr*obj)
{
if (left->expr_type() == IVL_VT_REAL ||
right->expr_type() == IVL_VT_REAL) {
real_args = true;
/* Convert the arguments to real. Handle the special
cases of constants, which can be converted more directly. */
/* Currently we will have a runtime assert if both expressions
are not real, though we can convert constants. */
if (left->expr_type() == IVL_VT_REAL) {
lsig = left->synthesize(des, scope);
} else if (NetEConst*tmpc = dynamic_cast<NetEConst*> (left)) {
lsig = convert_to_real_const(des, scope, tmpc);
lsig = left->synthesize(des);
} else {
NetNet*tmp = left->synthesize(des, scope);
lsig = cast_to_real(des, scope, tmp);
lsig = convert_to_real_const(des, left, obj);
}
if (right->expr_type() == IVL_VT_REAL) {
rsig = right->synthesize(des, scope);
} else if (NetEConst*tmpc = dynamic_cast<NetEConst*> (right)) {
rsig = convert_to_real_const(des, scope, tmpc);
rsig = right->synthesize(des);
} else {
NetNet*tmp = right->synthesize(des, scope);
rsig = cast_to_real(des, scope, tmp);
rsig = convert_to_real_const(des, right, obj);
}
} else {
real_args = false;
lsig = left->synthesize(des, scope);
rsig = right->synthesize(des, scope);
lsig = left->synthesize(des);
rsig = right->synthesize(des);
}
@@ -77,7 +77,7 @@ static bool process_binary_args(Design*des, NetScope*scope,
else return false;
}
NetNet* NetExpr::synthesize(Design*des, NetScope*scope)
NetNet* NetExpr::synthesize(Design*des)
{
cerr << get_fileline() << ": internal error: cannot synthesize expression: "
<< *this << endl;
@@ -88,35 +88,25 @@ NetNet* NetExpr::synthesize(Design*des, NetScope*scope)
/*
* Make an LPM_ADD_SUB device from addition operators.
*/
NetNet* NetEBAdd::synthesize(Design*des, NetScope*scope)
NetNet* NetEBAdd::synthesize(Design*des)
{
ivl_assert(*this, (op()=='+') || (op()=='-'));
assert((op()=='+') || (op()=='-'));
NetNet *lsig=0, *rsig=0;
bool real_args=false;
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
if (process_binary_args(des, left_, right_, lsig, rsig,
real_args, this)) {
return 0;
}
ivl_assert(*this, expr_width() >= lsig->vector_width());
ivl_assert(*this, expr_width() >= rsig->vector_width());
assert(expr_width() >= lsig->vector_width());
assert(expr_width() >= rsig->vector_width());
unsigned width;
if (expr_type() == IVL_VT_REAL) {
width = 1;
if (lsig->data_type() != IVL_VT_REAL)
lsig = cast_to_real(des, scope, lsig);
if (rsig->data_type() != IVL_VT_REAL)
rsig = cast_to_real(des, scope, rsig);
lsig = pad_to_width(des, lsig, expr_width());
rsig = pad_to_width(des, rsig, expr_width());
} else {
lsig = pad_to_width(des, lsig, expr_width());
rsig = pad_to_width(des, rsig, expr_width());
assert(lsig->vector_width() == rsig->vector_width());
width=lsig->vector_width();
}
assert(lsig->vector_width() == rsig->vector_width());
unsigned width=lsig->vector_width();
perm_string path = lsig->scope()->local_symbol();
NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, width);
@@ -148,10 +138,10 @@ NetNet* NetEBAdd::synthesize(Design*des, NetScope*scope)
* signals, then just connect a single gate to each bit of the vector
* of the expression.
*/
NetNet* NetEBBits::synthesize(Design*des, NetScope*scope)
NetNet* NetEBBits::synthesize(Design*des)
{
NetNet*lsig = left_->synthesize(des, scope);
NetNet*rsig = right_->synthesize(des, scope);
NetNet*lsig = left_->synthesize(des);
NetNet*rsig = right_->synthesize(des);
if (lsig == 0 || rsig == 0) return 0;
@@ -164,7 +154,10 @@ NetNet* NetEBBits::synthesize(Design*des, NetScope*scope)
return 0;
}
unsigned width = expr_width();
NetScope*scope = lsig->scope();
assert(scope);
unsigned width = lsig->vector_width();
if (rsig->vector_width() > width) width = rsig->vector_width();
lsig = pad_to_width(des, lsig, width);
@@ -212,13 +205,13 @@ NetNet* NetEBBits::synthesize(Design*des, NetScope*scope)
return osig;
}
NetNet* NetEBComp::synthesize(Design*des, NetScope*scope)
NetNet* NetEBComp::synthesize(Design*des)
{
NetNet *lsig=0, *rsig=0;
unsigned width;
bool real_args=false;
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
if (process_binary_args(des, left_, right_, lsig, rsig,
real_args, this)) {
return 0;
}
@@ -229,58 +222,24 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope)
width = lsig->vector_width();
if (rsig->vector_width() > width) width = rsig->vector_width();
if (lsig->get_signed())
lsig = pad_to_width_signed(des, lsig, width);
else
lsig = pad_to_width(des, lsig, width);
if (rsig->get_signed())
rsig = pad_to_width_signed(des, rsig, width);
else
rsig = pad_to_width(des, rsig, width);
lsig = pad_to_width(des, lsig, width);
rsig = pad_to_width(des, rsig, width);
}
NetScope*scope = lsig->scope();
assert(scope);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
osig->set_line(*this);
osig->local_flag(true);
osig->data_type(IVL_VT_LOGIC);
// Test if the comparison is signed.
//
// Note 1: This is not the same as asking if the result is
// signed. In fact, the result will typically be UNsigned. The
// decision to make the comparison signed depends on the
// operand expressions.
//
// Note 2: The operand expressions may be signed even if the
// sig that comes out of synthesis is unsigned. The $signed()
// function marks the expression but doesn't change the
// underlying signals.
bool signed_compare = left_->has_sign() && right_->has_sign();
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Comparison (" << op_ << ")"
<< " is " << (signed_compare? "signed" : "unsigned")
<< endl;
cerr << get_fileline() << ": : lsig is "
<< (lsig->get_signed()? "signed" : "unsigned")
<< " rsig is " << (rsig->get_signed()? "signed" : "unsigned")
<< endl;
}
if (op_ == 'E' || op_ == 'N') {
NetCaseCmp*gate = new NetCaseCmp(scope, scope->local_symbol(),
width, op_=='E'?true:false);
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;
}
bool signed_compare = lsig->get_signed() && rsig->get_signed();
/* Handle the special case of a single bit equality
operation. Make an XNOR gate instead of a comparator. */
if ((width == 1) && (op_ == 'e') && !real_args) {
if ((width == 1) && ((op_ == 'e') || (op_ == 'E')) && !real_args) {
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
3, NetLogic::XNOR, 1);
gate->set_line(*this);
@@ -294,7 +253,7 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope)
/* Handle the special case of a single bit inequality
operation. This is similar to single bit equality, but uses
an XOR instead of an XNOR gate. */
if ((width == 1) && (op_ == 'n') && !real_args) {
if ((width == 1) && ((op_ == 'n') || (op_ == 'N')) && !real_args) {
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
3, NetLogic::XOR, 1);
gate->set_line(*this);
@@ -362,12 +321,12 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope)
return osig;
}
NetNet* NetEBPow::synthesize(Design*des, NetScope*scope)
NetNet* NetEBPow::synthesize(Design*des)
{
NetNet *lsig=0, *rsig=0;
unsigned width;
bool real_args=false;
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
if (process_binary_args(des, left_, right_, lsig, rsig,
real_args, this)) {
return 0;
}
@@ -375,6 +334,9 @@ NetNet* NetEBPow::synthesize(Design*des, NetScope*scope)
if (real_args) width = 1;
else width = expr_width();
NetScope*scope = lsig->scope();
assert(scope);
NetPow*powr = new NetPow(scope, scope->local_symbol(), width,
lsig->vector_width(),
rsig->vector_width());
@@ -397,12 +359,12 @@ NetNet* NetEBPow::synthesize(Design*des, NetScope*scope)
return osig;
}
NetNet* NetEBMult::synthesize(Design*des, NetScope*scope)
NetNet* NetEBMult::synthesize(Design*des)
{
NetNet *lsig=0, *rsig=0;
unsigned width;
bool real_args=false;
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
if (process_binary_args(des, left_, right_, lsig, rsig,
real_args, this)) {
return 0;
}
@@ -410,6 +372,9 @@ NetNet* NetEBMult::synthesize(Design*des, NetScope*scope)
if (real_args) width = 1;
else width = expr_width();
NetScope*scope = lsig->scope();
assert(scope);
NetMult*mult = new NetMult(scope, scope->local_symbol(),
width,
lsig->vector_width(),
@@ -433,12 +398,12 @@ NetNet* NetEBMult::synthesize(Design*des, NetScope*scope)
return osig;
}
NetNet* NetEBDiv::synthesize(Design*des, NetScope*scope)
NetNet* NetEBDiv::synthesize(Design*des)
{
NetNet *lsig=0, *rsig=0;
unsigned width;
bool real_args=false;
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
if (process_binary_args(des, left_, right_, lsig, rsig,
real_args, this)) {
return 0;
}
@@ -446,11 +411,12 @@ NetNet* NetEBDiv::synthesize(Design*des, NetScope*scope)
if (real_args) width = 1;
else width = expr_width();
NetScope*scope = lsig->scope();
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, width);
osig->set_line(*this);
osig->data_type(lsig->data_type());
osig->set_signed(has_sign());
osig->local_flag(true);
switch (op()) {
@@ -461,7 +427,6 @@ NetNet* NetEBDiv::synthesize(Design*des, NetScope*scope)
lsig->vector_width(),
rsig->vector_width());
div->set_line(*this);
div->set_signed(has_sign());
des->add_node(div);
connect(div->pin_DataA(), lsig->pin(0));
@@ -484,7 +449,6 @@ NetNet* NetEBDiv::synthesize(Design*des, NetScope*scope)
lsig->vector_width(),
rsig->vector_width());
div->set_line(*this);
div->set_signed(has_sign());
des->add_node(div);
connect(div->pin_DataA(), lsig->pin(0));
@@ -495,7 +459,7 @@ NetNet* NetEBDiv::synthesize(Design*des, NetScope*scope)
default: {
cerr << get_fileline() << ": internal error: "
<< "NetEBDiv has unexpected op() code: "
<< "NetEBDiv has unexpeced op() code: "
<< op() << endl;
des->errors += 1;
@@ -507,10 +471,10 @@ NetNet* NetEBDiv::synthesize(Design*des, NetScope*scope)
return osig;
}
NetNet* NetEBLogic::synthesize(Design*des, NetScope*scope)
NetNet* NetEBLogic::synthesize(Design*des)
{
NetNet*lsig = left_->synthesize(des, scope);
NetNet*rsig = right_->synthesize(des, scope);
NetNet*lsig = left_->synthesize(des);
NetNet*rsig = right_->synthesize(des);
if (lsig == 0 || rsig == 0) return 0;
@@ -523,6 +487,9 @@ NetNet* NetEBLogic::synthesize(Design*des, NetScope*scope)
return 0;
}
NetScope*scope = lsig->scope();
assert(scope);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
osig->data_type(expr_type());
@@ -584,11 +551,11 @@ NetNet* NetEBLogic::synthesize(Design*des, NetScope*scope)
return osig;
}
NetNet* NetEBShift::synthesize(Design*des, NetScope*scope)
NetNet* NetEBShift::synthesize(Design*des)
{
eval_expr(right_);
NetNet*lsig = left_->synthesize(des, scope);
NetNet*lsig = left_->synthesize(des);
if (lsig == 0) return 0;
@@ -601,8 +568,10 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope)
return 0;
}
const bool right_flag = op_ == 'r' || op_ == 'R';
const bool signed_flag = op_ == 'R';
bool right_flag = op_ == 'r' || op_ == 'R';
bool signed_flag = op_ == 'R';
NetScope*scope = lsig->scope();
/* Detect the special case where the shift amount is
constant. Evaluate the shift amount, and simply reconnect
@@ -611,7 +580,7 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope)
verinum shift_v = rcon->value();
long shift = shift_v.as_long();
if (right_flag)
if (op() == 'r')
shift = 0-shift;
if (shift == 0)
@@ -624,13 +593,34 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope)
// ushift is the amount of pad created by the shift.
unsigned long ushift = shift>=0? shift : -shift;
ivl_assert(*this, ushift < osig->vector_width());
if (ushift > osig->vector_width())
ushift = osig->vector_width();
// part_width is the bits of the vector that survive the shift.
unsigned long part_width = osig->vector_width() - ushift;
// Create a part select to reduce the width of the lsig
// to the amount left by the shift.
verinum znum (verinum::V0, ushift, true);
NetConst*zcon = new NetConst(scope, scope->local_symbol(),
znum);
des->add_node(zcon);
/* Detect the special case that the shift is the size of
the whole expression. Simply connect the pad to the
osig and escape. */
if (ushift >= osig->vector_width()) {
connect(zcon->pin(0), osig->pin(0));
return osig;
}
NetNet*zsig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, znum.len());
zsig->data_type(osig->data_type());
zsig->local_flag(true);
zsig->set_line(*this);
connect(zcon->pin(0), zsig->pin(0));
/* Create a part select to reduce the width of the lsig
to the amount left by the shift. */
NetPartSelect*psel = new NetPartSelect(lsig, shift<0? ushift : 0,
part_width,
NetPartSelect::VP);
@@ -643,34 +633,6 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope)
psig->set_line(*this);
connect(psig->pin(0), psel->pin(0));
// Handle the special case of a signed right shift. In
// this case, use the NetSignExtend device to pad the
// result to the desired width.
if (signed_flag && right_flag) {
NetSignExtend*pad = new NetSignExtend(scope, scope->local_symbol(),
osig->vector_width());
des->add_node(pad);
pad->set_line(*this);
connect(pad->pin(1), psig->pin(0));
connect(pad->pin(0), osig->pin(0));
return osig;
}
// Other cases are handled by zero-extending on the
// proper end.
verinum znum (verinum::V0, ushift, true);
NetConst*zcon = new NetConst(scope, scope->local_symbol(),
znum);
des->add_node(zcon);
NetNet*zsig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, znum.len());
zsig->data_type(osig->data_type());
zsig->local_flag(true);
zsig->set_line(*this);
connect(zcon->pin(0), zsig->pin(0));
NetConcat*ccat = new NetConcat(scope, scope->local_symbol(),
osig->vector_width(), 2);
ccat->set_line(*this);
@@ -690,7 +652,7 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope)
return osig;
}
NetNet*rsig = right_->synthesize(des, scope);
NetNet*rsig = right_->synthesize(des);
if (rsig == 0) return 0;
@@ -716,13 +678,13 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope)
return osig;
}
NetNet* NetEConcat::synthesize(Design*des, NetScope*scope)
NetNet* NetEConcat::synthesize(Design*des)
{
/* First, synthesize the operands. */
NetNet**tmp = new NetNet*[parms_.count()];
bool flag = true;
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
tmp[idx] = parms_[idx]->synthesize(des, scope);
tmp[idx] = parms_[idx]->synthesize(des);
if (tmp[idx] == 0)
flag = false;
}
@@ -730,7 +692,9 @@ NetNet* NetEConcat::synthesize(Design*des, NetScope*scope)
if (flag == false)
return 0;
ivl_assert(*this, tmp[0]);
assert(tmp[0]);
NetScope*scope = tmp[0]->scope();
assert(scope);
/* Make a NetNet object to carry the output vector. */
perm_string path = scope->local_symbol();
@@ -748,9 +712,7 @@ NetNet* NetEConcat::synthesize(Design*des, NetScope*scope)
unsigned cur_pin = 1;
for (unsigned rpt = 0; rpt < repeat(); rpt += 1) {
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
unsigned concat_item = parms_.count()-idx-1;
ivl_assert(*this, tmp[concat_item]);
connect(concat->pin(cur_pin), tmp[concat_item]->pin(0));
connect(concat->pin(cur_pin), tmp[parms_.count()-idx-1]->pin(0));
cur_pin += 1;
}
}
@@ -759,14 +721,17 @@ NetNet* NetEConcat::synthesize(Design*des, NetScope*scope)
return osig;
}
NetNet* NetEConst::synthesize(Design*des, NetScope*scope)
NetNet* NetEConst::synthesize(Design*des)
{
NetScope*scope = des->find_root_scope();
assert(scope);
perm_string path = scope->local_symbol();
unsigned width=expr_width();
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width);
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width-1,0);
osig->local_flag(true);
osig->data_type(expr_type());
osig->data_type(IVL_VT_LOGIC);
osig->set_signed(has_sign());
NetConst*con = new NetConst(scope, scope->local_symbol(), value());
connect(osig->pin(0), con->pin(0));
@@ -778,8 +743,11 @@ NetNet* NetEConst::synthesize(Design*des, NetScope*scope)
/*
* Create a NetLiteral object to represent real valued constants.
*/
NetNet* NetECReal::synthesize(Design*des, NetScope*scope)
NetNet* NetECReal::synthesize(Design*des)
{
NetScope*scope = des->find_root_scope();
assert(scope);
perm_string path = scope->local_symbol();
NetNet*osig = new NetNet(scope, path, NetNet::WIRE, 1);
@@ -800,9 +768,9 @@ NetNet* NetECReal::synthesize(Design*des, NetScope*scope)
* The bitwise unary logic operator (there is only one) is turned
* into discrete gates just as easily as the binary ones above.
*/
NetNet* NetEUBits::synthesize(Design*des, NetScope*scope)
NetNet* NetEUBits::synthesize(Design*des)
{
NetNet*isig = expr_->synthesize(des, scope);
NetNet*isig = expr_->synthesize(des);
if (isig == 0) return 0;
@@ -814,6 +782,9 @@ NetNet* NetEUBits::synthesize(Design*des, NetScope*scope)
return 0;
}
NetScope*scope = isig->scope();
assert(scope);
unsigned width = isig->vector_width();
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, width);
@@ -839,56 +810,13 @@ NetNet* NetEUBits::synthesize(Design*des, NetScope*scope)
return osig;
}
NetNet* NetEUnary::synthesize(Design*des, NetScope*scope)
NetNet* NetEUReduce::synthesize(Design*des)
{
if (op_ == '+')
return expr_->synthesize(des, scope);
if (op_ == '-') {
NetNet*sig = expr_->synthesize(des, scope);
sig = sub_net_from(des, scope, 0, sig);
return sig;
}
if (op_ == 'm') {
NetNet*sub = expr_->synthesize(des, scope);
if (expr_->has_sign() == false)
return sub;
NetNet*sig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, sub->vector_width());
sig->set_line(*this);
sig->local_flag(true);
sig->data_type(sub->data_type());
NetAbs*tmp = new NetAbs(scope, scope->local_symbol(), sub->vector_width());
des->add_node(tmp);
tmp->set_line(*this);
connect(tmp->pin(1), sub->pin(0));
connect(tmp->pin(0), sig->pin(0));
return sig;
}
cerr << get_fileline() << ": iternal error: "
<< "NetEUnary::synthesize cannot handle op_=" << op_ << endl;
des->errors += 1;
return expr_->synthesize(des, scope);
}
NetNet* NetEUReduce::synthesize(Design*des, NetScope*scope)
{
NetNet*isig = expr_->synthesize(des, scope);
NetNet*isig = expr_->synthesize(des);
if (isig == 0) return 0;
if (isig->data_type() == IVL_VT_REAL) {
if (op() == '!') {
cerr << get_fileline() << ": sorry: ! is currently "
"unsupported for real values." << endl;
des->errors += 1;
return 0;
}
cerr << get_fileline() << ": error: reduction operator ("
<< human_readable_op(op_)
<< ") may not have a REAL operand." << endl;
@@ -896,6 +824,9 @@ NetNet* NetEUReduce::synthesize(Design*des, NetScope*scope)
return 0;
}
NetScope*scope = isig->scope();
assert(scope);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
osig->data_type(expr_type());
@@ -918,7 +849,7 @@ NetNet* NetEUReduce::synthesize(Design*des, NetScope*scope)
rtype = NetUReduce::XOR;
break;
case 'A':
rtype = NetUReduce::NAND;
rtype = NetUReduce::XNOR;
break;
case 'X':
rtype = NetUReduce::XNOR;
@@ -940,101 +871,22 @@ NetNet* NetEUReduce::synthesize(Design*des, NetScope*scope)
return osig;
}
/*
* Turn a part/bit select expression into gates.
* We know some things about the expression that elaboration enforces
* for us:
*
* - Expression elaboration already converted the offset expression into
* canonical form, so we don't have to worry about that here.
*/
NetNet* NetESelect::synthesize(Design *des, NetScope*scope)
NetNet* NetESelect::synthesize(Design *des)
{
NetNet*sub = expr_->synthesize(des, scope);
NetNet*sub = expr_->synthesize(des);
if (sub == 0) return 0;
NetScope*scope = sub->scope();
NetNet*off = 0;
// Detect the special case that there is a base expression and
// it is constant. In this case we can generate fixed part selects.
if (NetEConst*base_const = dynamic_cast<NetEConst*>(base_)) {
verinum base_tmp = base_const->value();
ivl_assert(*this, base_tmp.is_defined());
long base_val = base_tmp.as_long();
unsigned select_width = expr_width();
// Any below X bits?
NetNet*below = 0;
if (base_val < 0) {
unsigned below_width = abs(base_val);
base_val = 0;
ivl_assert(*this, below_width < select_width);
select_width -= below_width;
below = make_const_x(des, scope, below_width);
below->set_line(*this);
}
// Any above bits?
NetNet*above = 0;
if ((unsigned)base_val+select_width > sub->vector_width()) {
select_width = sub->vector_width() - base_val;
unsigned above_width = expr_width() - select_width;
above = make_const_x(des, scope, above_width);
above->set_line(*this);
}
// Make the make part select.
NetPartSelect*sel = new NetPartSelect(sub, base_val, select_width,
NetPartSelect::VP);
des->add_node(sel);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, select_width);
tmp->data_type(sub->data_type());
tmp->local_flag(true);
tmp->set_line(*this);
connect(sel->pin(0), tmp->pin(0));
unsigned concat_count = 1;
if (above)
concat_count += 1;
if (below)
concat_count += 1;
if (concat_count > 1) {
NetConcat*cat = new NetConcat(scope, scope->local_symbol(),
expr_width(), concat_count);
cat->set_line(*this);
des->add_node(cat);
if (below) {
connect(cat->pin(1), below->pin(0));
connect(cat->pin(2), tmp->pin(0));
} else {
connect(cat->pin(1), tmp->pin(0));
}
if (above) {
connect(cat->pin(concat_count), above->pin(0));
}
tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, expr_width());
tmp->data_type(sub->data_type());
tmp->local_flag(true);
tmp->set_line(*this);
connect(cat->pin(0), tmp->pin(0));
}
return tmp;
}
// This handles the case that the NetESelect exists to do an
// actual part/bit select. Generate a NetPartSelect object to
// do the work, and replace "sub" with the selected output.
if (base_ != 0) {
off = base_->synthesize(des, scope);
off = base_->synthesize(des);
NetPartSelect*sel = new NetPartSelect(sub, off, expr_width());
sel->set_line(*this);
@@ -1115,26 +967,21 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope)
* expressions to the B and A inputs. This way, when the select input
* is one, the B input, which is the true expression, is selected.
*/
NetNet* NetETernary::synthesize(Design *des, NetScope*scope)
NetNet* NetETernary::synthesize(Design *des)
{
NetNet*csig = cond_->synthesize(des, scope),
*tsig = true_val_->synthesize(des, scope),
*fsig = false_val_->synthesize(des, scope);
NetNet*csig = cond_->synthesize(des),
*tsig = true_val_->synthesize(des),
*fsig = false_val_->synthesize(des);
if (csig == 0 || tsig == 0 || fsig == 0) return 0;
if (! NetETernary::test_operand_compat(tsig->data_type(),fsig->data_type())) {
cerr << get_fileline() << ": internal error: "
<< " True and False clauses of ternary expression "
<< " have incompatible types." << endl;
if (tsig->data_type() != fsig->data_type()) {
cerr << get_fileline() << ": error: True and False clauses of "
"ternary expression have different types." << endl;
cerr << get_fileline() << ": : True clause is: "
<< tsig->data_type()
<< " (" << true_val_->expr_type() << "): "
<< *true_val_ << endl;
<< tsig->data_type() << endl;
cerr << get_fileline() << ": : False clause is: "
<< fsig->data_type()
<< " (" << false_val_->expr_type() << "): "
<< *false_val_ << endl;
<< fsig->data_type() << endl;
des->errors += 1;
return 0;
} else if (tsig->data_type() == IVL_VT_NO_TYPE) {
@@ -1146,7 +993,7 @@ NetNet* NetETernary::synthesize(Design *des, NetScope*scope)
perm_string path = csig->scope()->local_symbol();
ivl_assert(*this, csig->vector_width() == 1);
assert(csig->vector_width() == 1);
unsigned width=expr_width();
NetNet*osig = new NetNet(csig->scope(), path, NetNet::IMPLICIT, width);
@@ -1178,25 +1025,26 @@ NetNet* NetETernary::synthesize(Design *des, NetScope*scope)
* a bit more work needs to be done. Return a temporary that represents
* the selected word.
*/
NetNet* NetESignal::synthesize(Design*des, NetScope*scope)
NetNet* NetESignal::synthesize(Design*des)
{
if (word_ == 0)
return net_;
NetScope*scope = net_->scope();
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, net_->vector_width());
tmp->set_line(*this);
tmp->local_flag(true);
tmp->data_type(net_->data_type());
// For NetExpr objects, the word index is already converted to
// a canonical (lsb==0) address. Just use the index directly.
if (NetEConst*index_co = dynamic_cast<NetEConst*> (word_)) {
long index = index_co->value().as_long();
connect(tmp->pin(0), net_->pin(index));
assert(net_->array_index_is_valid(index));
index = net_->array_index_to_address(index);
connect(tmp->pin(0), net_->pin(index));
} else {
unsigned selwid = word_->expr_width();
@@ -1205,7 +1053,7 @@ NetNet* NetESignal::synthesize(Design*des, NetScope*scope)
mux->set_line(*this);
des->add_node(mux);
NetNet*index_net = word_->synthesize(des, scope);
NetNet*index_net = word_->synthesize(des);
connect(mux->pin_Address(), index_net->pin(0));
connect(tmp->pin(0), mux->pin_Result());
@@ -1213,68 +1061,22 @@ NetNet* NetESignal::synthesize(Design*des, NetScope*scope)
return tmp;
}
NetNet* NetESFunc::synthesize(Design*des, NetScope*scope)
NetNet* NetESFunc::synthesize(Design*des)
{
const struct sfunc_return_type*def = lookup_sys_func(name_);
/* We cannot use the default value for system functions in a
* continuous assignment since the function name is NULL. */
if (def == 0 || def->name == 0) {
cerr << get_fileline() << ": error: System function "
<< name_ << " not defined in system "
"table or SFT file(s)." << endl;
des->errors += 1;
return 0;
}
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Net system function "
<< name_ << " returns " << def->type << endl;
}
NetSysFunc*net = new NetSysFunc(scope, scope->local_symbol(),
def, 1+nparms_);
net->set_line(*this);
des->add_node(net);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, def->wid);
osig->local_flag(true);
osig->set_signed(def->type==IVL_VT_REAL? true : false);
osig->data_type(def->type);
osig->set_line(*this);
connect(net->pin(0), osig->pin(0));
unsigned errors = 0;
for (unsigned idx = 0 ; idx < nparms_ ; idx += 1) {
NetNet*tmp = parms_[idx]->synthesize(des, scope);
if (tmp == 0) {
cerr << get_fileline() << ": error: Unable to elaborate "
<< "argument " << idx << " of call to " << name_ <<
"." << endl;
errors += 1;
des->errors += 1;
continue;
}
connect(net->pin(1+idx), tmp->pin(0));
}
if (errors > 0) return 0;
return osig;
cerr << get_fileline() << ": sorry: cannot synthesize system function: "
<< *this << " in this context" << endl;
des->errors += 1;
return 0;
}
NetNet* NetEUFunc::synthesize(Design*des, NetScope*scope)
NetNet* NetEUFunc::synthesize(Design*des)
{
svector<NetNet*> eparms (parms_.count());
/* Synthesize the arguments. */
bool errors = false;
for (unsigned idx = 0; idx < eparms.count(); idx += 1) {
NetNet*tmp = parms_[idx]->synthesize(des, scope);
NetNet*tmp = parms_[idx]->synthesize(des);
if (tmp == 0) {
cerr << get_fileline() << ": error: Unable to synthesize "
"port " << idx << " of call to "
@@ -1301,7 +1103,7 @@ NetNet* NetEUFunc::synthesize(Design*des, NetScope*scope)
/* Connect the pins to the arguments. */
NetFuncDef*def = func_->func_def();
for (unsigned idx = 0; idx < eparms.count(); idx += 1) {
NetNet*tmp = pad_to_width(des, eparms[idx],
NetNet*tmp = pad_to_width(des, eparms[idx],
def->port(idx)->vector_width());
connect(net->pin(idx+1), tmp->pin(0));
}
+13 -5
View File
@@ -111,12 +111,20 @@ void NetScope::run_functor(Design*des, functor_t*fun)
// apply to signals. Each iteration, allow for the possibility
// that the current signal deletes itself.
if (signals_) {
unsigned count = 0;
NetNet*cur = signals_->sig_next_;
do {
count += 1;
cur = cur->sig_next_;
} while (cur != signals_->sig_next_);
signals_map_iter_t cur = signals_map_.begin();
while (cur != signals_map_.end()) {
signals_map_iter_t tmp = cur;
cur ++;
fun->signal(des, tmp->second);
cur = signals_->sig_next_;
for (unsigned idx = 0 ; idx < count ; idx += 1) {
NetNet*tmp = cur->sig_next_;
fun->signal(des, cur);
cur = tmp;
}
}
}
+3 -4
View File
@@ -17,18 +17,17 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: iverilog-vpi.sh,v 1.17 2007/02/06 05:07:31 steve Exp $"
# These are the variables used for compiling files
CC=@IVCC@
CXX=@IVCXX@
CFLAGS="@PIC@ @IVCFLAGS@ -I@INCLUDEDIR@"
SUFFIX=@SUFFIX@
# These are used for linking...
LD=$CC
LDFLAGS="@SHARED@ -L@LIBDIR@"
LDLIBS="-lveriuser$SUFFIX -lvpi$SUFFIX"
LDLIBS="-lveriuser -lvpi"
CCSRC=
CXSRC=
@@ -102,7 +101,7 @@ do
;;
--install-dir)
echo "@LIBDIR@/ivl$SUFFIX"
echo "@LIBDIR@/ivl"
exit
;;
esac
-7
View File
@@ -15,9 +15,6 @@ ivl_const_signed
ivl_const_type
ivl_const_width
ivl_discipline_domain
ivl_discipline_name
ivl_event_any
ivl_event_basename
ivl_event_name
@@ -146,7 +143,6 @@ ivl_scope_def_lineno
ivl_scope_event
ivl_scope_events
ivl_scope_file
ivl_scope_is_auto
ivl_scope_lineno
ivl_scope_logs
ivl_scope_log
@@ -175,7 +171,6 @@ ivl_signal_attr_val
ivl_signal_basename
ivl_signal_data_type
ivl_signal_dimensions
ivl_signal_discipline
ivl_signal_file
ivl_signal_integer
ivl_signal_lineno
@@ -196,8 +191,6 @@ ivl_path_source
ivl_process_attr_cnt
ivl_process_attr_val
ivl_process_file
ivl_process_lineno
ivl_process_scope
ivl_process_stmt
ivl_process_type
+5 -55
View File
@@ -151,7 +151,6 @@ _BEGIN_DECL
typedef struct ivl_array_s *ivl_array_t;
typedef struct ivl_delaypath_s*ivl_delaypath_t;
typedef struct ivl_design_s *ivl_design_t;
typedef struct ivl_discipline_s*ivl_discipline_t;
typedef struct ivl_event_s *ivl_event_t;
typedef struct ivl_expr_s *ivl_expr_t;
typedef struct ivl_island_s *ivl_island_t;
@@ -160,7 +159,6 @@ typedef struct ivl_lval_s *ivl_lval_t;
typedef struct ivl_net_const_s*ivl_net_const_t;
typedef struct ivl_net_logic_s*ivl_net_logic_t;
typedef struct ivl_udp_s *ivl_udp_t;
typedef struct ivl_nature_s *ivl_nature_t;
typedef struct ivl_net_probe_s*ivl_net_probe_t;
typedef struct ivl_nexus_s *ivl_nexus_t;
typedef struct ivl_nexus_ptr_s*ivl_nexus_ptr_t;
@@ -178,12 +176,6 @@ typedef struct ivl_statement_s*ivl_statement_t;
* changes and additions to the enumerations.
*/
typedef enum ivl_dis_domain_e {
IVL_DIS_NONE = 0,
IVL_DIS_DISCRETE = 1,
IVL_DIS_CONTINUOUS = 2
} ivl_dis_domain_t;
typedef enum ivl_drive_e {
IVL_DR_HiZ = 0,
IVL_DR_SMALL = 1,
@@ -201,7 +193,6 @@ typedef enum ivl_drive_e {
typedef enum ivl_expr_type_e {
IVL_EX_NONE = 0,
IVL_EX_ARRAY = 18,
IVL_EX_BACCESS= 19,
IVL_EX_BINARY = 2,
IVL_EX_CONCAT = 3,
IVL_EX_EVENT = 17,
@@ -263,8 +254,6 @@ typedef enum ivl_lpm_type_e {
IVL_LPM_ABS = 32,
IVL_LPM_ADD = 0,
IVL_LPM_ARRAY = 30,
IVL_LPM_CAST_INT = 34,
IVL_LPM_CAST_REAL = 33,
IVL_LPM_CONCAT = 16,
IVL_LPM_CMP_EEQ= 18, /* Case EQ (===) */
IVL_LPM_CMP_EQ = 10,
@@ -351,7 +340,6 @@ typedef enum ivl_signal_type_e {
typedef enum ivl_statement_type_e {
IVL_ST_NONE = 0,
IVL_ST_NOOP = 1,
IVL_ST_ALLOC = 25,
IVL_ST_ASSIGN = 2,
IVL_ST_ASSIGN_NB = 3,
IVL_ST_BLOCK = 4,
@@ -368,7 +356,6 @@ typedef enum ivl_statement_type_e {
IVL_ST_FORCE = 14,
IVL_ST_FOREVER = 15,
IVL_ST_FORK = 16,
IVL_ST_FREE = 26,
IVL_ST_RELEASE = 17,
IVL_ST_REPEAT = 18,
IVL_ST_STASK = 19,
@@ -512,8 +499,7 @@ extern ivl_net_const_t ivl_design_const(ivl_design_t, unsigned idx);
* ivl_const_bits
* This returns a pointer to an array of constant characters,
* each byte a '0', '1', 'x' or 'z'. The array is *not* nul
* terminated. This value is only value if ivl_const_type is
* IVL_VT_LOGIC or IVL_VT_BOOL. It returns nil otherwise.
* terminated.
*
* ivl_const_nex
* Return the ivl_nexus_t of the output for the constant.
@@ -551,28 +537,6 @@ extern double ivl_const_real(ivl_net_const_t net);
/* extern ivl_nexus_t ivl_const_pin(ivl_net_const_t net, unsigned idx); */
/* extern unsigned ivl_const_pins(ivl_net_const_t net); */
/* DISCIPLINES
*
* Disciplines are Verilog-AMS construct. A discipline is a collection
* of attributes that can be attached to a signal.
*
* FUNCTION SUMMARY
*
* ivl_discipline_name
* This is the name of the discipline in the Verilog-AMS source.
*
* ivl_discipline_domain
* This is the domain: continuous or discrete.
*
* SEMANTIC NOTES
*
* The discipline domain will not be IVL_DIS_NONE. The "none" domain
* is a place-holder internally for incomplete parsing, and is also
* available for code generaters to use.
*/
extern const char*ivl_discipline_name(ivl_discipline_t net);
extern ivl_dis_domain_t ivl_discipline_domain(ivl_discipline_t net);
/* EVENTS
*
* Events are a unification of named events and implicit events
@@ -1022,9 +986,8 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
* more than the width of the output, although the possibility of
* overflow exists at run time.
*
* The inputs are always treated as unsigned. If the expression is
* supposed to be signed, elaboration will generate the necessary sign
* extension, so the target need not (must not) consider signedness.
* Multiply may be signed. If so, the output should be sign extended
* to fill in its result.
*
* - Power (IVL_LPM_POW)
* The power takes two inputs and generates an output. Unlike other
@@ -1288,7 +1251,7 @@ extern const char*ivl_lpm_string(ivl_lpm_t net);
*/
extern unsigned ivl_lval_width(ivl_lval_t net);
extern ivl_expr_t ivl_lval_mux(ivl_lval_t net); /* XXXX Obsolete? */
extern ivl_expr_t ivl_lval_mux(ivl_lval_t net); // XXXX Obsolete?
extern ivl_expr_t ivl_lval_idx(ivl_lval_t net);
extern ivl_expr_t ivl_lval_part_off(ivl_lval_t net);
extern ivl_signal_t ivl_lval_sig(ivl_lval_t net);
@@ -1482,9 +1445,6 @@ extern unsigned ivl_parameter_lineno(ivl_parameter_t net);
* ivl_scope_lineno
* Returns the instantiation file and line for this scope.
*
* ivl_scope_is_auto
* Is the task or function declared to be automatic?
*
* ivl_scope_var
* ivl_scope_vars
* REMOVED
@@ -1561,7 +1521,6 @@ extern unsigned ivl_scope_def_lineno(ivl_scope_t net);
extern unsigned ivl_scope_events(ivl_scope_t net);
extern ivl_event_t ivl_scope_event(ivl_scope_t net, unsigned idx);
extern const char* ivl_scope_file(ivl_scope_t net);
extern unsigned ivl_scope_is_auto(ivl_scope_t net);
extern unsigned ivl_scope_lineno(ivl_scope_t net);
extern unsigned ivl_scope_logs(ivl_scope_t net);
extern ivl_net_logic_t ivl_scope_log(ivl_scope_t net, unsigned idx);
@@ -1614,10 +1573,6 @@ extern int ivl_scope_time_units(ivl_scope_t net);
* The signal may be an array (of vectors) in which case this
* function returns >0, the number of dimensions of the array.
*
* ivl_signal_discipline
* If the signal has been declared with a domain (Verilog-AMS) then
* this function wil return a non-nil ivl_discipline_t.
*
* ivl_signal_msb
* ivl_signal_lsb
* ivl_signal_width
@@ -1685,7 +1640,6 @@ extern ivl_nexus_t ivl_signal_nex(ivl_signal_t net, unsigned word);
extern int ivl_signal_array_base(ivl_signal_t net);
extern unsigned ivl_signal_array_count(ivl_signal_t net);
extern unsigned ivl_signal_dimensions(ivl_signal_t net);
extern ivl_discipline_t ivl_signal_discipline(ivl_signal_t net);
extern int ivl_signal_msb(ivl_signal_t net);
extern int ivl_signal_lsb(ivl_signal_t net);
extern unsigned ivl_signal_width(ivl_signal_t net);
@@ -1739,9 +1693,6 @@ extern ivl_statement_t ivl_process_stmt(ivl_process_t net);
extern unsigned ivl_process_attr_cnt(ivl_process_t net);
extern ivl_attribute_t ivl_process_attr_val(ivl_process_t net, unsigned idx);
extern const char* ivl_process_file(ivl_process_t net);
extern unsigned ivl_process_lineno(ivl_process_t net);
/*
* These functions manage statements of various type. This includes
* all the different kinds of statements (as enumerated in
@@ -1966,7 +1917,7 @@ extern unsigned ivl_switch_lineno(ivl_switch_t net);
#endif
extern DLLEXPORT int target_design(ivl_design_t des);
extern DLLEXPORT const char* target_query(const char*key);
/* target_design
@@ -1984,7 +1935,6 @@ extern DLLEXPORT const char* target_query(const char*key);
ivl core. This function is how the target module is invoked. */
typedef int (*target_design_f)(ivl_design_t des);
typedef const char* (*target_query_f) (const char*key);
_END_DECL
+6 -8
View File
@@ -25,8 +25,6 @@ SHELL = /bin/sh
VERSION = 0.0
suffix = @install_suffix@
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
@@ -42,7 +40,7 @@ INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir)/.. -I$(srcdir) -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@
CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir)/.. -I$(srcdir) @CPPFLAGS@ @DEFS@
CFLAGS = -Wall @CFLAGS@
LDFLAGS = @LDFLAGS@
@@ -62,16 +60,16 @@ ivlpp@EXEEXT@: $O
lexor.c: lexor.lex
flex -olexor.c $(srcdir)/lexor.lex
install: all installdirs $(libdir)/ivl$(suffix)/ivlpp@EXEEXT@
install: all installdirs $(libdir)/ivl/ivlpp@EXEEXT@
$(libdir)/ivl$(suffix)/ivlpp@EXEEXT@: ivlpp@EXEEXT@
$(INSTALL_PROGRAM) ./ivlpp@EXEEXT@ $(DESTDIR)$(libdir)/ivl$(suffix)/ivlpp@EXEEXT@
$(libdir)/ivl/ivlpp@EXEEXT@: ivlpp@EXEEXT@
$(INSTALL_PROGRAM) ./ivlpp@EXEEXT@ $(libdir)/ivl/ivlpp@EXEEXT@
installdirs: ../mkinstalldirs
$(srcdir)/../mkinstalldirs $(DESTDIR)$(libdir)/ivl$(suffix)
$(srcdir)/../mkinstalldirs $(libdir)/ivl
uninstall:
rm -f $(DESTDIR)$(libdir)/ivl$(suffix)/ivlpp@EXEEXT@
rm -f $(libdir)/ivl/ivlpp@EXEEXT@
lexor.o: lexor.c globals.h
main.o: main.c globals.h
+1 -3
View File
@@ -1,7 +1,7 @@
#ifndef __globals_H
#define __globals_H
/*
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2007 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,11 +22,9 @@
# include <stdio.h>
extern void reset_lexor(FILE*out, char*paths[]);
extern void destroy_lexor();
extern void load_precompiled_defines(FILE*src);
extern void define_macro(const char*name, const char*value, int keyword,
int argc);
extern void free_macros();
extern void dump_precompiled_defines(FILE*out);
/* These variables contain the include directories to be searched when
+12 -74
View File
@@ -78,9 +78,6 @@ struct include_stack_t
YY_BUFFER_STATE yybs;
struct include_stack_t* next;
/* A single line comment can be associated with this include. */
char* comment;
};
static void emit_pathline(struct include_stack_t* isp);
@@ -118,7 +115,7 @@ static void ifdef_enter(void)
struct ifdef_stack_t*cur;
cur = (struct ifdef_stack_t*) calloc(1, sizeof(struct ifdef_stack_t));
if (istack->path) cur->path = strdup(istack->path);
cur->path = strdup(istack->path);
cur->lineno = istack->lineno;
cur->next = ifdef_stack;
@@ -134,10 +131,8 @@ static void ifdef_leave(void)
cur = ifdef_stack;
ifdef_stack = cur->next;
/* If either path is from a non-file context e.g.(macro expansion)
* we assume that the non-file part is from this file. */
if (istack->path != NULL && cur->path != NULL &&
strcmp(istack->path,cur->path) != 0) {
if (strcmp(istack->path,cur->path) != 0)
{
fprintf
(
stderr,
@@ -298,10 +293,9 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
/* Catch single-line comments that share the line with an include
* directive. And while I'm at it, I might as well preserve the
* comment in the output stream. This will be printed after the
* file has been included.
* comment in the output stream.
*/
<PPINCLUDE>"//"[^\r\n]* { standby->comment = strdup(yytext); }
<PPINCLUDE>"//"[^\r\n]* { ECHO; }
/* These finish the include directive (EOF or EOL) so I revert the
* lexor state and execute the inclusion.
@@ -702,7 +696,7 @@ static int is_defined(const char*name)
* These variables are also used for storing the actual arguments when
* a macro is instantiated.
*/
#define MAX_DEF_ARG 256 /* allows argument IDs to be stored in a single char */
#define MAX_DEF_ARG 256 // allows argument IDs to be stored in a single char
#define DEF_BUF_CHUNK 256
@@ -711,14 +705,14 @@ static int def_buf_size = 0;
static int def_buf_free = 0;
static int def_argc = 0;
static int def_argo[MAX_DEF_ARG]; /* offset of first character in arg */
static int def_argl[MAX_DEF_ARG]; /* length of arg string. */
static int def_argo[MAX_DEF_ARG]; // offset of first character in arg
static int def_argl[MAX_DEF_ARG]; // length of arg string.
/*
* Return a pointer to the start of argument 'arg'. Returned pointers
* may go stale after a call to def_buf_grow_to_fit.
*/
static /* inline */ char* def_argv(int arg)
static inline char* def_argv(int arg)
{
return def_buf + def_argo[arg];
}
@@ -833,21 +827,6 @@ void define_macro(const char* name, const char* value, int keyword, int argc)
}
}
static void free_macro(struct define_t* def)
{
if (def == 0) return;
free_macro(def->left);
free_macro(def->right);
free(def->name);
free(def->value);
free(def);
}
void free_macros()
{
free_macro(def_table);
}
/*
* The do_define function accumulates the defined value in these
* variables. When the define is over, the def_finish() function
@@ -877,7 +856,6 @@ static int define_continue_flag = 0;
static char *find_arg(char*ptr, char*head, char*arg)
{
char *cp = ptr;
size_t len = strlen(arg);
while (1) {
/* Look for a candidate match, just return if none is found. */
@@ -888,8 +866,7 @@ static char *find_arg(char*ptr, char*head, char*arg)
* match is not in the middle of another identifier.
*/
if (cp != head &&
(isalnum(*(cp-1)) || *(cp-1) == '_' || *(cp-1) == '$' ||
isalnum(*(cp+len)) || *(cp+len) == '_' || *(cp+len) == '$')) {
(isalnum(*(cp-1)) || *(cp-1) == '_' || *(cp-1) == '$')) {
cp++;
continue;
}
@@ -964,7 +941,7 @@ static void do_define()
}
/* Detect the continuation sequence. If I find it, remove it
* and the white space that precedes it, then replace all that
* and the white space that preceeds it, then replace all that
* with a single newline.
*/
if ((cp > yytext) && (cp[-1] == '\\'))
@@ -1437,7 +1414,6 @@ static void include_filename()
standby->path = strdup(yytext+1);
standby->path[strlen(standby->path)-1] = 0;
standby->lineno = 0;
standby->comment = NULL;
}
static void do_include()
@@ -1477,8 +1453,6 @@ static void do_include()
if ((standby->file = fopen(path, "r")))
{
/* Free the original path before we overwrite it. */
free(standby->path);
standby->path = strdup(path);
goto code_that_switches_buffers;
}
@@ -1490,14 +1464,11 @@ static void do_include()
code_that_switches_buffers:
/* Clear the current files path from the search list. */
include_dir[0] = 0;
if(depend_file)
fprintf(depend_file, "%s\n", standby->path);
if (line_direct_flag)
fprintf(yyout, "\n`line 1 \"%s\" 1\n", standby->path);
fprintf(yyout, "\n`line %u \"%s\" 1\n", istack->lineno+1, standby->path);
standby->next = istack;
standby->stringify_flag = 0;
@@ -1555,17 +1526,6 @@ static int load_next_input()
/* Delete the current input buffers, and free the cell. */
yy_delete_buffer(YY_CURRENT_BUFFER);
/* If there was a comment for this include print it before we
* return to the previous input stream. This technically belongs
* to the previous stream, but it should not create any problems
* since it is only a comment.
*/
if (isp->comment) {
fprintf(yyout, "%s\n", isp->comment);
free(isp->comment);
isp->comment = NULL;
}
if (isp->file)
{
free(isp->path);
@@ -1624,12 +1584,6 @@ static int load_next_input()
if(depend_file)
fprintf(depend_file, "%s\n", istack->path);
/* This works around an issue in flex yyrestart() where it
* uses yyin to create a new buffer when one does not exist.
* I would have assumed that it would use the file argument.
* The problem is that we have deleted the buffer and freed
* yyin (isp->file) above. */
yyin = 0;
yyrestart(istack->file);
return 1;
}
@@ -1762,7 +1716,6 @@ void reset_lexor(FILE* out, char* paths[])
isp->ebs = 0;
isp->lineno = 0;
isp->stringify_flag = 0;
isp->comment = NULL;
if (isp->file == 0)
{
@@ -1793,7 +1746,6 @@ void reset_lexor(FILE* out, char* paths[])
isp->next = 0;
isp->lineno = 0;
isp->stringify_flag = 0;
isp->comment = NULL;
if (tail)
tail->next = isp;
@@ -1803,17 +1755,3 @@ void reset_lexor(FILE* out, char* paths[])
tail = isp;
}
}
/*
* Modern version of flex (>=2.5.9) can clean up the scanner data.
*/
void destroy_lexor()
{
# ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy();
# endif
# endif
# endif
}
+9 -33
View File
@@ -17,8 +17,7 @@ const char COPYRIGHT[] =
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "config.h"
# include "version.h"
# include "config.h"
const char NOTICE[] =
" This program is free software; you can redistribute it and/or modify\n"
@@ -36,6 +35,8 @@ const char NOTICE[] =
" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\n"
;
const char VERSION[] = "$Name: $ $State: Exp $";
# include <stdio.h>
# include <stdlib.h>
#ifdef HAVE_MALLOC_H
@@ -102,8 +103,6 @@ static int flist_read_flags(const char*path)
char*cp = line_buf + strspn(line_buf, " \t\r\b\f");
/* Remove trailing white space. */
char*tail = cp + strlen(cp);
char*arg;
while (tail > cp) {
if (! isspace(tail[-1]))
break;
@@ -119,7 +118,7 @@ static int flist_read_flags(const char*path)
continue;
/* The arg points to the argument to the keyword. */
arg = strchr(cp, ':');
char*arg = strchr(cp, ':');
if (arg) *arg++ = 0;
if (strcmp(cp,"D") == 0) {
@@ -189,14 +188,12 @@ static int flist_read_names(const char*path)
add_source_file(cp);
}
fclose(fd);
return 0;
}
int main(int argc, char*argv[])
{
int opt, idx;
unsigned lp;
const char*flist_path = 0;
unsigned flag_errors = 0;
char*out_path = 0;
@@ -232,7 +229,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:vV")) != EOF) switch (opt) {
while ((opt=getopt(argc, argv, "F:f:K:Lo:p:P:v")) != EOF) switch (opt) {
case 'F':
flist_read_flags(optarg);
@@ -285,21 +282,14 @@ int main(int argc, char*argv[])
fclose(src);
break;
}
case 'v':
fprintf(stderr, "Icarus Verilog Preprocessor version "
VERSION " (" VERSION_TAG ")\n\n");
fprintf(stderr, "Icarus Verilog Preprocessor version %s\n",
VERSION);
fprintf(stderr, "%s\n", COPYRIGHT);
fputs(NOTICE, stderr);
break;
case 'V':
fprintf(stdout, "Icarus Verilog Preprocessor version "
VERSION " (" VERSION_TAG ")\n\n");
fprintf(stdout, "%s\n", COPYRIGHT);
fputs(NOTICE, stdout);
return 0;
default:
flag_errors += 1;
break;
@@ -314,8 +304,7 @@ int main(int argc, char*argv[])
" -o<fil> - Send the output to <fil>\n"
" -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",
" -v - Print version information\n",
argv[0]);
return flag_errors;
}
@@ -370,7 +359,6 @@ int main(int argc, char*argv[])
start scanning. */
reset_lexor(out, source_list);
if (yylex()) return -1;
destroy_lexor();
if(depend_file) {
fclose(depend_file);
@@ -381,17 +369,5 @@ int main(int argc, char*argv[])
fclose(precomp_out);
}
/* Free the source and include directory lists. */
for (lp = 0; lp < source_cnt; lp += 1) {
free(source_list[lp]);
}
free(source_list);
for (lp = 0; lp < include_cnt; lp += 1) {
free(include_dir[lp]);
}
free(include_dir);
free_macros();
return error_count;
}
+11 -27
View File
@@ -87,7 +87,6 @@ static void process_timescale(const char*txt);
static list<int> keyword_mask_stack;
static int comment_enter;
static bool in_module = false;
%}
%x CCOMMENT
@@ -124,8 +123,8 @@ S [afpnumkKMGT]
/* The contents of C-style comments are ignored, like white space. */
"/*" { comment_enter = YY_START; BEGIN(CCOMMENT); }
<CCOMMENT>. { ; }
<CCOMMENT>\n { yylloc.first_line += 1; }
<CCOMMENT>. { yymore(); }
<CCOMMENT>\n { yylloc.first_line += 1; yymore(); }
<CCOMMENT>"*/" { BEGIN(comment_enter); }
@@ -228,15 +227,6 @@ S [afpnumkKMGT]
BEGIN(EDGES);
break;
case K_module:
case K_macromodule:
in_module = true;
break;
case K_endmodule:
in_module = false;
break;
default:
yylval.text = 0;
break;
@@ -247,7 +237,7 @@ S [afpnumkKMGT]
value instead. */
if (rc == IDENTIFIER && gn_verilog_ams_flag) {
perm_string tmp = lex_strings.make(yylval.text);
map<perm_string,ivl_discipline_t>::iterator cur = disciplines.find(tmp);
map<perm_string,discipline_t*>::iterator cur = disciplines.find(tmp);
if (cur != disciplines.end()) {
yylval.discipline = (*cur).second;
rc = DISCIPLINE_IDENTIFIER;
@@ -353,12 +343,6 @@ S [afpnumkKMGT]
^{W}?`timescale { BEGIN(PPTIMESCALE); }
<PPTIMESCALE>.* { process_timescale(yytext); }
<PPTIMESCALE>\n {
if (in_module) {
cerr << yylloc.text << ":" << yylloc.first_line << ": error: "
"`timescale directive can not be inside a module "
"definition." << endl;
error_count += 1;
}
yylloc.first_line += 1;
BEGIN(0); }
@@ -455,7 +439,7 @@ S [afpnumkKMGT]
} else {
cerr << yylloc.text << ":" << yylloc.first_line
<< ": error: Net type " << yytext
<< " error: Net type " << yytext
<< " is not a valid (and supported)"
<< " default net type." << endl;
net_type = NetNet::WIRE;
@@ -473,37 +457,37 @@ S [afpnumkKMGT]
^{W}?`define{W}?.* {
cerr << yylloc.text << ":" << yylloc.first_line <<
": warning: `define not supported. Use an external preprocessor."
": `define not supported. Use an external preprocessor."
<< endl;
}
^{W}?`else{W}?.* {
cerr << yylloc.text << ":" << yylloc.first_line <<
": warning: `else not supported. Use an external preprocessor."
": `else not supported. Use an external preprocessor."
<< endl;
}
^{W}?`endif{W}?.* {
cerr << yylloc.text << ":" << yylloc.first_line <<
": warning: `endif not supported. Use an external preprocessor."
": `endif not supported. Use an external preprocessor."
<< endl;
}
^{W}?`ifdef{W}?.* {
cerr << yylloc.text << ":" << yylloc.first_line <<
": warning: `ifdef not supported. Use an external preprocessor."
": `ifdef not supported. Use an external preprocessor."
<< endl;
}
^`include{W}?.* {
cerr << yylloc.text << ":" << yylloc.first_line <<
": warning: `include not supported. Use an external preprocessor."
": `include not supported. Use an external preprocessor."
<< endl;
}
^`undef{W}?.* {
cerr << yylloc.text << ":" << yylloc.first_line <<
": warning: `undef not supported. Use an external preprocessor."
": `undef not supported. Use an external preprocessor."
<< endl;
}
@@ -859,7 +843,7 @@ static verinum*make_unsized_dec(const char*ptr)
if (ptr[0] == '\'') {
/* The number has decorations of the form 'sd<digits>,
possibly with space between the d and the <digits>.
Also, the 's' is optional, and marks the number as
Also, the 's' is optional, and markes the number as
signed. */
ptr += 1;
-1
View File
@@ -25,7 +25,6 @@ assign, GN_KEYWORDS_1364_1995, K_assign
atan, GN_KEYWORDS_VAMS_2_3, K_atan
atan2, GN_KEYWORDS_VAMS_2_3, K_atan2
atanh, GN_KEYWORDS_VAMS_2_3, K_atanh
automatic, GN_KEYWORDS_1364_2001, K_automatic
begin, GN_KEYWORDS_1364_1995, K_begin
bool, GN_KEYWORDS_ICARUS, K_bool
buf, GN_KEYWORDS_1364_1995, K_buf
+5 -6
View File
@@ -21,7 +21,6 @@
#
SHELL = /bin/sh
suffix = @install_suffix@
prefix = @prefix@
exec_prefix = @exec_prefix@
@@ -87,15 +86,15 @@ clean:
distclean: clean
rm -f Makefile config.status config.log config.cache config.h
install:: all installdirs $(libdir)/libveriuser$(suffix).a $(INSTALL32)
install:: all installdirs $(libdir)/libveriuser.a $(INSTALL32)
$(libdir)/libveriuser$(suffix).a: ./libveriuser.a
$(INSTALL_DATA) ./libveriuser.a $(DESTDIR)$(libdir)/libveriuser$(suffix).a
$(libdir)/libveriuser.a: ./libveriuser.a
$(INSTALL_DATA) ./libveriuser.a $(libdir)/libveriuser.a
installdirs: mkinstalldirs
$(srcdir)/mkinstalldirs $(DESTDIR)$(includedir) $(DESTDIR)$(libdir)
$(srcdir)/mkinstalldirs $(includedir) $(libdir)
uninstall::
rm -f $(DESTDIR)$(libdir)/libveriuser$(suffix).a
rm -f $(libdir)/libveriuser.a
-include $(patsubst %.o, dep/%.d, $O)
+1 -1
View File
@@ -99,7 +99,7 @@ PLI_INT32 acc_fetch_fulltype(handle obj)
return accTopModule;
else
return accModuleInstance;
/* FIXME accCellInstance */
// FIXME accCellInstance
case vpiNamedEvent: return accNamedEvent;
+1 -1
View File
@@ -55,7 +55,7 @@ handle acc_next(PLI_INT32 *type, handle scope, handle prev)
* rescan all the items up to the previous one, then return
* the next one.
*/
iter = vpi_iterate(vpiScope, scope); /* ICARUS extension */
iter = vpi_iterate(vpiScope, scope); // ICARUS extension
if (prev) {
while ((hand = vpi_scan(iter))) {
if (hand == prev) break;
+1 -1
View File
@@ -35,7 +35,7 @@ int acc_object_of_type(handle object, PLI_INT32 type)
if (pli_trace) {
fprintf(pli_trace, "acc_object_of_type(%p \"%s\", %d)",
object, vpi_get_str(vpiName, object), type);
object, vpi_get_str(vpiName, object), type);
fflush(pli_trace);
}
-2
View File
@@ -10,8 +10,6 @@ AC_PROG_RANLIB
AC_EXEEXT
AX_CPP_IDENT
AX_ENABLE_SUFFIX
AC_CHECK_HEADERS(malloc.h)
AC_CHECK_SIZEOF(unsigned long long)
+1 -1
View File
@@ -366,7 +366,7 @@ PLI_INT32 tf_isetrealdelay(double dly, void*obj)
s_cb_data cb;
s_vpi_time ti = {vpiSimTime};
/* Scale delay to SimTime */
// Scale delay to SimTime
ivl_u64_t delay = ((dly
* pow(10, tf_gettimeprecision() - tf_gettimeunit()))
+ 0.5);
+4 -5
View File
@@ -60,9 +60,8 @@ bool Nexus::drivers_constant() const
if (cur_dir == Link::PASSIVE) {
const NetPins*obj = cur->get_obj();
const NetObj*as_obj = dynamic_cast<const NetObj*>(obj);
if (as_obj == 0 || as_obj->scope()->parent() != 0)
const NetObj*obj = cur->get_obj();
if (obj->scope()->parent() != 0)
continue;
sig = dynamic_cast<const NetNet*>(cur->get_obj());
@@ -81,8 +80,8 @@ bool Nexus::drivers_constant() const
/* If there is a supply net, then this nexus will have a
constant value independent of any drivers. */
if (const NetNet*s = dynamic_cast<const NetNet*>(cur->get_obj()))
switch (s->type()) {
if (const NetNet*sig = dynamic_cast<const NetNet*>(cur->get_obj()))
switch (sig->type()) {
case NetNet::SUPPLY0:
driven_ = V0;
return true;
+43 -83
View File
@@ -20,7 +20,6 @@ const char COPYRIGHT[] =
*/
# include "config.h"
# include "version.h"
const char NOTICE[] =
" This program is free software; you can redistribute it and/or modify\n"
@@ -55,12 +54,10 @@ const char NOTICE[] =
#endif
# include "pform.h"
# include "parse_api.h"
# include "PGenerate.h"
# include "netlist.h"
# include "target.h"
# include "compiler.h"
# include "discipline.h"
# include "t-dll.h"
#if defined(__MINGW32__) && !defined(HAVE_GETOPT_H)
extern "C" int getopt(int argc, char*argv[], const char*fmt);
@@ -77,8 +74,12 @@ extern "C" const char*optarg;
/* Count errors detected in flag processing. */
unsigned flag_errors = 0;
const char VERSION[] = "$Name: $";
const char*basedir = ".";
const char*target = "null";
/*
* These are the language support control flags. These support which
* language features (the generation) to support. The generation_flag
@@ -124,7 +125,6 @@ bool debug_eval_tree = false;
bool debug_elaborate = false;
bool debug_synth2 = false;
bool debug_optimizer = false;
bool debug_automatic = false;
/*
* Verbose messages enabled.
@@ -160,6 +160,9 @@ extern void synth(Design*des);
extern void synth2(Design*des);
extern void syn_rules(Design*des);
extern void nodangle(Design*des);
#ifdef WITH_T_XNF
extern void xnfio(Design*des);
#endif
typedef void (*net_func)(Design*);
static struct net_func_map {
@@ -171,6 +174,9 @@ static struct net_func_map {
{ "synth", &synth },
{ "synth2", &synth2 },
{ "syn-rules", &syn_rules },
#ifdef WITH_T_XNF
{ "xnfio", &xnfio },
#endif
{ 0, 0 }
};
@@ -229,16 +235,16 @@ static void process_generation_flag(const char*gen)
} else if (strcmp(gen,"specify") == 0) {
gn_specify_blocks_flag = true;
} else if (strcmp(gen,"no-specify") == 0) {
gn_specify_blocks_flag = false;
} else if (strcmp(gen,"verilog-ams") == 0) {
gn_verilog_ams_flag = true;
} else if (strcmp(gen,"no-verilog-ams") == 0) {
gn_verilog_ams_flag = false;
} else if (strcmp(gen,"io-range-error") == 0) {
gn_io_range_error_flag = true;
@@ -266,9 +272,6 @@ static void parm_to_flagmap(const string&flag)
flags[key] = value;
}
static void find_module_mention(map<perm_string,bool>&check_map, Module*m);
static void find_module_mention(map<perm_string,bool>&check_map, PGenerate*s);
/*
* Read the contents of a config file. This file is a temporary
* configuration file made by the compiler driver to carry the bulky
@@ -292,7 +295,7 @@ static void find_module_mention(map<perm_string,bool>&check_map, PGenerate*s);
* -T:<min/typ/max>
* Select which expression to use.
*
* -t:<target> (obsolete)
* -t:<target>
* Usually, "-t:dll"
*
* basedir:<path>
@@ -393,8 +396,6 @@ static void read_iconfig_file(const char*ipath)
} else if (strcmp(cp,"optimizer") == 0) {
debug_optimizer = true;
cerr << "debug: Enable optimizer debug" << endl;
} else if (strcmp(cp,"automatic") == 0) {
debug_automatic = true;
} else {
}
@@ -484,7 +485,7 @@ static void read_iconfig_file(const char*ipath)
library_suff.push_back(strdup(cp));
} else if (strcmp(buf,"-t") == 0) {
// NO LONGER USED
target = strdup(cp);
} else if (strcmp(buf,"-T") == 0) {
if (strcmp(cp,"min") == 0) {
@@ -534,7 +535,6 @@ int main(int argc, char*argv[])
{
bool help_flag = false;
bool times_flag = false;
bool version_flag = false;
const char* net_path = 0;
const char* pf_path = 0;
@@ -578,8 +578,10 @@ int main(int argc, char*argv[])
# endif
break;
case 'V':
version_flag = true;
break;
cout << "Icarus Verilog version " << VERSION << endl;
cout << COPYRIGHT << endl;
cout << endl << NOTICE << endl;
return 0;
default:
flag_errors += 1;
break;
@@ -588,20 +590,8 @@ int main(int argc, char*argv[])
if (flag_errors)
return flag_errors;
if (version_flag) {
cout << "\n\nIcarus Verilog Parser/Elaborator version "
<< VERSION << " (" << VERSION_TAG << ")" << endl;
cout << COPYRIGHT << endl;
cout << endl << NOTICE << endl;
dll_target_obj.test_version(flags["DLL"]);
return 0;
}
if (help_flag) {
cout << "Icarus Verilog Parser/Elaborator version "
<< VERSION << " (" << VERSION_TAG << ")" << endl <<
cout << "Icarus Verilog version " << VERSION << endl <<
"usage: ivl <options> <file>\n"
"options:\n"
"\t-C <name> Config file from driver.\n"
@@ -705,7 +695,7 @@ int main(int argc, char*argv[])
pform_dump(out, (*cur).second);
}
out << "PFORM DUMP DISCIPLINES:" << endl;
for (map<perm_string,ivl_discipline_t>::iterator cur = disciplines.begin()
for (map<perm_string,discipline_t*>::iterator cur = disciplines.begin()
; cur != disciplines.end() ; cur ++ ) {
pform_dump(out, (*cur).second);
}
@@ -739,7 +729,15 @@ int main(int argc, char*argv[])
for (mod = pform_modules.begin()
; mod != pform_modules.end()
; mod++) {
find_module_mention(mentioned_p, mod->second);
list<PGate*> gates = (*mod).second->get_gates();
list<PGate*>::const_iterator gate;
for (gate = gates.begin(); gate != gates.end(); gate++) {
PGModule *mod = dynamic_cast<PGModule*>(*gate);
if (mod) {
// Note that this module has been instantiated
mentioned_p[mod->get_type()] = true;
}
}
}
for (mod = pform_modules.begin()
@@ -856,21 +854,20 @@ int main(int argc, char*argv[])
}
if (verbose_flag) {
cout << "CODE GENERATION" << endl;
cout << "CODE GENERATION -t "<<target<< endl;
}
if (int emit_rc = des->emit(&dll_target_obj)) {
if (emit_rc > 0) {
cerr << "error: Code generation had "
<< emit_rc << " errors."
<< endl;
return 1;
}
if (emit_rc < 0) {
cerr << "error: Code generator failure: " << emit_rc << endl;
return -1;
}
assert(emit_rc);
int emit_rc;
emit_rc = emit(des, target);
if (emit_rc > 0) {
cerr << "error: Code generation had "
<< emit_rc << " errors."
<< endl;
return 1;
}
if (emit_rc < 0) {
cerr << "error: Code generator failure: " << emit_rc << endl;
return -1;
}
if (verbose_flag) {
@@ -910,40 +907,3 @@ int main(int argc, char*argv[])
return des? des->errors : 1;
}
static void find_module_mention(map<perm_string,bool>&check_map, Module*mod)
{
list<PGate*> gates = mod->get_gates();
list<PGate*>::const_iterator gate;
for (gate = gates.begin(); gate != gates.end(); gate++) {
PGModule*tmp = dynamic_cast<PGModule*>(*gate);
if (tmp) {
// Note that this module has been instantiated
check_map[tmp->get_type()] = true;
}
}
list<PGenerate*>::const_iterator cur;
for (cur = mod->generate_schemes.begin()
; cur != mod->generate_schemes.end() ; cur ++) {
find_module_mention(check_map, *cur);
}
}
static void find_module_mention(map<perm_string,bool>&check_map, PGenerate*schm)
{
list<PGate*>::const_iterator gate;
for (gate = schm->gates.begin(); gate != schm->gates.end(); gate++) {
PGModule*tmp = dynamic_cast<PGModule*>(*gate);
if (tmp) {
// Note that this module has been instantiated
check_map[tmp->get_type()] = true;
}
}
list<PGenerate*>::const_iterator cur;
for (cur = schm->generate_schemes.begin()
; cur != schm->generate_schemes.end() ; cur ++) {
find_module_mention(check_map, *cur);
}
}
-37
View File
@@ -1,37 +0,0 @@
/*
* Copyright (c) 2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "config.h"
# include <typeinfo>
# include <cstdlib>
# include <climits>
# include "compiler.h"
# include "netlist.h"
# include "netmisc.h"
# include "ivl_assert.h"
NetContribution::NetContribution(NetExpr*l, NetExpr*r)
: lval_(l), rval_(r)
{
}
NetContribution::~NetContribution()
{
}
+36 -26
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000 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
@@ -16,6 +16,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_assign.cc,v 1.22 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -81,11 +84,6 @@ unsigned NetAssign_::lwidth() const
return lwid_;
}
ivl_variable_type_t NetAssign_::expr_type() const
{
return sig_->data_type();
}
perm_string NetAssign_::name() const
{
if (sig_) {
@@ -214,34 +212,15 @@ NetAssign::~NetAssign()
{
}
NetAssignNB::NetAssignNB(NetAssign_*lv, NetExpr*rv, NetEvWait*ev, NetExpr*cnt)
NetAssignNB::NetAssignNB(NetAssign_*lv, NetExpr*rv)
: NetAssignBase(lv, rv)
{
event_ = ev;
count_ = cnt;
}
NetAssignNB::~NetAssignNB()
{
}
unsigned NetAssignNB::nevents() const
{
if (event_) return event_->nevents();
return 0;
}
const NetEvent*NetAssignNB::event(unsigned idx) const
{
if (event_) return event_->event(idx);
return 0;
}
const NetExpr*NetAssignNB::get_count() const
{
return count_;
}
NetCAssign::NetCAssign(NetAssign_*lv, NetExpr*rv)
: NetAssignBase(lv, rv)
{
@@ -277,3 +256,34 @@ NetRelease::NetRelease(NetAssign_*l)
NetRelease::~NetRelease()
{
}
/*
* $Log: net_assign.cc,v $
* Revision 1.22 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.21 2006/02/02 02:43:58 steve
* Allow part selects of memory words in l-values.
*
* Revision 1.20 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.19 2004/12/11 02:31:26 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.18 2004/08/28 15:08:31 steve
* Do not change reg to wire in NetAssign_ unless synthesizing.
*
* Revision 1.17 2004/02/18 17:11:56 steve
* Use perm_strings for named langiage items.
*
* Revision 1.16 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*/
+14 -128
View File
@@ -20,7 +20,6 @@
# include "config.h"
# include <iostream>
# include <set>
# include <cstdlib>
/*
@@ -36,7 +35,7 @@
# include "ivl_assert.h"
Design:: Design()
: errors(0), nodes_(0), procs_(0), aprocs_(0), lcounter_(0)
: errors(0), nodes_(0), procs_(0), lcounter_(0)
{
procs_idx_ = 0;
des_precision_ = 0;
@@ -209,12 +208,10 @@ void NetScope::run_defparams(Design*des)
}
}
while (! defparams.empty()) {
pair<pform_name_t,NetExpr*> pp = defparams.front();
defparams.pop_front();
pform_name_t path = pp.first;
NetExpr*val = pp.second;
map<pform_name_t,NetExpr*>::const_iterator pp;
for (pp = defparams.begin() ; pp != defparams.end() ; pp ++ ) {
NetExpr*val = (*pp).second;
pform_name_t path = (*pp).first;
perm_string perm_name = peek_tail_name(path);
path.pop_back();
@@ -225,20 +222,11 @@ void NetScope::run_defparams(Design*des)
is the current scope. */
NetScope*targ_scope = des->find_scope(this, eval_path);
if (targ_scope == 0) {
// Push the defparam onto a list for retry
// later. It is possible for the scope lookup to
// fail if the scope being defparam'd into is
// generated by an index array for generate.
eval_path.push_back(hname_t(perm_name));
defparams_later.push_back(make_pair(eval_path,val));
cerr << val->get_fileline() << ": warning: scope of " <<
path << "." << perm_name << " not found." << endl;
continue;
}
// Once placed in the parameter map, the expression may
// be deleted when evaluated, so give it a copy of this
// expression, not the original.
val = val->dup_expr();
bool flag = targ_scope->replace_parameter(perm_name, val);
if (! flag) {
cerr << val->get_fileline() << ": warning: parameter "
@@ -247,66 +235,6 @@ void NetScope::run_defparams(Design*des)
}
}
// If some of the defparams didn't find a scope in the name,
// then try again later. It may be that the target scope is
// created later by generate scheme or instance array.
if (! defparams_later.empty())
des->defparams_later.insert(this);
}
void NetScope::run_defparams_later(Design*des)
{
set<NetScope*> target_scopes;
list<pair<list<hname_t>,NetExpr*> > defparams_even_later;
while (! defparams_later.empty()) {
pair<list<hname_t>,NetExpr*> cur = defparams_later.front();
defparams_later.pop_front();
list<hname_t>eval_path = cur.first;
perm_string name = eval_path.back().peek_name();
eval_path.pop_back();
NetExpr*val = cur.second;
NetScope*targ_scope = des->find_scope(this, eval_path);
if (targ_scope == 0) {
// If a scope in the target path is not found,
// then push this defparam for handling even
// later. Maybe a later generate scheme or
// instance array will create the scope.
defparams_even_later.push_back(cur);
continue;
}
// Once placed in the parameter map, the expression may
// be deleted when evaluated, so give it a copy of this
// expression, not the original.
val = val->dup_expr();
bool flag = targ_scope->replace_parameter(name, val);
if (! flag) {
cerr << val->get_fileline() << ": warning: parameter "
<< name << " not found in "
<< scope_path(targ_scope) << "." << endl;
}
// We'll need to re-evaluate parameters in this scope
target_scopes.insert(targ_scope);
}
// All the scopes that this defparam set touched should have
// their parameters re-evaluated.
for (set<NetScope*>::iterator cur = target_scopes.begin()
; cur != target_scopes.end() ; cur ++ )
(*cur)->evaluate_parameters(des);
// If there are some scopes that still have missing scopes,
// then sav them back into the defparams_later list for a
// later pass.
defparams_later = defparams_even_later;
if (! defparams_later.empty())
des->defparams_later.insert(this);
}
void Design::evaluate_parameters()
@@ -357,11 +285,11 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
/* Evaluate the parameter expression, if necessary. */
NetExpr*expr = (*cur).second.expr;
if (expr == NULL) return; // This is an invalid parameter so return.
assert(expr);
eval_expr(expr);
/* The eval_expr may delete and replace the expr pointer, so the
/* The eval_expr may delete any replace the expr pointer, so the
second.expr value cannot be relied on. Might as well replace
it now with the expression that we evaluated. */
(*cur).second.expr = expr;
@@ -407,14 +335,6 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
unsigned long wid = (msb >= lsb)? msb - lsb : lsb - msb;
wid += 1;
/* If we have a real value convert it to an integer. */
if(NetECReal*tmp = dynamic_cast<NetECReal*>(expr)) {
verinum nval(tmp->value().as_long64());
expr = new NetEConst(nval);
expr->set_line(*((*cur).second.expr));
(*cur).second.expr = expr;
}
NetEConst*val = dynamic_cast<NetEConst*>(expr);
assert(val);
@@ -428,7 +348,7 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
tmp.has_sign ( (*cur).second.signed_flag );
delete val;
val = new NetEConst(tmp);
(*cur).second.expr = expr = val;
expr = val;
}
}
@@ -580,15 +500,12 @@ void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur)
void NetScope::evaluate_parameters(Design*des)
{
NetScope*curs = sub_;
while (curs) {
curs->evaluate_parameters(des);
curs = curs->sib_;
NetScope*cur = sub_;
while (cur) {
cur->evaluate_parameters(des);
cur = cur->sib_;
}
if (debug_scopes)
cerr << ":0" << ": debug: "
<< "Evaluate parameters in " << scope_path(this) << endl;
// Evaluate the parameter values. The parameter expressions
// have already been elaborated and replaced by the scope
@@ -623,32 +540,6 @@ void NetScope::evaluate_parameters(Design*des)
}
void Design::residual_defparams()
{
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
scope != root_scopes_.end(); scope++)
(*scope)->residual_defparams(this);
}
void NetScope::residual_defparams(Design*des)
{
// Clean out the list of defparams that never managed to match
// a scope. Print a warning for each.
while (! defparams_later.empty()) {
pair<list<hname_t>,NetExpr*> cur = defparams_later.front();
defparams_later.pop_front();
cerr << cur.second->get_fileline() << ": warning: "
<< "Scope of " << cur.first << " not found." << endl;
}
NetScope*cur = sub_;
while (cur) {
cur->residual_defparams(des);
cur = cur->sib_;
}
}
const char* Design::get_flag(const string&key) const
{
map<string,const char*>::const_iterator tmp = flags_.find(key);
@@ -764,11 +655,6 @@ void Design::add_process(NetProcTop*pro)
procs_ = pro;
}
void Design::add_process(NetAnalogTop*pro)
{
pro->next_ = aprocs_;
aprocs_ = pro;
}
void Design::delete_process(NetProcTop*top)
{
assert(top);
+3 -7
View File
@@ -173,12 +173,6 @@ void NetEvent::find_similar_event(list<NetEvent*>&event_list)
if (tmp == this)
continue;
/* For automatic tasks, the VVP runtime holds state for events
in the automatically allocated context. This means we can't
merge similar events in different automatic tasks. */
if (scope()->is_auto() && (tmp->scope() != scope()))
continue;
if ((*idx).second != probe_count)
continue;
@@ -257,6 +251,7 @@ NetEvProbe::NetEvProbe(NetScope*s, perm_string n, NetEvent*tgt,
{
for (unsigned idx = 0 ; idx < p ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("P"), idx);
}
enext_ = event_->probes_;
@@ -304,7 +299,7 @@ void NetEvProbe::find_similar_probes(list<NetEvProbe*>&plist)
Nexus*nex = pin(0).nexus();
for (Link*lcur = nex->first_nlink(); lcur; lcur = lcur->next_nlink()) {
NetPins*obj = lcur->get_obj();
NetObj*obj = lcur->get_obj();
if (obj->pin_count() != pin_count())
continue;
@@ -559,3 +554,4 @@ NetProc* NetEvWait::statement()
* Simulate named event trigger and waits.
*
*/
+41 -66
View File
@@ -35,8 +35,8 @@ ivl_variable_type_t NetExpr::expr_type() const
* Create an add/sub node from the two operands. Make a best guess of
* the
*/
NetEBAdd::NetEBAdd(char op__, NetExpr*l, NetExpr*r, bool lossless_flag)
: NetEBinary(op__, l, r)
NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r, bool lossless_flag)
: NetEBinary(op, l, r)
{
NetEConst* tmp;
@@ -56,54 +56,42 @@ NetEBAdd::NetEBAdd(char op__, NetExpr*l, NetExpr*r, bool lossless_flag)
&& (! tmp->has_width())
&& (tmp->expr_width() > l->expr_width() || integer_width > l->expr_width()) ) {
verinum tmp_v = trim_vnum(tmp->value());
unsigned target_width = l->expr_width();
if (target_width < tmp_v.len())
target_width = tmp_v.len();
if (lossless_flag)
target_width += 1;
unsigned target_width = l->expr_width() + 1;
if (target_width < integer_width)
target_width = integer_width;
r->set_width(target_width);
/* Note: This constant value will not gain a defined
width from this. Make sure. */
assert(! r->has_width() );
expr_width(target_width);
} else if ( (tmp = dynamic_cast<NetEConst*>(l))
&& (! tmp->has_width())
&& (tmp->expr_width() > r->expr_width() || integer_width > r->expr_width()) ) {
verinum tmp_v = trim_vnum(tmp->value());
unsigned target_width = r->expr_width();
if (target_width < tmp_v.len())
target_width = tmp_v.len();
if (lossless_flag)
target_width += 1;
unsigned target_width = r->expr_width() + 1;
if (target_width < integer_width)
target_width = integer_width;
l->set_width(target_width);
/* Note: This constant value will not gain a defined
width from this. Make sure. */
assert(! l->has_width() );
expr_width(target_width);
} else if (r->expr_width() > l->expr_width()) {
unsigned loss_pad = lossless_flag? 1 : 0;
expr_width(r->expr_width() + loss_pad);
} else {
unsigned loss_pad = lossless_flag? 1 : 0;
expr_width(l->expr_width() + loss_pad);
}
unsigned pad_width = lossless_flag? 1 : 0;
cast_signed(l->has_sign() && r->has_sign());
/* Now that we have the operand sizes the way we like, or as
good as we are going to get them, set the size of myself. */
if (r->expr_width() > l->expr_width()) {
expr_width(r->expr_width() + pad_width);
} else {
expr_width(l->expr_width() + pad_width);
}
}
NetEBAdd::~NetEBAdd()
@@ -136,12 +124,9 @@ ivl_variable_type_t NetEBAdd::expr_type() const
* expression. Otherwise, the netlist will have to allow the
* expressions to have different widths.
*/
NetEBComp::NetEBComp(char op__, NetExpr*l, NetExpr*r)
: NetEBinary(op__, l, r)
NetEBComp::NetEBComp(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
// The output of compare is always unsigned.
cast_signed_base_(false);
if (NetEConst*tmp = dynamic_cast<NetEConst*>(r)) do {
if (tmp->has_width())
@@ -200,8 +185,8 @@ ivl_variable_type_t NetEBComp::expr_type() const
return IVL_VT_BOOL;
}
NetEBDiv::NetEBDiv(char op__, NetExpr*l, NetExpr*r)
: NetEBinary(op__, l, r)
NetEBDiv::NetEBDiv(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
unsigned w = l->expr_width();
if (r->expr_width() > w)
@@ -233,8 +218,8 @@ ivl_variable_type_t NetEBDiv::expr_type() const
return IVL_VT_LOGIC;
}
NetEBMinMax::NetEBMinMax(char op__, NetExpr*l, NetExpr*r)
: NetEBinary(op__, l, r)
NetEBMinMax::NetEBMinMax(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
expr_width( max(l->expr_width(), r->expr_width()) );
cast_signed(l->has_sign() || r->has_sign());
@@ -254,18 +239,18 @@ ivl_variable_type_t NetEBMinMax::expr_type() const
return IVL_VT_LOGIC;
}
NetEBMult::NetEBMult(char op__, NetExpr*l, NetExpr*r)
: NetEBinary(op__, l, r)
NetEBMult::NetEBMult(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
if (expr_type() == IVL_VT_REAL)
expr_width(1);
else
expr_width(l->expr_width() + r->expr_width());
expr_width(l->expr_width() + r->expr_width());
cast_signed(l->has_sign() && r->has_sign());
if (expr_type() == IVL_VT_REAL)
cast_signed(true);
else
cast_signed(l->has_sign() && r->has_sign());
/* If it turns out that this is not a signed expression, then
cast the signedness out of the operands as well. */
if (! has_sign()) {
l->cast_signed(false);
r->cast_signed(false);
}
}
NetEBMult::~NetEBMult()
@@ -290,10 +275,10 @@ ivl_variable_type_t NetEBMult::expr_type() const
return IVL_VT_LOGIC;
}
NetEBPow::NetEBPow(char op__, NetExpr*l, NetExpr*r)
: NetEBinary(op__, l, r)
NetEBPow::NetEBPow(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
assert(op__ == 'p');
assert(op == 'p');
/* This is incorrect! a * (2^b - 1) is close. */
expr_width(l->expr_width()+r->expr_width());
cast_signed(l->has_sign() || r->has_sign());
@@ -317,17 +302,21 @@ ivl_variable_type_t NetEBPow::expr_type() const
return IVL_VT_REAL;
if (left_->expr_type() == IVL_VT_REAL)
return IVL_VT_REAL;
if (left_->has_sign())
return IVL_VT_REAL;
if (right_->has_sign())
return IVL_VT_REAL;
return IVL_VT_LOGIC;
}
NetEBShift::NetEBShift(char op__, NetExpr*l, NetExpr*r)
: NetEBinary(op__, l, r)
NetEBShift::NetEBShift(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
expr_width(l->expr_width());
// The >>> is signed if the left operand is signed.
if (op__ == 'R') cast_signed(l->has_sign());
if (op == 'R') cast_signed(l->has_sign());
}
NetEBShift::~NetEBShift()
@@ -599,17 +588,3 @@ ivl_variable_type_t NetESFunc::expr_type() const
{
return type_;
}
NetEAccess::NetEAccess(NetBranch*br, nature_t*nat)
: branch_(br), nature_(nat)
{
}
NetEAccess::~NetEAccess()
{
}
ivl_variable_type_t NetEAccess::expr_type() const
{
return IVL_VT_REAL;
}
+82
View File
@@ -0,0 +1,82 @@
/*
* Copyright (c) 2000-2004 Stephen Williams (steve@picturel.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_force.cc,v 1.13 2004/12/11 02:31:26 steve Exp $"
#endif
# include "config.h"
# include "compiler.h"
/*
* This file contains implementation of the NetForce, NetRelease,
* NetCAssign and NetDeassign classes. These are similar or related in
* that they handle the procedural continuous assign and force
* statements.
*/
# include "netlist.h"
# include <assert.h>
/*
* $Log: net_force.cc,v $
* Revision 1.13 2004/12/11 02:31:26 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.12 2004/02/18 17:11:56 steve
* Use perm_strings for named langiage items.
*
* Revision 1.11 2003/03/06 00:28:41 steve
* All NetObj objects have lex_string base names.
*
* Revision 1.10 2003/01/27 05:09:17 steve
* Spelling fixes.
*
* Revision 1.9 2002/08/19 00:06:12 steve
* Allow release to handle removal of target net.
*
* Revision 1.8 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
* Revision 1.7 2002/01/19 19:02:08 steve
* Pass back target errors processing conditionals.
*
* Revision 1.6 2001/11/14 03:28:49 steve
* DLL target support for force and release.
*
* Revision 1.5 2001/10/31 05:24:52 steve
* ivl_target support for assign/deassign.
*
* Revision 1.4 2001/10/28 01:14:53 steve
* NetObj constructor finally requires a scope.
*
* Revision 1.3 2001/07/25 03:10:49 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.2 2000/05/12 01:22:41 steve
* NetCAssign needs to incr_eref its lval to lock it down.
*
* Revision 1.1 2000/05/11 23:37:27 steve
* Add support for procedural continuous assignment.
*
*/
+14 -10
View File
@@ -34,10 +34,12 @@ NetUserFunc::NetUserFunc(NetScope*s, perm_string n, NetScope*d)
def_(d)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(def_->basename(), 0);
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("D"), idx-1);
pin(idx).drive0(Link::HIGHZ);
pin(idx).drive1(Link::HIGHZ);
}
@@ -49,36 +51,36 @@ NetUserFunc::~NetUserFunc()
ivl_variable_type_t NetUserFunc::data_type(unsigned port) const
{
NetFuncDef*fdef = def_->func_def();
NetFuncDef*def = def_->func_def();
/* Port 0 is the return port. */
if (port == 0) {
const NetNet*sig = fdef->return_sig();
const NetNet*sig = def->return_sig();
assert(sig);
return sig->data_type();
}
port -= 1;
assert(port < fdef->port_count());
const NetNet*port_sig = fdef->port(port);
assert(port < def->port_count());
const NetNet*port_sig = def->port(port);
return port_sig->data_type();
}
unsigned NetUserFunc::port_width(unsigned port) const
{
NetFuncDef*fdef = def_->func_def();
NetFuncDef*def = def_->func_def();
/* Port 0 is the return port. */
if (port == 0) {
const NetNet*sig = fdef->return_sig();
const NetNet*sig = def->return_sig();
assert(sig);
return sig->vector_width();
}
port -= 1;
assert(port < fdef->port_count());
const NetNet*port_sig = fdef->port(port);
assert(port < def->port_count());
const NetNet*port_sig = def->port(port);
return port_sig->vector_width();
}
@@ -102,7 +104,7 @@ bool PECallFunction::check_call_matches_definition_(Design*des, NetScope*dscope)
1 nil pointer. This is how the parser tells me of no
parameter. In other words, ``func()'' is 1 nil parameter. */
unsigned parms_count = parms_.size();
unsigned parms_count = parms_.count();
if ((parms_count == 1) && (parms_[0] == 0))
parms_count = 0;
@@ -133,11 +135,13 @@ NetSysFunc::NetSysFunc(NetScope*s, perm_string n,
{
def_ = def;
pin(0).set_dir(Link::OUTPUT); // Q
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Q"), 0);
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("D"), idx-1);
pin(idx).drive0(Link::HIGHZ);
pin(idx).drive1(Link::HIGHZ);
}
+34 -82
View File
@@ -64,7 +64,7 @@ void connect(Link&l, Link&r)
Link::Link()
: dir_(PASSIVE), drive0_(STRONG), drive1_(STRONG), init_(verinum::Vx),
next_(0), nexus_(0)
inst_(0), next_(0), nexus_(0)
{
(new Nexus()) -> relink(this);
}
@@ -103,11 +103,6 @@ void Link::drivers_delays(NetExpr*rise, NetExpr*fall, NetExpr*decay)
nexus_->drivers_delays(rise, fall, decay);
}
void Link::drivers_drive(strength_t drive0__, strength_t drive1__)
{
nexus_->drivers_drive(drive0__, drive1__);
}
void Link::drive0(Link::strength_t str)
{
drive0_ = str;
@@ -139,16 +134,16 @@ verinum::V Link::get_init() const
}
void Link::cur_link(NetPins*&net, unsigned &pin)
void Link::cur_link(NetObj*&net, unsigned &pin)
{
net = get_obj();
pin = get_pin();
net = node_;
pin = pin_;
}
void Link::cur_link(const NetPins*&net, unsigned &pin) const
void Link::cur_link(const NetObj*&net, unsigned &pin) const
{
net = get_obj();
pin = get_pin();
net = node_;
pin = pin_;
}
void Link::unlink()
@@ -191,30 +186,35 @@ const Link* Link::next_nlink() const
return next_;
}
const NetPins*Link::get_obj() const
const NetObj*Link::get_obj() const
{
if (pin_zero_)
return node_;
const Link*tmp = this - pin_;
assert(tmp->pin_zero_);
return tmp->node_;
return node_;
}
NetPins*Link::get_obj()
NetObj*Link::get_obj()
{
if (pin_zero_)
return node_;
Link*tmp = this - pin_;
assert(tmp->pin_zero_);
return tmp->node_;
return node_;
}
unsigned Link::get_pin() const
{
if (pin_zero_)
return 0;
else
return pin_;
return pin_;
}
void Link::set_name(perm_string n, unsigned i)
{
name_ = n;
inst_ = i;
}
perm_string Link::get_name() const
{
return name_;
}
unsigned Link::get_inst() const
{
return inst_;
}
Nexus::Nexus()
@@ -247,68 +247,19 @@ verinum::V Nexus::get_init() const
return verinum::Vz;
}
bool Nexus::drivers_present() const
{
assert(list_);
for (Link*cur = list_ ; cur ; cur = cur->next_) {
if (cur->get_dir() == Link::OUTPUT)
return true;
if (cur->get_dir() == Link::INPUT)
continue;
// Must be PASSIVE, so if it is some kind of net, see if
// it is the sort that might drive the nexus.
const NetPins*obj;
unsigned pin;
cur->cur_link(obj, pin);
if (const NetNet*net = dynamic_cast<const NetNet*>(obj))
switch (net->type()) {
case NetNet::SUPPLY0:
case NetNet::SUPPLY1:
case NetNet::TRI0:
case NetNet::TRI1:
case NetNet::WAND:
case NetNet::WOR:
case NetNet::TRIAND:
case NetNet::TRIOR:
case NetNet::REG:
return true;
default:
break;
}
}
return false;
}
void Nexus::drivers_delays(NetExpr*rise, NetExpr*fall, NetExpr*decay)
{
for (Link*cur = list_ ; cur ; cur = cur->next_) {
if (cur->get_dir() != Link::OUTPUT)
continue;
NetObj*obj = dynamic_cast<NetObj*>(cur->get_obj());
if (obj == 0)
continue;
NetObj*obj = cur->get_obj();
obj->rise_time(rise);
obj->fall_time(fall);
obj->decay_time(decay);
}
}
void Nexus::drivers_drive(Link::strength_t drive0, Link::strength_t drive1)
{
for (Link*cur = list_ ; cur ; cur = cur->next_) {
if (cur->get_dir() != Link::OUTPUT)
continue;
cur->drive0(drive0);
cur->drive1(drive1);
}
}
void Nexus::unlink(Link*that)
{
if (name_) {
@@ -446,11 +397,12 @@ const char* Nexus::name() const
if (sig == 0) {
const Link*lnk = first_nlink();
const NetObj*obj = dynamic_cast<const NetObj*>(lnk->get_obj());
const NetObj*obj = lnk->get_obj();
pin = lnk->get_pin();
cerr << "internal error: No signal for nexus of "
<< obj->name() << " pin " << pin
<< " type=" << typeid(*obj).name() << "?" << endl;
cerr << "internal error: No signal for nexus of " <<
obj->name() << " pin " << pin << "(" <<
lnk->get_name() << "<" << lnk->get_inst() << ">)"
" type=" << typeid(*obj).name() << "?" << endl;
}
assert(sig);
+32 -14
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2005 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
@@ -16,6 +16,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_modulo.cc,v 1.9 2005/09/15 22:54:47 steve Exp $"
#endif
# include "config.h"
@@ -37,9 +40,12 @@ NetModulo::NetModulo(NetScope*s, perm_string n, unsigned wr,
: NetNode(s, n, 3),
width_r_(wr), width_a_(wa), width_b_(wb)
{
pin(0).set_dir(Link::OUTPUT); // Result
pin(1).set_dir(Link::INPUT); // DataA
pin(2).set_dir(Link::INPUT); // DataB
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Result"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("DataA"), 0);
pin(2).set_dir(Link::INPUT);
pin(2).set_name(perm_string::literal("DataB"), 0);
}
NetModulo::~NetModulo()
@@ -66,16 +72,6 @@ Link& NetModulo::pin_Result()
return pin(0);
}
void NetModulo::set_signed(bool flag)
{
signed_flag_ = flag;
}
bool NetModulo::get_signed() const
{
return signed_flag_;
}
const Link& NetModulo::pin_Result() const
{
return pin(0);
@@ -100,3 +96,25 @@ const Link& NetModulo::pin_DataB() const
{
return pin(2);
}
/*
* $Log: net_modulo.cc,v $
* Revision 1.9 2005/09/15 22:54:47 steve
* Fix bug configuring NetModulo pins.
*
* Revision 1.8 2005/03/12 06:43:35 steve
* Update support for LPM_MOD.
*
* Revision 1.7 2004/02/18 17:11:56 steve
* Use perm_strings for named langiage items.
*
* Revision 1.6 2003/03/06 00:28:41 steve
* All NetObj objects have lex_string base names.
*
* Revision 1.5 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
* Revision 1.4 2002/08/11 23:47:04 steve
* Add missing Log and Ident strings.
*
*/
+2 -15
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-2007 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,13 +53,8 @@ NexusSet* NetEBinary::nex_input(bool rem_out)
NexusSet* NetEConcat::nex_input(bool rem_out)
{
if (parms_[0] == NULL) return NULL;
NexusSet*result = parms_[0]->nex_input(rem_out);
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
if (parms_[idx] == NULL) {
delete result;
return NULL;
}
NexusSet*tmp = parms_[idx]->nex_input(rem_out);
result->add(*tmp);
delete tmp;
@@ -67,11 +62,6 @@ NexusSet* NetEConcat::nex_input(bool rem_out)
return result;
}
NexusSet* NetEAccess::nex_input(bool rem_out)
{
return new NexusSet;
}
/*
* A constant has not inputs, so always return an empty set.
*/
@@ -108,10 +98,6 @@ NexusSet* NetESelect::nex_input(bool rem_out)
{
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;
return result;
@@ -395,3 +381,4 @@ NexusSet* NetWhile::nex_input(bool rem_out)
delete tmp;
return result;
}
+34 -12
View File
@@ -38,9 +38,9 @@
NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t)
: type_(t), up_(up), sib_(0), sub_(0)
{
signals_ = 0;
events_ = 0;
lcounter_ = 0;
is_auto_ = false;
if (up) {
default_nettype_ = up->default_nettype();
@@ -106,7 +106,7 @@ void NetScope::set_line(perm_string file, perm_string def_file,
}
NetExpr* NetScope::set_parameter(perm_string key, NetExpr*expr,
ivl_variable_type_t type__,
ivl_variable_type_t type,
NetExpr*msb, NetExpr*lsb, bool signed_flag,
NetScope::range_t*range_list,
const LineInfo&file_line)
@@ -114,7 +114,7 @@ NetExpr* NetScope::set_parameter(perm_string key, NetExpr*expr,
param_expr_t&ref = parameters[key];
NetExpr* res = ref.expr;
ref.expr = expr;
ref.type = type__;
ref.type = type;
ref.msb = msb;
ref.lsb = lsb;
ref.signed_flag = signed_flag;
@@ -122,7 +122,7 @@ NetExpr* NetScope::set_parameter(perm_string key, NetExpr*expr,
ref.range = range_list;
ref.set_line(file_line);
ivl_assert(file_line, type__ != IVL_VT_NO_TYPE);
ivl_assert(file_line, type != IVL_VT_NO_TYPE);
return res;
}
@@ -166,7 +166,7 @@ bool NetScope::replace_parameter(perm_string key, NetExpr*expr)
/*
* This is not really complete (msb, lsb, sign). It is currently only
* used to add a genvar to the local parameter list.
* used to add a genver to the local parameter list.
*/
NetExpr* NetScope::set_localparam(perm_string key, NetExpr*expr,
const LineInfo&file_line)
@@ -261,7 +261,6 @@ NetFuncDef* NetScope::func_def()
assert( type_ == FUNC );
return func_;
}
bool NetScope::in_func()
{
return (type_ == FUNC) ? true : false;
@@ -276,7 +275,7 @@ const NetFuncDef* NetScope::func_def() const
void NetScope::set_module_name(perm_string n)
{
assert(type_ == MODULE);
module_name_ = n; /* NOTE: n must have been permallocated. */
module_name_ = n; /* NOTE: n mus have been permallocated. */
}
perm_string NetScope::module_name() const
@@ -359,13 +358,30 @@ NetEvent* NetScope::find_event(perm_string name)
void NetScope::add_signal(NetNet*net)
{
signals_map_[net->name()]=net;
if (signals_ == 0) {
net->sig_next_ = net;
net->sig_prev_ = net;
} else {
net->sig_next_ = signals_->sig_next_;
net->sig_prev_ = signals_;
net->sig_next_->sig_prev_ = net;
net->sig_prev_->sig_next_ = net;
}
signals_ = net;
}
void NetScope::rem_signal(NetNet*net)
{
assert(net->scope() == this);
signals_map_.erase(net->name());
if (signals_ == net)
signals_ = net->sig_prev_;
if (signals_ == net) {
signals_ = 0;
} else {
net->sig_prev_->sig_next_ = net->sig_next_;
net->sig_next_->sig_prev_ = net->sig_prev_;
}
}
/*
@@ -375,10 +391,16 @@ void NetScope::rem_signal(NetNet*net)
*/
NetNet* NetScope::find_signal(perm_string key)
{
if (signals_map_.find(key)!=signals_map_.end())
return signals_map_[key];
else
if (signals_ == 0)
return 0;
NetNet*cur = signals_;
do {
if (cur->name() == key)
return cur;
cur = cur->sig_prev_;
} while (cur != signals_);
return 0;
}
/*
+15 -18
View File
@@ -42,21 +42,22 @@ static bool has_enable(ivl_switch_type_t tt)
}
}
NetTran::NetTran(NetScope*scope__, perm_string n, ivl_switch_type_t tt)
: NetNode(scope__, n, has_enable(tt)? 3 : 2), type_(tt)
NetTran::NetTran(NetScope*scope, perm_string n, ivl_switch_type_t tt)
: NetNode(scope, n, has_enable(tt)? 3 : 2), type_(tt)
{
pin(0).set_dir(Link::PASSIVE);
pin(1).set_dir(Link::PASSIVE);
pin(0).set_dir(Link::PASSIVE); pin(0).set_name(perm_string::literal("A"), 0);
pin(1).set_dir(Link::PASSIVE); pin(1).set_name(perm_string::literal("B"), 0);
if (pin_count() == 3) {
pin(2).set_dir(Link::INPUT); // Enable
pin(2).set_dir(Link::INPUT);
pin(2).set_name(perm_string::literal("E"), 0);
}
}
NetTran::NetTran(NetScope*scope__, perm_string n, unsigned wid, unsigned part, unsigned off)
: NetNode(scope__, n, 2), type_(IVL_SW_TRAN_VP), wid_(wid), part_(part), off_(off)
NetTran::NetTran(NetScope*scope, perm_string n, unsigned wid, unsigned part, unsigned off)
: NetNode(scope, n, 2), type_(IVL_SW_TRAN_VP), wid_(wid), part_(part), off_(off)
{
pin(0).set_dir(Link::PASSIVE);
pin(1).set_dir(Link::PASSIVE);
pin(0).set_dir(Link::PASSIVE); pin(0).set_name(perm_string::literal("A"), 0);
pin(1).set_dir(Link::PASSIVE); pin(1).set_name(perm_string::literal("B"), 0);
}
NetTran::~NetTran()
@@ -99,12 +100,8 @@ void join_island(NetObj*obj)
Nexus*nex = obj->pin(idx).nexus();
for (Link*cur = nex->first_nlink() ; cur ; cur = cur->next_nlink()) {
unsigned pin;
NetPins*tmp_pins;
cur->cur_link(tmp_pins, pin);
NetObj*tmp = dynamic_cast<NetObj*> (tmp_pins);
if (tmp == 0)
continue;
NetObj*tmp;
cur->cur_link(tmp, pin);
// Skip self.
if (tmp == obj)
@@ -117,7 +114,7 @@ void join_island(NetObj*obj)
// If that is an uncommitted branch, then save
// it. When I finally choose an island for self,
// these branches will be scanned so that they join
// these branches will be scanned so tha they join
// this island as well.
if (tmp_branch->island == 0) {
uncommitted_neighbors.push_back(tmp);
@@ -131,7 +128,7 @@ void join_island(NetObj*obj)
if (branch->island == 0) {
if (debug_elaborate)
cerr << obj->get_fileline() << ": debug: "
<< "Join branch to existing island." << endl;
<< "Join brach to existing island." << endl;
branch->island = tmp_branch->island;
} else if (branch->island != tmp_branch->island) {
@@ -142,7 +139,7 @@ void join_island(NetObj*obj)
}
}
// If after all that we did not find an island to join, then
// If after all that we did not find an idland to join, then
// start the island not and join it.
if (branch->island == 0) {
branch->island = new ivl_island_s;
+2
View File
@@ -30,8 +30,10 @@ NetUDP::NetUDP(NetScope*s, perm_string n, unsigned pins, PUdp *u)
: NetNode(s, n, pins), udp(u)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"), 0);
for (unsigned idx = 1 ; idx < pins ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("I"), idx-1);
}
}
+249 -259
View File
@@ -23,7 +23,6 @@
# include <typeinfo>
# include <cstdlib>
# include <climits>
# include "compiler.h"
# include "netlist.h"
# include "netmisc.h"
@@ -92,7 +91,7 @@ unsigned count_inputs(const Link&pin)
const Nexus*nex = pin.nexus();
for (const Link*clnk = nex->first_nlink()
; clnk ; clnk = clnk->next_nlink()) {
const NetPins*cur;
const NetObj*cur;
unsigned cpin;
clnk->cur_link(cur, cpin);
if (cur->pin(cpin).get_dir() == Link::INPUT)
@@ -109,7 +108,7 @@ unsigned count_outputs(const Link&pin)
const Nexus*nex = pin.nexus();
for (const Link*clnk = nex->first_nlink()
; clnk ; clnk = clnk->next_nlink()) {
const NetPins*cur;
const NetObj*cur;
unsigned cpin;
clnk->cur_link(cur, cpin);
if (cur->pin(cpin).get_dir() == Link::OUTPUT)
@@ -126,7 +125,7 @@ unsigned count_signals(const Link&pin)
const Nexus*nex = pin.nexus();
for (const Link*clnk = nex->first_nlink()
; clnk ; clnk = clnk->next_nlink()) {
const NetPins*cur;
const NetObj*cur;
unsigned cpin;
clnk->cur_link(cur, cpin);
if (dynamic_cast<const NetNet*>(cur))
@@ -143,7 +142,7 @@ const NetNet* find_link_signal(const NetObj*net, unsigned pin, unsigned&bidx)
for (const Link*clnk = nex->first_nlink()
; clnk ; clnk = clnk->next_nlink()) {
const NetPins*cur;
const NetObj*cur;
unsigned cpin;
clnk->cur_link(cur, cpin);
@@ -172,53 +171,19 @@ Link* find_next_output(Link*lnk)
return 0;
}
NetPins::NetPins(unsigned npins)
: npins_(npins)
NetObj::NetObj(NetScope*s, perm_string n, unsigned np)
: scope_(s), name_(n), npins_(np), delay1_(0), delay2_(0), delay3_(0)
{
pins_ = new Link[npins_];
pins_[0].pin_zero_ = true;
pins_[0].node_ = this;
for (unsigned idx = 1 ; idx < npins_ ; idx += 1) {
pins_[idx].pin_zero_ = false;
pins_[idx].pin_ = idx;
for (unsigned idx = 0 ; idx < npins_ ; idx += 1) {
pins_[idx].node_ = this;
pins_[idx].pin_ = idx;
}
}
NetPins::~NetPins()
{
delete[]pins_;
}
Link& NetPins::pin(unsigned idx)
{
if (idx >= npins_) {
cerr << get_fileline() << ": internal error: pin("<<idx<<")"
<< " out of bounds("<<npins_<<")" << endl;
cerr << get_fileline() << ": : typeid="
<< typeid(*this).name() << endl;
}
assert(idx < npins_);
assert(idx == 0? pins_[0].pin_zero_ : pins_[idx].pin_==idx);
return pins_[idx];
}
const Link& NetPins::pin(unsigned idx) const
{
assert(idx < npins_);
assert(idx == 0? pins_[0].pin_zero_ : pins_[idx].pin_==idx);
return pins_[idx];
}
NetObj::NetObj(NetScope*s, perm_string n, unsigned np)
: NetPins(np), scope_(s), name_(n), delay1_(0), delay2_(0), delay3_(0)
{
}
NetObj::~NetObj()
{
delete[]pins_;
}
NetScope* NetObj::scope()
@@ -231,6 +196,25 @@ const NetScope* NetObj::scope() const
return scope_;
}
Link& NetObj::pin(unsigned idx)
{
if (idx >= npins_) {
cerr << get_fileline() << ": internal error: pin("<<idx<<")"
<< " out of bounds("<<npins_<<")" << endl;
cerr << get_fileline() << ": : typeid="
<< typeid(*this).name() << endl;
}
assert(idx < npins_);
return pins_[idx];
}
const Link& NetObj::pin(unsigned idx) const
{
assert(idx < npins_);
return pins_[idx];
}
NetNode::NetNode(NetScope*s, perm_string n, unsigned npins)
: NetObj(s, n, npins), node_next_(0), node_prev_(0), design_(0)
{
@@ -242,19 +226,8 @@ NetNode::~NetNode()
design_->del_node(this);
}
NetBranch::NetBranch(ivl_discipline_t dis)
: NetPins(2), discipline_(dis)
{
pin(0).set_dir(Link::PASSIVE);
pin(1).set_dir(Link::PASSIVE);
}
NetBranch::~NetBranch()
{
}
NetBus::NetBus(NetScope*s, unsigned pin_count__)
: NetObj(s, perm_string::literal(""), pin_count__)
NetBus::NetBus(NetScope*s, unsigned pin_count)
: NetObj(s, perm_string::literal(""), pin_count)
{
}
@@ -271,11 +244,13 @@ NetDelaySrc::NetDelaySrc(NetScope*s, perm_string n, unsigned npins,
posedge_ = false;
negedge_ = false;
for (unsigned idx = 0 ; idx < npins ; idx += 1) {
pin(idx).set_name(perm_string::literal("I"), idx);
pin(idx).set_dir(Link::INPUT);
}
if (condit_src) {
condit_flag_ = true;
pin(npins).set_name(perm_string::literal("COND"), 0);
pin(npins).set_dir(Link::INPUT);
}
}
@@ -427,10 +402,9 @@ const Link& NetDelaySrc::condit_pin() const
}
NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
: NetObj(s, n, 1),
: NetObj(s, n, 1), sig_next_(0), sig_prev_(0),
type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE),
signed_(false), isint_(false), discipline_(0), msb_(npins-1), lsb_(0),
dimensions_(0),
signed_(false), isint_(false), msb_(npins-1), lsb_(0), dimensions_(0),
s0_(0), e0_(0), local_flag_(false), eref_count_(0), lref_count_(0)
{
assert(s);
@@ -458,6 +432,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
break;
}
pin(0).set_name(perm_string::literal("P"), 0);
pin(0).set_dir(dir);
pin(0).set_init(init_value);
@@ -466,9 +441,10 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
NetNet::NetNet(NetScope*s, perm_string n, Type t,
long ms, long ls)
: NetObj(s, n, 1), type_(t),
: NetObj(s, n, 1),
sig_next_(0), sig_prev_(0), type_(t),
port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false),
isint_(false), discipline_(0), msb_(ms), lsb_(ls), dimensions_(0), s0_(0), e0_(0),
isint_(false), msb_(ms), lsb_(ls), dimensions_(0), s0_(0), e0_(0),
local_flag_(false), eref_count_(0), lref_count_(0)
{
assert(s);
@@ -495,6 +471,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
}
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
pin(idx).set_name(perm_string::literal("P"), idx);
pin(idx).set_dir(dir);
pin(idx).set_init(init_value);
}
@@ -513,9 +490,9 @@ static unsigned calculate_count(long s, long e)
NetNet::NetNet(NetScope*s, perm_string n, Type t,
long ms, long ls, long array_s, long array_e)
: NetObj(s, n, calculate_count(array_s, array_e)),
type_(t), port_type_(NOT_A_PORT),
sig_next_(0), sig_prev_(0), type_(t), port_type_(NOT_A_PORT),
data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false),
discipline_(0), msb_(ms), lsb_(ls), dimensions_(1), s0_(array_s), e0_(array_e),
msb_(ms), lsb_(ls), dimensions_(1), s0_(array_s), e0_(array_e),
local_flag_(false), eref_count_(0), lref_count_(0)
{
assert(s);
@@ -542,6 +519,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
}
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
pin(idx).set_name(perm_string::literal("P"), idx);
pin(idx).set_dir(dir);
pin(idx).set_init(init_value);
}
@@ -626,10 +604,7 @@ void NetNet::data_type(ivl_variable_type_t t)
bool NetNet::get_signed() const
{
if (data_type_ == IVL_VT_REAL)
return true;
else
return signed_;
return signed_;
}
void NetNet::set_signed(bool flag)
@@ -647,17 +622,6 @@ void NetNet::set_isint(bool flag)
isint_ = flag;
}
ivl_discipline_t NetNet::get_discipline() const
{
return discipline_;
}
void NetNet::set_discipline(ivl_discipline_t dis)
{
ivl_assert(*this, discipline_ == 0);
discipline_ = dis;
}
long NetNet::lsb() const
{
return lsb_;
@@ -781,9 +745,9 @@ const NetDelaySrc* NetNet::delay_path(unsigned idx) const
}
NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid,
NetPartSelect::dir_t dir__)
NetPartSelect::dir_t dir)
: NetNode(sig->scope(), sig->scope()->local_symbol(), 2),
off_(off), wid_(wid), dir_(dir__)
off_(off), wid_(wid), dir_(dir)
{
connect(pin(1), sig->pin(0));
set_line(*sig);
@@ -798,6 +762,8 @@ NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid,
pin(1).set_dir(Link::OUTPUT);
break;
}
pin(0).set_name(perm_string::literal("Part"), 0);
pin(1).set_name(perm_string::literal("Vect"), 0);
}
NetPartSelect::NetPartSelect(NetNet*sig, NetNet*sel,
@@ -819,6 +785,10 @@ NetPartSelect::NetPartSelect(NetNet*sig, NetNet*sel,
break;
}
pin(2).set_dir(Link::INPUT);
pin(0).set_name(perm_string::literal("Part"), 0);
pin(1).set_name(perm_string::literal("Vect"), 0);
pin(2).set_name(perm_string::literal("Select"), 0);
}
NetPartSelect::~NetPartSelect()
@@ -849,7 +819,7 @@ NetProc::~NetProc()
{
}
NetProcTop::NetProcTop(NetScope*s, ivl_process_type_t t, NetProc*st)
NetProcTop::NetProcTop(NetScope*s, Type t, NetProc*st)
: type_(t), statement_(st), scope_(s)
{
}
@@ -874,41 +844,19 @@ NetScope* NetProcTop::scope()
return scope_;
}
NetAnalogTop::NetAnalogTop(NetScope*scope, ivl_process_type_t t, NetProc*st)
: type_(t), statement_(st), scope_(scope)
{
next_ = 0;
}
NetAnalogTop::~NetAnalogTop()
{
}
const NetScope* NetProcTop::scope() const
{
return scope_;
}
NetCastInt::NetCastInt(NetScope*scope__, perm_string n, unsigned width__)
: NetNode(scope__, n, 2), width_(width__)
{
pin(0).set_dir(Link::OUTPUT);
pin(1).set_dir(Link::INPUT);
}
NetCastReal::NetCastReal(NetScope*scope__, perm_string n, bool signed_flag__)
: NetNode(scope__, n, 2), signed_flag_(signed_flag__)
{
pin(0).set_dir(Link::OUTPUT);
pin(1).set_dir(Link::INPUT);
}
NetConcat::NetConcat(NetScope*scope__, perm_string n, unsigned wid, unsigned cnt)
: NetNode(scope__, n, cnt+1), width_(wid)
NetConcat::NetConcat(NetScope*scope, perm_string n, unsigned wid, unsigned cnt)
: NetNode(scope, n, cnt+1), width_(wid)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"), 0);
for (unsigned idx = 1 ; idx < cnt+1 ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("I"), idx-1);
}
}
@@ -921,12 +869,14 @@ unsigned NetConcat::width() const
return width_;
}
NetReplicate::NetReplicate(NetScope*scope__, perm_string n,
NetReplicate::NetReplicate(NetScope*scope, perm_string n,
unsigned wid, unsigned rpt)
: NetNode(scope__, n, 2), width_(wid), repeat_(rpt)
: NetNode(scope, n, 2), width_(wid), repeat_(rpt)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("I"), 0);
}
NetReplicate::~NetReplicate()
@@ -957,17 +907,25 @@ unsigned NetReplicate::repeat() const
* ...
*/
NetFF::NetFF(NetScope*s, perm_string n, unsigned width__)
: NetNode(s, n, 8), width_(width__)
NetFF::NetFF(NetScope*s, perm_string n, unsigned width)
: NetNode(s, n, 8), width_(width)
{
pin_Clock().set_dir(Link::INPUT);
pin_Clock().set_name(perm_string::literal("Clock"), 0);
pin_Enable().set_dir(Link::INPUT);
pin_Enable().set_name(perm_string::literal("Enable"), 0);
pin_Aset().set_dir(Link::INPUT);
pin_Aset().set_name(perm_string::literal("Aset"), 0);
pin_Aclr().set_dir(Link::INPUT);
pin_Aclr().set_name(perm_string::literal("Aclr"), 0);
pin_Sset().set_dir(Link::INPUT);
pin_Sset().set_name(perm_string::literal("Sset"), 0);
pin_Sclr().set_dir(Link::INPUT);
pin_Sclr().set_name(perm_string::literal("Sclr"), 0);
pin_Data().set_dir(Link::INPUT);
pin_Data().set_name(perm_string::literal("Data"), 0);
pin_Q().set_dir(Link::OUTPUT);
pin_Q().set_name(perm_string::literal("Q"), 0);
}
NetFF::~NetFF()
@@ -1084,7 +1042,9 @@ NetAbs::NetAbs(NetScope*s, perm_string n, unsigned w)
: NetNode(s, n, 2), width_(w)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Result"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("DataA"), 0);
}
NetAbs::~NetAbs()
@@ -1099,18 +1059,37 @@ unsigned NetAbs::width() const
/*
* The NetAddSub class represents an LPM_ADD_SUB device. The pinout is
* assigned like so:
* 0 -- Cout
* 1 -- DataA (normally a vector)
* 2 -- DataB (normally a vector)
* 3 -- Result (normally a vector)
* 0 -- Add_Sub
* 1 -- Aclr
* 2 -- Clock
* 3 -- Cin
* 4 -- Cout
* 5 -- Overflow
* 6 -- DataA (normally a vector)
* 7 -- DataB (normally a vector)
* 8 -- Result (normally a vector)
*/
NetAddSub::NetAddSub(NetScope*s, perm_string n, unsigned w)
: NetNode(s, n, 4), width_(w)
: NetNode(s, n, 9), width_(w)
{
pin(0).set_dir(Link::OUTPUT); // Cout
pin(1).set_dir(Link::INPUT); // DataA
pin(2).set_dir(Link::INPUT); // DataB
pin(3).set_dir(Link::OUTPUT); // Result
pin(0).set_dir(Link::INPUT);
pin(0).set_name(perm_string::literal("Add_Sub"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("Aclr"), 0);
pin(2).set_dir(Link::INPUT);
pin(2).set_name(perm_string::literal("Clock"), 0);
pin(3).set_dir(Link::INPUT);
pin(3).set_name(perm_string::literal("Cin"), 0);
pin(4).set_dir(Link::OUTPUT);
pin(4).set_name(perm_string::literal("Cout"), 0);
pin(5).set_dir(Link::OUTPUT);
pin(5).set_name(perm_string::literal("Overflow"), 0);
pin(6).set_dir(Link::INPUT);
pin(6).set_name(perm_string::literal("DataA"), 0);
pin(7).set_dir(Link::INPUT);
pin(7).set_name(perm_string::literal("DataB"), 0);
pin(8).set_dir(Link::OUTPUT);
pin(8).set_name(perm_string::literal("Result"), 0);
}
NetAddSub::~NetAddSub()
@@ -1124,53 +1103,55 @@ unsigned NetAddSub::width()const
Link& NetAddSub::pin_Cout()
{
return pin(0);
return pin(4);
}
const Link& NetAddSub::pin_Cout() const
{
return pin(0);
return pin(4);
}
Link& NetAddSub::pin_DataA()
{
return pin(1);
return pin(6);
}
const Link& NetAddSub::pin_DataA() const
{
return pin(1);
return pin(6);
}
Link& NetAddSub::pin_DataB()
{
return pin(2);
return pin(7);
}
const Link& NetAddSub::pin_DataB() const
{
return pin(2);
return pin(7);
}
Link& NetAddSub::pin_Result()
{
return pin(3);
return pin(8);
}
const Link& NetAddSub::pin_Result() const
{
return pin(3);
return pin(8);
}
NetArrayDq::NetArrayDq(NetScope*s, perm_string n, NetNet*mem__, unsigned awid)
NetArrayDq::NetArrayDq(NetScope*s, perm_string n, NetNet*mem, unsigned awid)
: NetNode(s, n, 2),
mem_(mem__), awidth_(awid)
mem_(mem), awidth_(awid)
{
pin(0).set_dir(Link::OUTPUT); // Result
pin(1).set_dir(Link::INPUT); // Address
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Result"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("Address"), 0);
// Increment the expression reference count for the target
// memory so that it is not deleted underneath me.
mem_->incr_eref();
mem->incr_eref();
}
NetArrayDq::~NetArrayDq()
@@ -1219,15 +1200,18 @@ const Link& NetArrayDq::pin_Address() const
* 2 -- Distance
*/
NetCLShift::NetCLShift(NetScope*s, perm_string n,
unsigned width__, unsigned width_dist__,
bool right_flag__, bool signed_flag__)
unsigned width, unsigned width_dist,
bool right_flag, bool signed_flag)
: NetNode(s, n, 3),
width_(width__), width_dist_(width_dist__),
right_flag_(right_flag__), signed_flag_(signed_flag__)
width_(width), width_dist_(width_dist),
right_flag_(right_flag), signed_flag_(signed_flag)
{
pin(0).set_dir(Link::OUTPUT); // Result
pin(1).set_dir(Link::INPUT); // Data
pin(2).set_dir(Link::INPUT); // Distance
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Result"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("Data"), 0);
pin(2).set_dir(Link::INPUT);
pin(2).set_name(perm_string::literal("Distance"), 0);
}
NetCLShift::~NetCLShift()
@@ -1285,17 +1269,29 @@ const Link& NetCLShift::pin_Distance() const
}
NetCompare::NetCompare(NetScope*s, perm_string n, unsigned wi)
: NetNode(s, n, 8), width_(wi)
: NetNode(s, n, 10), width_(wi)
{
signed_flag_ = false;
pin(0).set_dir(Link::OUTPUT); // AGB
pin(1).set_dir(Link::OUTPUT); // AGEB
pin(2).set_dir(Link::OUTPUT); // AEB
pin(3).set_dir(Link::OUTPUT); // ANEB
pin(4).set_dir(Link::OUTPUT); // ALB
pin(5).set_dir(Link::OUTPUT); // ALEB
pin(6).set_dir(Link::INPUT); // DataA
pin(7).set_dir(Link::INPUT); // DataB
pin(0).set_dir(Link::INPUT); pin(0).set_name(
perm_string::literal("Aclr"));
pin(1).set_dir(Link::INPUT); pin(1).set_name(
perm_string::literal("Clock"));
pin(2).set_dir(Link::OUTPUT); pin(2).set_name(
perm_string::literal("AGB"));
pin(3).set_dir(Link::OUTPUT); pin(3).set_name(
perm_string::literal("AGEB"));
pin(4).set_dir(Link::OUTPUT); pin(4).set_name(
perm_string::literal("AEB"));
pin(5).set_dir(Link::OUTPUT); pin(5).set_name(
perm_string::literal("ANEB"));
pin(6).set_dir(Link::OUTPUT); pin(6).set_name(
perm_string::literal("ALB"));
pin(7).set_dir(Link::OUTPUT); pin(7).set_name(
perm_string::literal("ALEB"));
pin(8).set_dir(Link::INPUT);
pin(8).set_name(perm_string::literal("DataA"));
pin(9).set_dir(Link::INPUT);
pin(9).set_name(perm_string::literal("DataB"));
}
NetCompare::~NetCompare()
@@ -1317,85 +1313,104 @@ void NetCompare::set_signed(bool flag)
signed_flag_ = flag;
}
Link& NetCompare::pin_Aclr()
{
return pin(0);
}
const Link& NetCompare::pin_Aclr() const
{
return pin(0);
}
Link& NetCompare::pin_Clock()
{
return pin(1);
}
const Link& NetCompare::pin_Clock() const
{
return pin(1);
}
Link& NetCompare::pin_AGB()
{
return pin(0);
return pin(2);
}
const Link& NetCompare::pin_AGB() const
{
return pin(0);
return pin(2);
}
Link& NetCompare::pin_AGEB()
{
return pin(1);
return pin(3);
}
const Link& NetCompare::pin_AGEB() const
{
return pin(1);
return pin(3);
}
Link& NetCompare::pin_AEB()
{
return pin(2);
return pin(4);
}
const Link& NetCompare::pin_AEB() const
{
return pin(2);
return pin(4);
}
Link& NetCompare::pin_ANEB()
{
return pin(3);
return pin(5);
}
const Link& NetCompare::pin_ANEB() const
{
return pin(3);
return pin(5);
}
Link& NetCompare::pin_ALB()
{
return pin(4);
return pin(6);
}
const Link& NetCompare::pin_ALB() const
{
return pin(4);
return pin(6);
}
Link& NetCompare::pin_ALEB()
{
return pin(5);
return pin(7);
}
const Link& NetCompare::pin_ALEB() const
{
return pin(5);
return pin(7);
}
Link& NetCompare::pin_DataA()
{
return pin(6);
return pin(8);
}
const Link& NetCompare::pin_DataA() const
{
return pin(6);
return pin(8);
}
Link& NetCompare::pin_DataB()
{
return pin(7);
return pin(9);
}
const Link& NetCompare::pin_DataB() const
{
return pin(7);
return pin(9);
}
NetDivide::NetDivide(NetScope*sc, perm_string n, unsigned wr,
@@ -1403,9 +1418,12 @@ NetDivide::NetDivide(NetScope*sc, perm_string n, unsigned wr,
: NetNode(sc, n, 3),
width_r_(wr), width_a_(wa), width_b_(wb), signed_flag_(false)
{
pin(0).set_dir(Link::OUTPUT); // Result
pin(1).set_dir(Link::INPUT); // DataA
pin(2).set_dir(Link::INPUT); // DataB
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Result"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("DataA"), 0);
pin(2).set_dir(Link::INPUT);
pin(2).set_name(perm_string::literal("DataB"), 0);
}
NetDivide::~NetDivide()
@@ -1471,17 +1489,13 @@ NetLiteral::NetLiteral(NetScope*sc, perm_string n, const verireal&val)
: NetNode(sc, n, 1), real_(val)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"), 0);
}
NetLiteral::~NetLiteral()
{
}
ivl_variable_type_t NetLiteral::data_type() const
{
return IVL_VT_REAL;
}
const verireal& NetLiteral::value_real() const
{
return real_;
@@ -1492,9 +1506,12 @@ NetMult::NetMult(NetScope*sc, perm_string n, unsigned wr,
: NetNode(sc, n, 3),
signed_(false), width_r_(wr), width_a_(wa), width_b_(wb)
{
pin(0).set_dir(Link::OUTPUT); // Result
pin(1).set_dir(Link::INPUT); // DataA
pin(2).set_dir(Link::INPUT); // DataB
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Result"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("DataA"), 0);
pin(2).set_dir(Link::INPUT);
pin(2).set_name(perm_string::literal("DataB"), 0);
}
NetMult::~NetMult()
@@ -1561,9 +1578,12 @@ NetPow::NetPow(NetScope*sc, perm_string n, unsigned wr,
: NetNode(sc, n, 3),
signed_(false), width_r_(wr), width_a_(wa), width_b_(wb)
{
pin(0).set_dir(Link::OUTPUT); // Result
pin(1).set_dir(Link::INPUT); // DataA
pin(2).set_dir(Link::INPUT); // DataB
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Result"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("DataA"), 0);
pin(2).set_dir(Link::INPUT);
pin(2).set_name(perm_string::literal("DataB"), 0);
}
NetPow::~NetPow()
@@ -1638,11 +1658,14 @@ NetMux::NetMux(NetScope*s, perm_string n,
: NetNode(s, n, 2+si),
width_(wi), size_(si), swidth_(sw)
{
pin(0).set_dir(Link::OUTPUT); // Q
pin(1).set_dir(Link::INPUT); // Sel
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Q"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("Sel"), 0);
for (unsigned idx = 0 ; idx < size_ ; idx += 1) {
pin_Data(idx).set_dir(Link::INPUT); // Data[idx]
pin_Data(idx).set_dir(Link::INPUT);
pin_Data(idx).set_name(perm_string::literal("D"), idx);
}
}
@@ -1702,6 +1725,8 @@ NetSignExtend::NetSignExtend(NetScope*s, perm_string n, unsigned w)
{
pin(0).set_dir(Link::OUTPUT);
pin(1).set_dir(Link::INPUT);
pin(0).set_name(perm_string::literal("O"), 0);
pin(1).set_name(perm_string::literal("I"), 0);
}
NetSignExtend::~NetSignExtend()
@@ -1718,6 +1743,8 @@ NetBUFZ::NetBUFZ(NetScope*s, perm_string n, unsigned w)
{
pin(0).set_dir(Link::OUTPUT);
pin(1).set_dir(Link::INPUT);
pin(0).set_name(perm_string::literal("O"), 0);
pin(1).set_name(perm_string::literal("I"), 0);
}
NetBUFZ::~NetBUFZ()
@@ -1729,12 +1756,12 @@ unsigned NetBUFZ::width() const
return width_;
}
NetCaseCmp::NetCaseCmp(NetScope*s, perm_string n, unsigned wid, bool eeq__)
: NetNode(s, n, 3), width_(wid), eeq_(eeq__)
NetCaseCmp::NetCaseCmp(NetScope*s, perm_string n, unsigned wid, bool eeq)
: NetNode(s, n, 3), width_(wid), eeq_(eeq)
{
pin(0).set_dir(Link::OUTPUT);
pin(1).set_dir(Link::INPUT);
pin(2).set_dir(Link::INPUT);
pin(0).set_dir(Link::OUTPUT); pin(0).set_name(perm_string::literal("O"),0);
pin(1).set_dir(Link::INPUT); pin(1).set_name(perm_string::literal("I"),0);
pin(2).set_dir(Link::INPUT); pin(2).set_name(perm_string::literal("I"),1);
}
NetCaseCmp::~NetCaseCmp()
@@ -1793,6 +1820,7 @@ NetConst::NetConst(NetScope*s, perm_string n, verinum::V v)
: NetNode(s, n, 1), width_(1)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"), 0);
value_ = new verinum::V[1];
value_[0] = v;
}
@@ -1801,6 +1829,7 @@ NetConst::NetConst(NetScope*s, perm_string n, const verinum&val)
: NetNode(s, n, 1), width_(val.len())
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"), 0);
value_ = new verinum::V[width_];
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
value_[idx] = val.get(idx);
@@ -1831,7 +1860,12 @@ NetFuncDef::NetFuncDef(NetScope*s, NetNet*result, const svector<NetNet*>&po)
NetFuncDef::~NetFuncDef()
{
}
#if 0
const string NetFuncDef::name() const
{
return scope_->name();
}
#endif
const NetScope* NetFuncDef::scope() const
{
return scope_;
@@ -1955,50 +1989,17 @@ NetUTask::NetUTask(NetScope*def)
NetUTask::~NetUTask()
{
}
#if 0
const string NetUTask::name() const
{
return task_->name();
}
#endif
const NetScope* NetUTask::task() const
{
return task_;
}
NetAlloc::NetAlloc(NetScope*scope__)
: scope_(scope__)
{
}
NetAlloc::~NetAlloc()
{
}
#if 0
const string NetAlloc::name() const
{
return scope_->name();
}
#endif
const NetScope* NetAlloc::scope() const
{
return scope_;
}
NetFree::NetFree(NetScope*scope__)
: scope_(scope__)
{
}
NetFree::~NetFree()
{
}
#if 0
const string NetFree::name() const
{
return scope_->name();
}
#endif
const NetScope* NetFree::scope() const
{
return scope_;
}
NetExpr::NetExpr(unsigned w)
: width_(w), signed_flag_(false)
{
@@ -2018,13 +2019,6 @@ void NetExpr::cast_signed(bool flag)
signed_flag_ = flag;
}
void NetExpr::expr_width(unsigned w)
{
// Catch underflow wrap errors.
ivl_assert(*this, w < (UINT_MAX - 256));
width_ = w;
}
bool NetExpr::has_width() const
{
return true;
@@ -2037,8 +2031,8 @@ bool NetExpr::has_width() const
* be. However, if we don't, our default will be the width of the
* largest operand.
*/
NetEBBits::NetEBBits(char op__, NetExpr*l, NetExpr*r)
: NetEBinary(op__, l, r)
NetEBBits::NetEBBits(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
if (r->expr_width() > l->expr_width())
expr_width(r->expr_width());
@@ -2057,12 +2051,9 @@ NetEBBits* NetEBBits::dup_expr() const
return result;
}
NetEBinary::NetEBinary(char op__, NetExpr*l, NetExpr*r)
: op_(op__), left_(l), right_(r)
NetEBinary::NetEBinary(char op, NetExpr*l, NetExpr*r)
: op_(op), left_(l), right_(r)
{
// Binary expressions of all sorts are signed if both the
// arguments are signed.
cast_signed_base_( left_->has_sign() && right_->has_sign());
}
NetEBinary::~NetEBinary()
@@ -2082,8 +2073,8 @@ NetEBinary* NetEBinary::dup_expr() const
return 0;
}
NetEBLogic::NetEBLogic(char op__, NetExpr*l, NetExpr*r)
: NetEBinary(op__, l, r)
NetEBLogic::NetEBLogic(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
expr_width(1);
}
@@ -2281,8 +2272,6 @@ const NetExpr* NetETernary::false_expr() const
ivl_variable_type_t NetETernary::expr_type() const
{
ivl_assert(*this, true_val_);
ivl_assert(*this, false_val_);
ivl_variable_type_t tru = true_val_->expr_type();
ivl_variable_type_t fal = false_val_->expr_type();
if (tru == IVL_VT_LOGIC && fal == IVL_VT_BOOL)
@@ -2304,8 +2293,8 @@ ivl_variable_type_t NetETernary::expr_type() const
return tru;
}
NetEUnary::NetEUnary(char op__, NetExpr*ex)
: NetExpr(ex->expr_width()), op_(op__), expr_(ex)
NetEUnary::NetEUnary(char op, NetExpr*ex)
: NetExpr(ex->expr_width()), op_(op), expr_(ex)
{
switch (op_) {
case '!':
@@ -2333,8 +2322,8 @@ ivl_variable_type_t NetEUnary::expr_type() const
return expr_->expr_type();
}
NetEUBits::NetEUBits(char op__, NetExpr*ex)
: NetEUnary(op__, ex)
NetEUBits::NetEUBits(char op, NetExpr*ex)
: NetEUnary(op, ex)
{
}
@@ -2347,8 +2336,8 @@ ivl_variable_type_t NetEUBits::expr_type() const
return expr_->expr_type();
}
NetEUReduce::NetEUReduce(char op__, NetExpr*ex)
: NetEUnary(op__, ex)
NetEUReduce::NetEUReduce(char op, NetExpr*ex)
: NetEUnary(op, ex)
{
expr_width(1);
}
@@ -2367,8 +2356,10 @@ NetLogic::NetLogic(NetScope*s, perm_string n, unsigned pins,
: NetNode(s, n, pins), type_(t), width_(wid)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"), 0);
for (unsigned idx = 1 ; idx < pins ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("I"), idx-1);
}
}
@@ -2382,12 +2373,14 @@ unsigned NetLogic::width() const
return width_;
}
NetUReduce::NetUReduce(NetScope*scope__, perm_string n,
NetUReduce::NetUReduce(NetScope*scope, perm_string n,
NetUReduce::TYPE t, unsigned wid)
: NetNode(scope__, n, 2), type_(t), width_(wid)
: NetNode(scope, n, 2), type_(t), width_(wid)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"));
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("I"));
}
NetUReduce::TYPE NetUReduce::type() const
@@ -2559,7 +2552,6 @@ DelayType NetBlock::delay_type() const
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;
@@ -2594,9 +2586,7 @@ DelayType NetCondit::delay_type() const
if (else_) {
result = combine_delays(if_->delay_type(), else_->delay_type());
} else {
/* Because of the indeterminate conditional value the
* best we can have for this case is a possible delay. */
result = combine_delays(if_->delay_type(), NO_DELAY);
result = if_->delay_type();
}
return result;
+82 -318
View File
@@ -29,8 +29,6 @@
# include <map>
# include <list>
# include <vector>
# include <set>
# include <utility>
# include "ivl_target.h"
# include "pform_types.h"
# include "config.h"
@@ -68,7 +66,6 @@ class NetTaskDef;
class NetEvTrig;
class NetEvWait;
class nature_t;
struct target;
struct functor_t;
@@ -77,24 +74,6 @@ ostream& operator << (ostream&o, ivl_variable_type_t val);
extern void join_island(NetObj*obj);
class NetPins : public LineInfo {
public:
explicit NetPins(unsigned npins);
virtual ~NetPins();
unsigned pin_count() const { return npins_; }
Link&pin(unsigned idx);
const Link&pin(unsigned idx) const;
void dump_node_pins(ostream&, unsigned, const char**pin_names =0) const;
private:
Link*pins_;
const unsigned npins_;
};
/* =========
* A NetObj is anything that has any kind of behavior in the
* netlist. Nodes can be gates, registers, etc. and are linked
@@ -115,7 +94,7 @@ class NetPins : public LineInfo {
* interpretation of the rise/fall/decay times is typically left to
* the target to properly interpret.
*/
class NetObj : public NetPins, public Attrib {
class NetObj : public Attrib, public virtual LineInfo {
public:
public:
@@ -129,6 +108,8 @@ class NetObj : public NetPins, public Attrib {
perm_string name() const { return name_; }
unsigned pin_count() const { return npins_; }
const NetExpr* rise_time() const { return delay1_; }
const NetExpr* fall_time() const { return delay2_; }
const NetExpr* decay_time() const { return delay3_; }
@@ -137,11 +118,17 @@ class NetObj : public NetPins, public Attrib {
void fall_time(const NetExpr* d) { delay2_ = d; }
void decay_time(const NetExpr* d) { delay3_ = d; }
Link&pin(unsigned idx);
const Link&pin(unsigned idx) const;
void dump_node_pins(ostream&, unsigned) const;
void dump_obj_attr(ostream&, unsigned) const;
private:
NetScope*scope_;
perm_string name_;
Link*pins_;
const unsigned npins_;
const NetExpr* delay1_;
const NetExpr* delay2_;
const NetExpr* delay3_;
@@ -161,31 +148,11 @@ class IslandBranch {
struct ivl_island_s* island;
};
/*
* A NetBranch is a construct of Verilog-A that is a branch between
* two nodes. The branch has exactly 2 pins and a discipline.
*
* pin(0) is the source of flow through a branch and the plus side of
* potential. Pin(1) is the sink of flow and the minus (or ground) of
* potential.
*/
class NetBranch : public NetPins {
public:
explicit NetBranch(ivl_discipline_t dis);
explicit NetBranch(ivl_discipline_t dis, perm_string name);
~NetBranch();
private:
ivl_discipline_t discipline_;
perm_string name_;
};
class Link {
friend void connect(Link&, Link&);
friend void connect(Nexus*, Link&);
friend class NetPins;
friend class NetObj;
friend class Nexus;
public:
@@ -193,11 +160,9 @@ class Link {
enum strength_t { HIGHZ, WEAK, PULL, STRONG, SUPPLY };
private: // Only NetPins can create/delete Link objects
Link();
~Link();
public:
// Manipulate the link direction.
void set_dir(DIR d);
DIR get_dir() const;
@@ -211,10 +176,6 @@ class Link {
void drive0(strength_t);
void drive1(strength_t);
// This sets the drives for all drivers of this link, and not
// just the current link.
void drivers_drive(strength_t d0, strength_t d1);
strength_t drive0() const;
strength_t drive1() const;
@@ -225,8 +186,8 @@ class Link {
void set_init(verinum::V val);
verinum::V get_init() const;
void cur_link(NetPins*&net, unsigned &pin);
void cur_link(const NetPins*&net, unsigned &pin) const;
void cur_link(NetObj*&net, unsigned &pin);
void cur_link(const NetObj*&net, unsigned &pin) const;
// Get a pointer to the nexus that represents all the links
// connected to me.
@@ -253,23 +214,32 @@ class Link {
// Return information about the object that this link is
// a part of.
const NetPins*get_obj() const;
NetPins*get_obj();
const NetObj*get_obj() const;
NetObj*get_obj();
unsigned get_pin() const;
// A link of an object (sometimes called a "pin") has a
// name. It is convenient for the name to have a string and an
// integer part.
void set_name(perm_string, unsigned inst =0);
perm_string get_name() const;
unsigned get_inst() const;
private:
// The NetNode manages these. They point back to the
// NetNode so that following the links can get me here.
union {
NetPins *node_;
unsigned pin_;
};
NetObj *node_;
unsigned pin_;
bool pin_zero_ : 1;
DIR dir_ : 2;
strength_t drive0_ : 3;
strength_t drive1_ : 3;
verinum::V init_ : 2;
DIR dir_;
strength_t drive0_, drive1_;
verinum::V init_;
// These members name the pin of the link. If the name
// has width, then the inst_ member is the index of the
// pin.
perm_string name_;
unsigned inst_;
private:
Link *next_;
@@ -308,7 +278,6 @@ class Nexus {
verinum::V get_init() const;
void drivers_delays(NetExpr*rise, NetExpr*fall, NetExpr*decay);
void drivers_drive(Link::strength_t d0, Link::strength_t d1);
Link*first_nlink();
const Link* first_nlink()const;
@@ -319,10 +288,6 @@ class Nexus {
NetNet* pick_any_net();
/* This method returns true if there are any drivers
(including variables) attached to this nexus. */
bool drivers_present() const;
/* This method returns true if all the possible drivers of
this nexus are constant. It will also return true if there
are no drivers at all. */
@@ -553,10 +518,6 @@ class NetNet : public NetObj {
bool get_isint() const;
void set_isint(bool);
/* Attach a discipline to the net. */
ivl_discipline_t get_discipline() const;
void set_discipline(ivl_discipline_t dis);
/* These methods return the msb and lsb indices for the most
significant and least significant bits. These are signed
longs, and may be different from pin numbers. For example,
@@ -613,13 +574,17 @@ class NetNet : public NetObj {
virtual void dump_net(ostream&, unsigned) const;
private:
// The NetScope class uses this for listing signals.
friend class NetScope;
NetNet*sig_next_, *sig_prev_;
private:
Type type_;
PortType port_type_;
ivl_variable_type_t data_type_;
bool signed_;
bool isint_; // original type of integer
ivl_discipline_t discipline_;
long msb_, lsb_;
const unsigned dimensions_;
@@ -721,9 +686,6 @@ class NetScope : public Attrib {
unsigned get_def_lineno() const { return def_lineno_; };
bool in_func();
/* Is the task or function automatic. */
void is_auto(bool is_auto__) { is_auto_ = is_auto__; };
bool is_auto() const { return is_auto_; };
const NetTaskDef* task_def() const;
const NetFuncDef* func_def() const;
@@ -756,13 +718,8 @@ class NetScope : public Attrib {
const hname_t& fullname() const { return name_; }
void run_defparams(class Design*);
void run_defparams_later(class Design*);
void evaluate_parameters(class Design*);
// Look for defparams that never matched, and print warnings.
void residual_defparams(class Design*);
/* This method generates a non-hierarchical name that is
guaranteed to be unique within this scope. */
perm_string local_symbol();
@@ -780,8 +737,7 @@ class NetScope : public Attrib {
assignments from the scope pass to the parameter evaluation
step. After that, it is not used. */
list<pair<pform_name_t,NetExpr*> > defparams;
list<pair<list<hname_t>,NetExpr*> > defparams_later;
map<pform_name_t,NetExpr*>defparams;
public:
struct range_t {
@@ -829,7 +785,7 @@ class NetScope : public Attrib {
/* Module instance arrays are collected here for access during
the multiple elaboration passes. */
typedef vector<NetScope*> scope_vec_t;
typedef svector<NetScope*> scope_vec_t;
map<perm_string, scope_vec_t>instance_arrays;
/* Loop generate uses this as scratch space during
@@ -855,8 +811,7 @@ class NetScope : public Attrib {
NetNet::Type default_nettype_;
NetEvent *events_;
typedef std::map<perm_string,NetNet*>::const_iterator signals_map_iter_t;
std::map <perm_string,NetNet*> signals_map_;
NetNet *signals_;
perm_string module_name_;
union {
NetTaskDef*task_;
@@ -868,12 +823,11 @@ class NetScope : public Attrib {
NetScope*sub_;
unsigned lcounter_;
bool is_auto_;
};
/*
* This class implements the LPM_ABS component. The node has a single
* input, a signed expression, that it converts to the absolute
* input, a signe expression, that it converts to the absolute
* value. The gate is simple: pin(0) is the output and pin(1) is the input.
*/
class NetAbs : public NetNode {
@@ -907,7 +861,13 @@ class NetAddSub : public NetNode {
// operands and results).
unsigned width() const;
Link& pin_Aclr();
Link& pin_Add_Sub();
Link& pin_Clock();
Link& pin_Cin();
Link& pin_Cout();
Link& pin_Overflow();
Link& pin_DataA();
Link& pin_DataB();
Link& pin_Result();
@@ -956,44 +916,6 @@ class NetArrayDq : public NetNode {
};
/*
* Convert an IVL_VT_REAL input to a logical value with the
* given width. The input is pin(1) and the output is pin(0).
*/
class NetCastInt : public NetNode {
public:
NetCastInt(NetScope*s, perm_string n, unsigned width);
unsigned width() const { return width_; }
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
private:
unsigned width_;
};
/*
* Convert an input to IVL_VT_REAL. The input is pin(1), which can be
* any vector type (VT_BOOL or VT_LOGIC) and the output is pin(0),
* which is IVL_VT_REAL. The conversion interprets the input as an
* unsigned value unless the signed_flag is true.
*/
class NetCastReal : public NetNode {
public:
NetCastReal(NetScope*s, perm_string n, bool signed_flag);
bool signed_flag() const { return signed_flag_; }
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
private:
bool signed_flag_;
};
/*
* This type represents the LPM_CLSHIFT device.
*/
@@ -1035,9 +957,6 @@ class NetCLShift : public NetNode {
* inputs is narrower then the other, it is up to the generator to
* make sure all the data pins are properly driven.
*
* The signed() property is true if the comparison is to be done to
* signed arguments. The result is always UNsigned.
*
* NOTE: This is not the same as the device used to support case
* compare. Case comparisons handle Vx and Vz values, whereas this
* device need not.
@@ -1053,6 +972,8 @@ class NetCompare : public NetNode {
bool get_signed() const;
void set_signed(bool);
Link& pin_Aclr();
Link& pin_Clock();
Link& pin_AGB();
Link& pin_AGEB();
Link& pin_AEB();
@@ -1063,6 +984,8 @@ class NetCompare : public NetNode {
Link& pin_DataA();
Link& pin_DataB();
const Link& pin_Aclr() const;
const Link& pin_Clock() const;
const Link& pin_AGB() const;
const Link& pin_AGEB() const;
const Link& pin_AEB() const;
@@ -1177,9 +1100,6 @@ class NetModulo : public NetNode {
unsigned width_a() const;
unsigned width_b() const;
void set_signed(bool);
bool get_signed() const;
Link& pin_DataA();
Link& pin_DataB();
Link& pin_Result();
@@ -1196,8 +1116,6 @@ class NetModulo : public NetNode {
unsigned width_r_;
unsigned width_a_;
unsigned width_b_;
bool signed_flag_;
};
/*
@@ -1461,7 +1379,7 @@ class NetSysFunc : public NetNode {
class NetTran : public NetNode, public IslandBranch {
public:
// Tran devices other than TRAN_VP
// Tran devices other then TRAN_VP
NetTran(NetScope*scope, perm_string n, ivl_switch_type_t type);
// Create a TRAN_VP
NetTran(NetScope*scope, perm_string n, unsigned wid,
@@ -1567,20 +1485,12 @@ class NetExpr : public LineInfo {
virtual NexusSet* nex_input(bool rem_out = true) =0;
// Return a version of myself that is structural. This is used
// for converting expressions to gates. The arguments are:
//
// des, scope: The context where this work is done
//
// rise/fall/decay: Attach these delays to the driver for the
// expression output.
//
// drive0/drive1: Attach these strengths tp the driver for
// the expression output.
virtual NetNet*synthesize(Design*des, NetScope*scope);
// for converting expressions to gates.
virtual NetNet*synthesize(Design*);
protected:
void expr_width(unsigned w);
void expr_width(unsigned w) { width_ = w; }
void cast_signed_base_(bool flag) {signed_flag_ = flag; }
private:
@@ -1614,7 +1524,7 @@ class NetEConst : public NetExpr {
virtual void dump(ostream&) const;
virtual NetEConst* dup_expr() const;
virtual NetNet*synthesize(Design*, NetScope*scope);
virtual NetNet*synthesize(Design*);
virtual NexusSet* nex_input(bool rem_out = true);
private:
@@ -1631,7 +1541,7 @@ class NetEConstParam : public NetEConst {
perm_string name() const;
const NetScope*scope() const;
virtual bool set_width(unsigned w, bool last_chance =false);
virtual bool set_width(unsigned w, bool last_chance);
virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const;
@@ -1667,7 +1577,7 @@ class NetECReal : public NetExpr {
virtual void dump(ostream&) const;
virtual NetECReal* dup_expr() const;
virtual NetNet*synthesize(Design*, NetScope*scope);
virtual NetNet*synthesize(Design*);
virtual NexusSet* nex_input(bool rem_out = true);
private:
@@ -2085,23 +1995,6 @@ class NetProc : public virtual LineInfo {
NetProc& operator= (const NetProc&);
};
class NetAlloc : public NetProc {
public:
NetAlloc(NetScope*);
~NetAlloc();
const string name() const;
const NetScope* scope() const;
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
private:
NetScope*scope_;
};
/*
* Procedural assignment is broken into a suite of classes. These
* classes represent the various aspects of the assignment statement
@@ -2155,7 +2048,6 @@ class NetAssign_ {
// method accounts for the presence of the mux, so it is not
// necessarily the same as the pin_count().
unsigned lwidth() const;
ivl_variable_type_t expr_type() const;
// Get the name of the underlying object.
perm_string name() const;
@@ -2247,8 +2139,7 @@ class NetAssign : public NetAssignBase {
class NetAssignNB : public NetAssignBase {
public:
explicit NetAssignNB(NetAssign_*lv, NetExpr*rv, NetEvWait*ev,
NetExpr*cnt);
explicit NetAssignNB(NetAssign_*lv, NetExpr*rv);
~NetAssignNB();
@@ -2256,13 +2147,7 @@ class NetAssignNB : public NetAssignBase {
virtual int match_proc(struct proc_match_t*);
virtual void dump(ostream&, unsigned ind) const;
unsigned nevents() const;
const NetEvent*event(unsigned) const;
const NetExpr* get_count() const;
private:
NetEvWait*event_;
NetExpr*count_;
};
/*
@@ -2434,24 +2319,6 @@ class NetCondit : public NetProc {
NetProc*else_;
};
/*
* This represents the analog contribution statement. The l-val is a
* branch expression, and the r-value is an arbitrary expression that
* may include branches and real values.
*/
class NetContribution : public NetProc {
public:
explicit NetContribution(NetExpr*lval, NetExpr*rval);
~NetContribution();
virtual void dump(ostream&, unsigned ind) const;
private:
NetExpr*lval_;
NetExpr*rval_;
};
/*
* The procedural deassign statement (the opposite of assign) releases
* any assign expressions attached to the bits of the reg. The
@@ -2662,8 +2529,6 @@ class NetEvWait : public NetProc {
const svector<NetEvProbe*>&events);
virtual void dump(ostream&, unsigned ind) const;
// This will ignore any statement.
virtual void dump_inline(ostream&) const;
virtual DelayType delay_type() const;
private:
@@ -2673,8 +2538,6 @@ class NetEvWait : public NetProc {
NetEvent**events_;
};
ostream& operator << (ostream&out, const NetEvWait&obj);
class NetEvProbe : public NetNode {
friend class NetEvent;
@@ -2740,23 +2603,6 @@ class NetForever : public NetProc {
NetProc*statement_;
};
class NetFree : public NetProc {
public:
NetFree(NetScope*);
~NetFree();
const string name() const;
const NetScope* scope() const;
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
private:
NetScope*scope_;
};
/*
* A function definition is elaborated just like a task, though by now
* it is certain that the first parameter (a phantom parameter) is the
@@ -2968,7 +2814,7 @@ class NetEUFunc : public NetExpr {
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetEUFunc*dup_expr() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NetNet* synthesize(Design*des, NetScope*scope);
virtual NetNet* synthesize(Design*des);
private:
NetScope*scope_;
@@ -2981,27 +2827,6 @@ class NetEUFunc : public NetExpr {
NetEUFunc& operator= (const NetEUFunc&);
};
/*
* A call to a nature access function for a branch.
*/
class NetEAccess : public NetExpr {
public:
explicit NetEAccess(NetBranch*br, nature_t*nat);
~NetEAccess();
virtual ivl_variable_type_t expr_type() const;
virtual void dump(ostream&) const;
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetEAccess*dup_expr() const;
virtual NexusSet* nex_input(bool rem_out = true);
private:
NetBranch*branch_;
nature_t*nature_;
};
/*
* A call to a user defined task is elaborated into this object. This
* contains a pointer to the elaborated task definition, but is a
@@ -3062,10 +2887,12 @@ class NetWhile : public NetProc {
class NetProcTop : public LineInfo, public Attrib {
public:
NetProcTop(NetScope*s, ivl_process_type_t t, class NetProc*st);
enum Type { KINITIAL, KALWAYS };
NetProcTop(NetScope*s, Type t, class NetProc*st);
~NetProcTop();
ivl_process_type_t type() const { return type_; }
Type type() const { return type_; }
NetProc*statement();
const NetProc*statement() const;
@@ -3090,7 +2917,7 @@ class NetProcTop : public LineInfo, public Attrib {
bool emit(struct target_t*tgt) const;
private:
const ivl_process_type_t type_;
const Type type_;
NetProc*const statement_;
NetScope*scope_;
@@ -3098,32 +2925,6 @@ class NetProcTop : public LineInfo, public Attrib {
NetProcTop*next_;
};
class NetAnalogTop : public LineInfo, public Attrib {
public:
NetAnalogTop(NetScope*scope, ivl_process_type_t t, NetProc*st);
~NetAnalogTop();
ivl_process_type_t type() const { return type_; }
NetProc*statement();
const NetProc*statement() const;
NetScope*scope();
const NetScope*scope() const;
void dump(ostream&, unsigned ind) const;
bool emit(struct target_t*tgt) const;
private:
const ivl_process_type_t type_;
NetProc* statement_;
NetScope*scope_;
friend class Design;
NetAnalogTop*next_;
};
/*
* This class represents a binary operator, with the left and right
* operands and a single character for the operator. The operator
@@ -3207,7 +3008,7 @@ class NetEBAdd : public NetEBinary {
virtual bool set_width(unsigned w, bool last_chance);
virtual NetEBAdd* dup_expr() const;
virtual NetExpr* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*, NetScope*scope);
virtual NetNet* synthesize(Design*);
private:
NetECReal* eval_tree_real_();
@@ -3229,7 +3030,7 @@ class NetEBDiv : public NetEBinary {
virtual bool set_width(unsigned w, bool last_chance);
virtual NetEBDiv* dup_expr() const;
virtual NetExpr* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*, NetScope*scope);
virtual NetNet* synthesize(Design*);
};
/*
@@ -3256,7 +3057,7 @@ class NetEBBits : public NetEBinary {
virtual NetEBBits* dup_expr() const;
virtual NetEConst* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*, NetScope*scope);
virtual NetNet* synthesize(Design*);
};
/*
@@ -3279,7 +3080,7 @@ class NetEBComp : public NetEBinary {
NetEBComp(char op, NetExpr*l, NetExpr*r);
~NetEBComp();
virtual bool set_width(unsigned w, bool last_chance =false);
virtual bool set_width(unsigned w, bool last_chance);
/* A compare expression has a definite width. */
virtual bool has_width() const;
@@ -3287,13 +3088,12 @@ class NetEBComp : public NetEBinary {
virtual NetEBComp* dup_expr() const;
virtual NetEConst* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*, NetScope*scope);
virtual NetNet* synthesize(Design*);
private:
NetEConst* must_be_leeq_(NetExpr*le, const verinum&rv, bool eq_flag);
NetEConst*eval_eqeq_(bool ne_flag);
NetEConst*eval_eqeq_real_(NetExpr*le, NetExpr*ri, bool ne_flag);
NetEConst*eval_less_();
NetEConst*eval_leeq_();
NetEConst*eval_leeq_real_(NetExpr*le, NetExpr*ri, bool eq_flag);
@@ -3316,10 +3116,10 @@ class NetEBLogic : public NetEBinary {
NetEBLogic(char op, NetExpr*l, NetExpr*r);
~NetEBLogic();
virtual bool set_width(unsigned w, bool last_chance =false);
virtual bool set_width(unsigned w, bool last_chance);
virtual NetEBLogic* dup_expr() const;
virtual NetEConst* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*, NetScope*scope);
virtual NetNet* synthesize(Design*);
private:
};
@@ -3357,7 +3157,7 @@ class NetEBMult : public NetEBinary {
virtual bool set_width(unsigned w, bool last_chance);
virtual NetEBMult* dup_expr() const;
virtual NetExpr* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*, NetScope*scope);
virtual NetNet* synthesize(Design*);
private:
@@ -3379,7 +3179,7 @@ class NetEBPow : public NetEBinary {
virtual bool set_width(unsigned w, bool last_chance);
virtual NetEBPow* dup_expr() const;
virtual NetExpr* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*, NetScope*scope);
virtual NetNet* synthesize(Design*);
private:
@@ -3411,7 +3211,7 @@ class NetEBShift : public NetEBinary {
virtual NetEBShift* dup_expr() const;
virtual NetEConst* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*, NetScope*scope);
virtual NetNet* synthesize(Design*);
private:
};
@@ -3445,7 +3245,7 @@ class NetEConcat : public NetExpr {
virtual bool set_width(unsigned w, bool last_chance =false);
virtual NetEConcat* dup_expr() const;
virtual NetEConst* eval_tree(int prune_to_width = -1);
virtual NetNet*synthesize(Design*, NetScope*scope);
virtual NetNet*synthesize(Design*);
virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const;
@@ -3521,7 +3321,7 @@ class NetESelect : public NetExpr {
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetEConst* eval_tree(int prune_to_width = -1);
virtual NetESelect* dup_expr() const;
virtual NetNet*synthesize(Design*des, NetScope*scope);
virtual NetNet*synthesize(Design*des);
virtual void dump(ostream&) const;
private:
@@ -3592,8 +3392,6 @@ class NetESFunc : public NetExpr {
NetExpr* parm(unsigned idx);
const NetExpr* parm(unsigned idx) const;
virtual NetExpr* eval_tree(int prune_to_width = -1);
virtual ivl_variable_type_t expr_type() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual bool set_width(unsigned, bool last_chance);
@@ -3601,7 +3399,7 @@ class NetESFunc : public NetExpr {
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetESFunc*dup_expr() const;
virtual NetNet*synthesize(Design*, NetScope*scope);
virtual NetNet*synthesize(Design*);
private:
const char* name_;
@@ -3638,10 +3436,7 @@ class NetETernary : public NetExpr {
virtual NexusSet* nex_input(bool rem_out = true);
virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const;
virtual NetNet*synthesize(Design*, NetScope*scope);
public:
static bool test_operand_compat(ivl_variable_type_t tru, ivl_variable_type_t fal);
virtual NetNet*synthesize(Design*);
private:
NetExpr*cond_;
@@ -3678,7 +3473,6 @@ class NetEUnary : public NetExpr {
virtual NetEUnary* dup_expr() const;
virtual NetExpr* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*, NetScope*scope);
virtual ivl_variable_type_t expr_type() const;
virtual NexusSet* nex_input(bool rem_out = true);
@@ -3699,9 +3493,8 @@ class NetEUBits : public NetEUnary {
NetEUBits(char op, NetExpr*ex);
~NetEUBits();
virtual NetNet* synthesize(Design*, NetScope*scope);
virtual NetNet* synthesize(Design*);
virtual NetEUBits* dup_expr() const;
virtual NetExpr* eval_tree(int prune_to_width = -1);
virtual ivl_variable_type_t expr_type() const;
};
@@ -3713,7 +3506,7 @@ class NetEUReduce : public NetEUnary {
~NetEUReduce();
virtual bool set_width(unsigned w, bool last_chance);
virtual NetNet* synthesize(Design*, NetScope*scope);
virtual NetNet* synthesize(Design*);
virtual NetEUReduce* dup_expr() const;
virtual NetEConst* eval_tree(int prune_to_width = -1);
virtual ivl_variable_type_t expr_type() const;
@@ -3740,7 +3533,7 @@ class NetESignal : public NetExpr {
virtual bool set_width(unsigned, bool last_chance);
virtual NetESignal* dup_expr() const;
NetNet* synthesize(Design*des, NetScope*scope);
NetNet* synthesize(Design*des);
NexusSet* nex_input(bool rem_out = true);
// This is the expression for selecting an array word, if this
@@ -3767,18 +3560,6 @@ class NetESignal : public NetExpr {
NetExpr*word_;
};
/*
* The Design object keeps a list of work items for processing
* elaboration. This is the type of those work items.
*/
struct elaborator_work_item_t {
explicit elaborator_work_item_t(Design*d)
: des(d) { }
virtual ~elaborator_work_item_t() { }
virtual void elaborate_runrun() =0;
protected:
Design*des;
};
/*
* This class contains an entire design. It includes processes and a
@@ -3828,23 +3609,10 @@ class Design {
NetScope* find_scope(NetScope*, const std::list<hname_t>&path,
NetScope::TYPE type = NetScope::MODULE) const;
/* These members help manage elaboration of scopes. When we
get to a point in scope elaboration where we want to put
off a scope elaboration, an object of scope_elaboration_t
is pushed onto the scope_elaborations list. The scope
elaborator will go through this list elaborating scopes
until the list is empty. */
list<elaborator_work_item_t*>elaboration_work_list;
void run_elaboration_work(void);
set<NetScope*> defparams_later;
// PARAMETERS
void run_defparams();
void evaluate_parameters();
// Look for defparams that never matched, and print warnings.
void residual_defparams();
/* This method locates a signal, starting at a given
scope. The name parameter may be partially hierarchical, so
@@ -3865,9 +3633,7 @@ class Design {
// PROCESSES
void add_process(NetProcTop*);
void add_process(NetAnalogTop*);
void delete_process(NetProcTop*);
bool check_always_delay() const;
// Iterate over the design...
void dump(ostream&) const;
@@ -3897,8 +3663,6 @@ class Design {
NetProcTop*procs_;
NetProcTop*procs_idx_;
NetAnalogTop*aprocs_;
map<string,const char*> flags_;
int des_precision_;
+39 -170
View File
@@ -76,86 +76,6 @@ NetNet* add_to_net(Design*des, NetNet*sig, long val)
#endif
}
NetNet* sub_net_from(Design*des, NetScope*scope, long val, NetNet*sig)
{
NetNet*zero_net = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, sig->vector_width());
zero_net->data_type(sig->data_type());
zero_net->local_flag(true);
if (sig->data_type() == IVL_VT_REAL) {
verireal zero (val);
NetLiteral*zero_obj = new NetLiteral(scope, scope->local_symbol(), zero);
des->add_node(zero_obj);
connect(zero_net->pin(0), zero_obj->pin(0));
} else {
verinum zero ((int64_t)val);
zero = pad_to_width(zero, sig->vector_width());
NetConst*zero_obj = new NetConst(scope, scope->local_symbol(), zero);
des->add_node(zero_obj);
connect(zero_net->pin(0), zero_obj->pin(0));
}
NetAddSub*adder = new NetAddSub(scope, scope->local_symbol(), sig->vector_width());
des->add_node(adder);
adder->attribute(perm_string::literal("LPM_Direction"), verinum("SUB"));
connect(zero_net->pin(0), adder->pin_DataA());
connect(adder->pin_DataB(), sig->pin(0));
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, sig->vector_width());
tmp->data_type(sig->data_type());
tmp->local_flag(true);
connect(adder->pin_Result(), tmp->pin(0));
return tmp;
}
NetNet* cast_to_int(Design*des, NetScope*scope, NetNet*src, unsigned wid)
{
if (src->data_type() != IVL_VT_REAL)
return src;
NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, wid);
tmp->data_type(IVL_VT_LOGIC);
tmp->set_line(*src);
tmp->local_flag(true);
NetCastInt*cast = new NetCastInt(scope, scope->local_symbol(), wid);
cast->set_line(*src);
des->add_node(cast);
connect(cast->pin(0), tmp->pin(0));
connect(cast->pin(1), src->pin(0));
return tmp;
}
NetNet* cast_to_real(Design*des, NetScope*scope, NetNet*src)
{
if (src->data_type() == IVL_VT_REAL)
return src;
NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE);
tmp->data_type(IVL_VT_REAL);
tmp->set_line(*src);
tmp->local_flag(true);
NetCastReal*cast = new NetCastReal(scope, scope->local_symbol(), src->get_signed());
cast->set_line(*src);
des->add_node(cast);
connect(cast->pin(0), tmp->pin(0));
connect(cast->pin(1), src->pin(0));
return tmp;
}
/*
* Add a signed constant to an existing expression. Generate a new
* NetEBAdd node that has the input expression and an expression made
@@ -210,27 +130,6 @@ NetEConst* make_const_x(unsigned long wid)
return resx;
}
NetEConst* make_const_0(unsigned long wid)
{
verinum xxx (verinum::V0, wid);
NetEConst*resx = new NetEConst(xxx);
return resx;
}
NetNet* make_const_x(Design*des, NetScope*scope, unsigned long wid)
{
verinum xxx (verinum::Vx, wid);
NetConst*res = new NetConst(scope, scope->local_symbol(), xxx);
des->add_node(res);
NetNet*sig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, wid);
sig->local_flag(true);
sig->data_type(IVL_VT_LOGIC);
connect(sig->pin(0), res->pin(0));
return sig;
}
NetExpr* condition_reduce(NetExpr*expr)
{
if (expr->expr_width() == 1)
@@ -305,57 +204,6 @@ bool eval_as_double(double&value, NetExpr*expr)
return false;
}
/*
* At the parser level, a name component is a name with a collection
* of expressions. For example foo[N] is the name "foo" and the index
* expression "N". This function takes as input the name component and
* returns the path component name. It will evaluate the index
* expression if it is present.
*/
hname_t eval_path_component(Design*des, NetScope*scope,
const name_component_t&comp)
{
// No index expression, so the path component is an undecorated
// name, for example "foo".
if (comp.index.empty())
return hname_t(comp.name);
// The parser will assure that path components will have only
// one index. For example, foo[N] is one index, foo[n][m] is two.
assert(comp.index.size() == 1);
const index_component_t&index = comp.index.front();
// The parser will assure that path components will have only
// bit select index expressions. For example, "foo[n]" is OK,
// but "foo[n:m]" is not.
assert(index.sel == index_component_t::SEL_BIT);
// Evaluate the bit select to get a number.
NetExpr*tmp = elab_and_eval(des, scope, index.msb, -1);
ivl_assert(*index.msb, tmp);
// Now we should have a constant value for the bit select
// expression, and we can use it to make the final hname_t
// value, for example "foo[5]".
if (NetEConst*ctmp = dynamic_cast<NetEConst*>(tmp)) {
hname_t res(comp.name, ctmp->value().as_long());
delete ctmp;
return res;
}
// Darn, the expression doesn't evaluate to a constant. That's
// an error to be reported. And make up a fake index value to
// return to the caller.
cerr << index.msb->get_fileline() << ": error: "
<< "Scope index expression is not constant: "
<< *index.msb << endl;
des->errors += 1;
delete tmp;
return hname_t (comp.name, 0);
}
std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
const pform_name_t&path)
{
@@ -365,7 +213,30 @@ std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
for (pform_path_it cur = path.begin() ; cur != path.end(); cur++) {
const name_component_t&comp = *cur;
res.push_back( eval_path_component(des,scope,comp) );
if (comp.index.empty()) {
res.push_back(hname_t(comp.name));
continue;
}
assert(comp.index.size() == 1);
const index_component_t&index = comp.index.front();
assert(index.sel == index_component_t::SEL_BIT);
NetExpr*tmp = elab_and_eval(des, scope, index.msb, -1);
ivl_assert(*index.msb, tmp);
if (NetEConst*ctmp = dynamic_cast<NetEConst*>(tmp)) {
res.push_back(hname_t(comp.name, ctmp->value().as_long()));
delete ctmp;
continue;
} else {
cerr << index.msb->get_fileline() << ": error: "
<< "Scope index expression is not constant: "
<< *index.msb << endl;
des->errors += 1;
}
return res;
}
return res;
@@ -378,28 +249,26 @@ const char *human_readable_op(const char op)
{
const char *type;
switch (op) {
case '~': type = "~"; break; // Negation
case '~': type = "~"; break; // Negation
case '^': type = "^"; break; // XOR
case 'X': type = "~^"; break; // XNOR
case '&': type = "&"; break; // Bitwise AND
case 'A': type = "~&"; break; // NAND (~&)
case '|': type = "|"; break; // Bitwise OR
case 'O': type = "~|"; break; // NOR
case '^': type = "^"; break; // XOR
case 'X': type = "~^"; break; // XNOR
case '&': type = "&"; break; // Bitwise AND
case 'A': type = "~&"; break; // NAND (~&)
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 'a': type = "&&"; break; // Logical AND
case 'o': type = "||"; break; // Logical OR
case 'E': type = "==="; break; // Case equality
case 'N': type = "!=="; break; // Case inequality
case 'E': type = "==="; break; // Case equality
case 'N': type = "!=="; break; // Case inequality
case 'l': type = "<<(<)"; break; // Left shifts
case 'r': type = ">>"; break; // Logical right shift
case 'R': type = ">>>"; break; // Arithmetic right shift
case 'l': type = "<<(<)"; break; // Left shifts
case 'r': type = ">>"; break; // Logical right shift
case 'R': type = ">>>"; break; // Arithmetic right shift
default:
assert(0);
default: assert(0);
}
return type;
}
+8 -56
View File
@@ -36,25 +36,21 @@
* ex2 is the lsb expression for the range. If there is no range, then
* these values are set to 0.
*/
extern NetScope* symbol_search(const LineInfo*li,
Design*des,
NetScope*start,
pform_name_t path,
extern NetScope* symbol_search(Design*des,
NetScope*start, pform_name_t path,
NetNet*&net, /* net/reg */
const NetExpr*&par,/* parameter */
NetEvent*&eve, /* named event */
const NetExpr*&ex1, const NetExpr*&ex2);
inline NetScope* symbol_search(const LineInfo*li,
Design*des,
NetScope*start,
const pform_name_t&path,
inline NetScope* symbol_search(Design*des,
NetScope*start, const pform_name_t&path,
NetNet*&net, /* net/reg */
const NetExpr*&par,/* parameter */
NetEvent*&eve /* named event */)
{
const NetExpr*ex1, *ex2;
return symbol_search(li, des, start, path, net, par, eve, ex1, ex2);
return symbol_search(des, start, path, net, par, eve, ex1, ex2);
}
/*
@@ -68,13 +64,6 @@ extern NetNet*pad_to_width(Design*des, NetNet*n, unsigned w);
extern NetNet*pad_to_width_signed(Design*des, NetNet*n, unsigned w);
/*
* Generate the nodes necessary to cast an expression (a net) to a
* real value.
*/
extern NetNet*cast_to_int(Design*des, NetScope*scope, NetNet*src, unsigned wid);
extern NetNet*cast_to_real(Design*des, NetScope*scope, NetNet*src);
/*
* Take the input expression and return a variation that assures that
* the expression is 1-bit wide and logical. This reflects the needs
@@ -95,7 +84,6 @@ extern NetNet*crop_to_width(Design*des, NetNet*n, unsigned w);
* return a new NetNet value that is the output of an addition.
*/
extern NetNet*add_to_net(Design*des, NetNet*sig, long val);
extern NetNet*sub_net_from(Design*des, NetScope*scope, long val, NetNet*sig);
/*
* These functions make various sorts of expressions, given operands
@@ -118,12 +106,6 @@ extern NetExpr*make_sub_expr(long val, NetExpr*expr);
* Make a NetEConst object that contains only X bits.
*/
extern NetEConst*make_const_x(unsigned long wid);
extern NetEConst*make_const_0(unsigned long wid);
/*
* Make A const net
*/
extern NetNet* make_const_x(Design*des, NetScope*scope, unsigned long wid);
/*
* In some cases the lval is accessible as a pointer to the head of
@@ -141,27 +123,14 @@ extern unsigned count_lval_width(const class NetAssign_*first);
* The expr_width is the width of the context where the expression is
* being elaborated, or -1 if the expression is self-determined width.
*
* The prune_width is the maximum width of the result, and is passed
* to the eval_tree method of the expression to limit constant
* results. The evaluation will prune any constant result down to the
* prune_width (if >0) so should only be used at the point where it is
* bound to the destination.
* Also, the prune_width is the maximum width of the result, and it
* passed to the eval_tree method of the expression to limit constant
* results if possible.
*/
class PExpr;
extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
const PExpr*pe, int expr_wid,
int prune_width =-1);
/*
* This function elaborates an expression as if it is for the r-value
* of an assignment, The data_type_lv and expr_wid_lv are the type and
* with of the l-value, and the expr is the expression to
* elaborate. The result is the NetExpr elaborated and evaluated.
* (See elab_expr.cc)
*/
extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
ivl_variable_type_t data_type_lv,
int expr_wid_lv, PExpr*expr);
/*
* This procedure elaborates an expression and if the elaboration is
* successful the original expression is replaced with the new one.
@@ -176,26 +145,9 @@ void eval_expr(NetExpr*&expr, int prune_width =-1);
bool eval_as_long(long&value, NetExpr*expr);
bool eval_as_double(double&value, NetExpr*expr);
/*
* Evaluate the component of a scope path to get an hname_t value. Do
* the evaluation in the context of the given scope.
*/
extern hname_t eval_path_component(Design*des, NetScope*scope,
const name_component_t&comp);
/*
* Evaluate an entire scope path in the context of the given scope.
*/
extern std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
const pform_name_t&path);
/*
* Return true if the data type is a type that is normally available
* in vector for. IVL_VT_BOOL and IVL_VT_LOGIC are vectorable,
* IVL_VT_REAL is not.
*/
extern bool type_is_vectorable(ivl_variable_type_t type);
/*
* Return a human readable version of the operator.
*/
+55 -82
View File
@@ -37,18 +37,14 @@ class nodangle_f : public functor_t {
void event(Design*des, NetEvent*ev);
void signal(Design*des, NetNet*sig);
unsigned iteration;
unsigned count_;
unsigned stotal, etotal;
bool scontinue, econtinue;
bool scomplete, ecomplete;
};
void nodangle_f::event(Design*des, NetEvent*ev)
{
if (ecomplete) return;
/* If there are no references to this event, then go right
ahead and delete it. There is no use looking further at
ahead and delete in. There is no use looking further at
it. */
if ((ev->nwait() + ev->ntrig() + ev->nexpr()) == 0) {
delete ev;
@@ -56,79 +52,58 @@ void nodangle_f::event(Design*des, NetEvent*ev)
return;
}
if (iteration == 0) {
/* Try to remove duplicate probes from the event. This
is done as a separate initial pass to ensure similar
events are detected as soon as possible in subsequent
iterations. */
for (unsigned idx = 0 ; idx < ev->nprobe() ; idx += 1) {
unsigned jdx = idx + 1;
while (jdx < ev->nprobe()) {
NetEvProbe*ip = ev->probe(idx);
NetEvProbe*jp = ev->probe(jdx);
/* Try to remove duplicate probes from the event. */
for (unsigned idx = 0 ; idx < ev->nprobe() ; idx += 1) {
unsigned jdx = idx + 1;
while (jdx < ev->nprobe()) {
NetEvProbe*ip = ev->probe(idx);
NetEvProbe*jp = ev->probe(jdx);
if (ip->edge() != jp->edge()) {
jdx += 1;
continue;
}
if (ip->edge() != jp->edge()) {
jdx += 1;
continue;
}
bool fully_connected = true;
for (unsigned jpin = 0; jpin < jp->pin_count(); jpin += 1) {
unsigned ipin = 0;
bool connected_flag = false;
for (ipin = 0 ; ipin < ip->pin_count(); ipin += 1)
if (connected(ip->pin(ipin), jp->pin(jpin))) {
connected_flag = true;
break;
}
bool fully_connected = true;
for (unsigned jpin = 0; jpin < jp->pin_count(); jpin += 1) {
unsigned ipin = 0;
bool connected_flag = false;
for (ipin = 0 ; ipin < ip->pin_count(); ipin += 1)
if (connected(ip->pin(ipin), jp->pin(jpin))) {
connected_flag = true;
break;
}
if (!connected_flag) {
fully_connected = false;
break;
}
}
if (!connected_flag) {
fully_connected = false;
break;
}
}
if (fully_connected) {
delete jp;
} else {
jdx += 1;
}
}
}
econtinue = true;
} else {
/* Postpone examining events in an automatic scope until the
third (optional) pass. This will mean similar events are
biased towards being stored in static scopes. */
if (ev->scope()->is_auto()) {
if (iteration == 1) {
econtinue = true;
return;
}
} else {
if (iteration == 2) {
return;
}
}
/* Try to find all the events that are similar to me, and
replace their references with references to me. */
list<NetEvent*> match;
ev->find_similar_event(match);
for (list<NetEvent*>::iterator idx = match.begin()
; idx != match.end() ; idx ++) {
NetEvent*tmp = *idx;
assert(tmp != ev);
tmp ->replace_event(ev);
}
if (fully_connected) {
delete jp;
} else {
jdx += 1;
}
}
}
/* Try to find all the events that are similar to me, and
replace their references with references to me. */
list<NetEvent*> match;
ev->find_similar_event(match);
for (list<NetEvent*>::iterator idx = match.begin()
; idx != match.end() ; idx ++) {
NetEvent*tmp = *idx;
assert(tmp != ev);
tmp ->replace_event(ev);
}
}
void nodangle_f::signal(Design*des, NetNet*sig)
{
if (scomplete) return;
/* Cannot delete signals referenced in an expression
or an l-value. */
if (sig->get_refs() > 0)
@@ -199,7 +174,7 @@ void nodangle_f::signal(Design*des, NetNet*sig)
/* If every pin is connected to another significant signal,
then I can delete this one. */
if (significant_flags == sig->pin_count()) {
scontinue = true;
count_ += 1;
delete sig;
stotal += 1;
}
@@ -208,26 +183,23 @@ void nodangle_f::signal(Design*des, NetNet*sig)
void nodangle(Design*des)
{
nodangle_f fun;
fun.iteration = 0;
unsigned count_iterations = 0;
fun.stotal = 0;
fun.etotal = 0;
fun.scomplete = false;
fun.ecomplete = false;
do {
fun.scontinue = false;
fun.econtinue = false;
fun.count_ = 0;
des->functor(&fun);
fun.iteration += 1;
fun.scomplete = !fun.scontinue;
fun.ecomplete = !fun.econtinue;
count_iterations += 1;
if (verbose_flag) {
cout << " ... " << fun.iteration << " iterations"
cout << " ... " << count_iterations << " iterations"
<< " deleted " << fun.stotal << " dangling signals"
<< " and " << fun.etotal << " events." << endl;
<< " and " << fun.etotal << " events."
<< " (count=" << fun.count_ << ")" << endl;
}
} while (fun.scontinue || fun.econtinue);
} while (fun.count_ > 0);
}
@@ -313,3 +285,4 @@ void nodangle(Design*des)
* symbols generated by elaboration and other steps.
*
*/
-1
View File
@@ -88,7 +88,6 @@ NetNet*pad_to_width(Design*des, NetNet*net, unsigned wid)
tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, wid);
tmp->data_type( net->data_type() );
tmp->set_line(*net);
tmp->local_flag(true);
connect(cc->pin(0), tmp->pin(0));
+210 -385
View File
File diff suppressed because it is too large Load Diff

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