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
366 changed files with 19583 additions and 26610 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
+37
View File
@@ -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: Attrib.cc,v 1.6 2004/02/20 18:53:33 steve Exp $"
#endif
# include "config.h"
@@ -99,3 +102,37 @@ const verinum& Attrib::attr_value(unsigned idx) const
assert(idx < nlist_);
return list_[idx].val;
}
/*
* $Log: Attrib.cc,v $
* Revision 1.6 2004/02/20 18:53:33 steve
* Addtrbute keys are perm_strings.
*
* Revision 1.5 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.4 2002/05/26 01:39:02 steve
* Carry Verilog 2001 attributes with processes,
* all the way through to the ivl_target API.
*
* Divide signal reference counts between rval
* and lval references.
*
* Revision 1.3 2002/05/23 03:08:50 steve
* Add language support for Verilog-2001 attribute
* syntax. Hook this support into existing $attribute
* handling, and add number and void value types.
*
* Add to the ivl_target API new functions for access
* of complex attributes attached to gates.
*
* Revision 1.2 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.1 2000/12/04 17:37:03 steve
* Add Attrib class for holding NetObj attributes.
*
*/
+30
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: Attrib.h,v 1.5 2004/02/20 18:53:33 steve Exp $"
#endif
# include "StringHeap.h"
# include "verinum.h"
@@ -57,4 +60,31 @@ class Attrib {
Attrib& operator= (const Attrib&);
};
/*
* $Log: Attrib.h,v $
* Revision 1.5 2004/02/20 18:53:33 steve
* Addtrbute keys are perm_strings.
*
* Revision 1.4 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.3 2002/05/26 01:39:02 steve
* Carry Verilog 2001 attributes with processes,
* all the way through to the ivl_target API.
*
* Divide signal reference counts between rval
* and lval references.
*
* Revision 1.2 2002/05/23 03:08:50 steve
* Add language support for Verilog-2001 attribute
* syntax. Hook this support into existing $attribute
* handling, and add number and void value types.
*
* Add to the ivl_target API new functions for access
* of complex attributes attached to gates.
*
* Revision 1.1 2000/12/04 17:37:03 steve
* Add Attrib class for holding NetObj attributes.
*
*/
#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.
+33
View File
@@ -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: HName.cc,v 1.8 2007/06/02 03:42:12 steve Exp $"
#endif
# include "config.h"
# include "HName.h"
@@ -117,3 +120,33 @@ ostream& operator<< (ostream&out, const hname_t&that)
return out;
}
/*
* $Log: HName.cc,v $
* Revision 1.8 2007/06/02 03:42:12 steve
* Properly evaluate scope path expressions.
*
* Revision 1.7 2007/05/16 19:12:33 steve
* Fix hname_t use of space for 1 perm_string.
*
* Revision 1.6 2007/04/26 03:06:21 steve
* Rework hname_t to use perm_strings.
*
* Revision 1.5 2002/11/02 03:27:52 steve
* Allow named events to be referenced by
* hierarchical names.
*
* Revision 1.4 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.3 2002/01/05 04:36:06 steve
* include malloc.h only when available.
*
* Revision 1.2 2001/12/18 04:52:45 steve
* Include config.h for namespace declaration.
*
* Revision 1.1 2001/12/03 04:47:14 steve
* Parser and pform use hierarchical names as hname_t
* objects instead of encoded strings.
*
*/
+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
+68 -72
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@/iverilog$(suffix)
includedir = @includedir@
mandir = @mandir@
dllib=@DLLIB@
@@ -77,15 +52,15 @@ MAN = @MAN@
PS2PDF = @PS2PDF@
GIT = @GIT@
CPPFLAGS = @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
@@ -121,25 +96,23 @@ distclean: clean
rm -f Makefile config.status config.log config.cache config.h
rm -f _pli_types.h
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o t-dll-analog.o
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
@@ -166,13 +139,12 @@ SUBDIRS += driver-vpi
else
all: dep iverilog-vpi
iverilog-vpi: iverilog-vpi.sh Makefile
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)
+33
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: PDelays.h,v 1.9 2006/01/03 05:22:14 steve Exp $"
#endif
# include "svector.h"
# include <string>
@@ -69,4 +72,34 @@ class PDelays {
ostream& operator << (ostream&o, const PDelays&);
/*
* $Log: PDelays.h,v $
* Revision 1.9 2006/01/03 05:22:14 steve
* Handle complex net node delays.
*
* Revision 1.8 2006/01/02 05:33:19 steve
* Node delays can be more general expressions in structural contexts.
*
* Revision 1.7 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.6 2002/06/14 03:25:51 steve
* Compiler portability.
*
* Revision 1.5 2001/12/29 20:19:31 steve
* Do not delete delay expressions of UDP instances.
*
* Revision 1.4 2001/11/22 06:20:59 steve
* Use NetScope instead of string for scope path.
*
* Revision 1.3 2001/01/16 02:44:17 steve
* Use the iosfwd header if available.
*
* Revision 1.2 2000/02/23 02:56:53 steve
* Macintosh compilers do not support ident.
*
* Revision 1.1 1999/09/04 19:11:46 steve
* Add support for delayed non-blocking assignments.
*
*/
#endif
+26
View File
@@ -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: PEvent.cc,v 1.5 2004/02/19 06:57:10 steve Exp $"
#endif
# include "config.h"
@@ -35,3 +38,26 @@ perm_string PEvent::name() const
return name_;
}
/*
* $Log: PEvent.cc,v $
* Revision 1.5 2004/02/19 06:57:10 steve
* Memory and Event names use perm_string.
*
* Revision 1.4 2003/03/01 06:25:30 steve
* Add the lex_strings string handler, and put
* scope names and system task/function names
* into this table. Also, permallocate event
* names from the beginning.
*
* Revision 1.3 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.2 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.1 2000/04/01 19:31:57 steve
* Named events as far as the pform.
*
*/
+37
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: PEvent.h,v 1.9 2004/02/19 06:57:10 steve Exp $"
#endif
# include "LineInfo.h"
# include "StringHeap.h"
@@ -51,4 +54,38 @@ class PEvent : public LineInfo {
PEvent& operator= (const PEvent&);
};
/*
* $Log: PEvent.h,v $
* Revision 1.9 2004/02/19 06:57:10 steve
* Memory and Event names use perm_string.
*
* Revision 1.8 2003/03/01 06:25:30 steve
* Add the lex_strings string handler, and put
* scope names and system task/function names
* into this table. Also, permallocate event
* names from the beginning.
*
* Revision 1.7 2003/01/30 16:23:07 steve
* Spelling fixes.
*
* Revision 1.6 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.5 2001/12/03 04:47:14 steve
* Parser and pform use hierarchical names as hname_t
* objects instead of encoded strings.
*
* Revision 1.4 2001/01/16 02:44:18 steve
* Use the iosfwd header if available.
*
* Revision 1.3 2000/04/09 17:44:30 steve
* Catch event declarations during scope elaborate.
*
* Revision 1.2 2000/04/04 03:20:15 steve
* Simulate named event trigger and waits.
*
* Revision 1.1 2000/04/01 19:31:57 steve
* Named events as far as the pform.
*
*/
#endif
+66 -98
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,36 +81,8 @@ PEBComp::~PEBComp()
{
}
PEBLogic::PEBLogic(char op, PExpr*l, PExpr*r)
: PEBinary(op, l, r)
{
assert(op == 'a' || op == 'o');
}
PEBLogic::~PEBLogic()
{
}
PEBLeftWidth::PEBLeftWidth(char op, PExpr*l, PExpr*r)
: PEBinary(op, l, r)
{
}
PEBLeftWidth::~PEBLeftWidth()
{
}
PEBPower::PEBPower(char op, PExpr*l, PExpr*r)
: PEBLeftWidth(op, l, r)
{
}
PEBPower::~PEBPower()
{
}
PEBShift::PEBShift(char op, PExpr*l, PExpr*r)
: PEBLeftWidth(op, l, r)
: PEBinary(op, l, r)
{
}
@@ -122,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)
{
}
@@ -135,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)
{
}
@@ -145,33 +113,22 @@ 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
PEConcat::PEConcat(const svector<PExpr*>&p, PExpr*r)
: parms_(p), repeat_(r)
{
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), tested_widths_(p.count()), 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()
@@ -179,18 +136,6 @@ 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)
{
@@ -205,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_;
@@ -231,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)
{
@@ -245,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)
@@ -286,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)
{
@@ -301,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)
{
@@ -310,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)
@@ -327,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);
}
+236 -158
View File
@@ -21,7 +21,6 @@
# include <string>
# include <vector>
# include <valarray>
# include "netlist.h"
# include "verinum.h"
# include "LineInfo.h"
@@ -37,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 {
@@ -47,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.
//
@@ -68,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.
@@ -109,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;
@@ -138,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&);
@@ -161,31 +160,30 @@ 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;
private:
svector<PExpr*>parms_;
std::valarray<unsigned>tested_widths_;
PExpr*repeat_;
};
/*
@@ -210,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_;
@@ -233,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:
@@ -259,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;
@@ -279,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;
@@ -287,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_; }
@@ -306,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,
@@ -358,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;
@@ -366,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 {
@@ -379,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;
@@ -392,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_;
@@ -415,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_;
};
@@ -435,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_;
@@ -463,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;
@@ -487,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;
};
/*
@@ -508,78 +636,20 @@ 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;
};
/*
* A couple of the binary operands have a special sub-expression rule
* where the expression width is carried entirely by the left
* expression, and the right operand is self-determined.
*/
class PEBLeftWidth : public PEBinary {
public:
explicit PEBLeftWidth(char op, PExpr*l, PExpr*r);
~PEBLeftWidth() =0;
virtual NetExpr*elaborate_expr_leaf(Design*des, NetExpr*lp, NetExpr*rp,
int expr_wid) const =0;
protected:
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*scope,
int expr_width, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*scope) const;
};
class PEBPower : public PEBLeftWidth {
public:
explicit PEBPower(char op, PExpr*l, PExpr*r);
~PEBPower();
NetExpr*elaborate_expr_leaf(Design*des, NetExpr*lp, NetExpr*rp,
int expr_wid) const;
};
class PEBShift : public PEBLeftWidth {
class PEBShift : public PEBinary {
public:
explicit PEBShift(char op, PExpr*l, PExpr*r);
~PEBShift();
NetExpr*elaborate_expr_leaf(Design*des, NetExpr*lp, NetExpr*rp,
int expr_wid) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, bool&flag) const;
};
/*
@@ -592,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;
@@ -621,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, ivl_nature_t) 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 -72
View File
@@ -16,96 +16,38 @@
* 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.cc,v 1.4 2007/06/02 03:42:12 steve Exp $"
#endif
# include "PGenerate.h"
# include "PWire.h"
# include "ivl_assert.h"
PGenerate::PGenerate(unsigned id)
: id_number(id)
{
direct_nested_ = false;
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::probe_for_direct_nesting_(void)
void PGenerate::add_behavior(PProcess*proc)
{
direct_nested_ = false;
ivl_assert(*this, scheme_type==GS_CASE_ITEM || scheme_type==GS_CONDIT || scheme_type==GS_ELSE);
// If this scheme has received an explicit name, then it
// cannot be direct nested.
if (scope_name[0] != '$') return;
if (tasks.size() > 0) return;
if (funcs.size() > 0) return;
if (gates.size() > 0) return;
if (parameters.size() > 0) return;
if (localparams.size() > 0) return;
if (events.size() > 0) return;
if (wires.size() > 0) return;
if (behaviors.size() > 0) return;
if (analog_behaviors.size() > 0) return;
if (generate_schemes.size() == 0) return;
switch (generate_schemes.size()) {
case 1: {
PGenerate*child = generate_schemes.front();
if (child->scheme_type == GS_CONDIT)
direct_nested_ = true;
if (child->scheme_type == GS_CASE)
direct_nested_ = true;
break;
}
case 2: {
PGenerate*child1 = generate_schemes.front();
PGenerate*child2 = generate_schemes.back();
if (child1->scheme_type==GS_CONDIT && child2->scheme_type==GS_ELSE)
direct_nested_ = true;
if (child2->scheme_type==GS_CONDIT && child1->scheme_type==GS_ELSE)
direct_nested_ = true;
break;
}
}
}
ostream& operator << (ostream&out, PGenerate::scheme_t type)
{
switch (type) {
case PGenerate::GS_NONE:
out << "GS_NONE";
break;
case PGenerate::GS_LOOP:
out << "GS_LOOP";
break;
case PGenerate::GS_CONDIT:
out << "GS_CONDIT";
break;
case PGenerate::GS_ELSE:
out << "GS_ELSE";
break;
case PGenerate::GS_CASE:
out << "GS_CASE";
break;
case PGenerate::GS_CASE_ITEM:
out << "GS_CASE_ITEM";
break;
case PGenerate::GS_NBLOCK:
out << "GS_NBLOCK";
break;
}
return out;
behaviors.push_back(proc);
}
+13 -34
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,22 +18,21 @@
* 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 <valarray>
# include "pform_types.h"
class Design;
class NetScope;
class PExpr;
class PFunction;
class PProcess;
class PTask;
class PGate;
class PWire;
@@ -50,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
@@ -61,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,20 +70,17 @@ class PGenerate : public LineInfo, public LexicalScope {
PExpr*loop_init;
PExpr*loop_test;
PExpr*loop_step;
// Case items may have multiple guard expression values. It is
// enough for any on of the guards to match the case statement
// test value.
std::valarray<PExpr*> item_test;
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
@@ -107,32 +99,19 @@ 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);
// Call probe during elaborate_scope to calulate the
// directed_nested_ flag. It is OK to store the direct_nested_
// information here because "direct nested" is a property of
// the lexical generate code.
void probe_for_direct_nesting_(void);
bool direct_nested_;
// Elaborate_scope within a generated scope.
void elaborate_subscope_(Design*des, NetScope*scope);
void elaborate_subscope_direct_(Design*des, NetScope*scope);
// These are the scopes created by generate_scope.
list<NetScope*>scope_list_;
// internal function called on each scope generated by this scheme.
bool elaborate_sig_(Design*des, NetScope*scope) const;
bool elaborate_sig_direct_(Design*des, NetScope*scope) const;
bool elaborate_(Design*des, NetScope*scope) const;
bool elaborate_direct_(Design*des, NetScope*scope) const;
private: // not implemented
PGenerate(const PGenerate&);
PGenerate& operator= (const PGenerate&);
};
extern std::ostream& operator << (std::ostream&, PGenerate::scheme_t);
#endif
+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;
+3
View File
@@ -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: PSpec.cc,v 1.2 2007/02/12 01:52:21 steve Exp $"
#endif
# include "PSpec.h"
+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: PSpec.h,v 1.3 2007/04/13 02:34:35 steve Exp $"
#endif
# include "LineInfo.h"
# include "StringHeap.h"
+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
+16
View File
@@ -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: PUdp.cc,v 1.3 2004/03/08 00:47:44 steve Exp $"
#endif
# include "PUdp.h"
@@ -35,3 +38,16 @@ unsigned PUdp::find_port(const char*name)
return ports.count();
}
/*
* $Log: PUdp.cc,v $
* Revision 1.3 2004/03/08 00:47:44 steve
* primitive ports can bind bi name.
*
* Revision 1.2 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items.
*
* Revision 1.1 2003/07/15 05:07:13 steve
* Move PUdp constructor into compiled file.
*
*/
+52
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: PUdp.h,v 1.12 2004/03/08 00:47:44 steve Exp $"
#endif
# include <map>
# include "StringHeap.h"
@@ -75,4 +78,53 @@ class PUdp {
PUdp& operator= (const PUdp&);
};
/*
* $Log: PUdp.h,v $
* Revision 1.12 2004/03/08 00:47:44 steve
* primitive ports can bind bi name.
*
* Revision 1.11 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items.
*
* Revision 1.10 2003/07/15 05:07:13 steve
* Move PUdp constructor into compiled file.
*
* Revision 1.9 2003/07/15 03:49:22 steve
* Spelling fixes.
*
* Revision 1.8 2003/01/30 16:23:07 steve
* Spelling fixes.
*
* Revision 1.7 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.6 2002/05/23 03:08:51 steve
* Add language support for Verilog-2001 attribute
* syntax. Hook this support into existing $attribute
* handling, and add number and void value types.
*
* Add to the ivl_target API new functions for access
* of complex attributes attached to gates.
*
* Revision 1.5 2001/04/22 23:09:45 steve
* More UDP consolidation from Stephan Boettcher.
*
* Revision 1.4 2000/02/23 02:56:53 steve
* Macintosh compilers do not support ident.
*
* Revision 1.3 1999/06/15 03:44:53 steve
* Get rid of the STL vector template.
*
* Revision 1.2 1998/12/01 00:42:13 steve
* Elaborate UDP devices,
* Support UDP type attributes, and
* pass those attributes to nodes that
* are instantiated by elaboration,
* Put modules into a map instead of
* a simple list.
*
* Revision 1.1 1998/11/25 02:35:53 steve
* Parse UDP primitives all the way to pform.
*
*/
#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:
+28
View File
@@ -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: StringHeap.cc,v 1.6 2004/02/18 17:11:54 steve Exp $"
#endif
# include "StringHeap.h"
#ifdef HAVE_MALLOC_H
@@ -176,3 +179,28 @@ bool operator < (perm_string a, perm_string b)
return false;
}
/*
* $Log: StringHeap.cc,v $
* Revision 1.6 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items.
*
* Revision 1.5 2003/03/01 06:25:30 steve
* Add the lex_strings string handler, and put
* scope names and system task/function names
* into this table. Also, permallocate event
* names from the beginning.
*
* Revision 1.4 2003/01/27 05:09:17 steve
* Spelling fixes.
*
* Revision 1.3 2003/01/16 21:44:46 steve
* Keep some debugging status.
*
* Revision 1.2 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.1 2002/08/04 19:13:16 steve
* dll uses StringHeap for named items.
*
*/
+27
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: StringHeap.h,v 1.6 2005/06/14 19:13:43 steve Exp $"
#endif
# include "config.h"
# include <string>
@@ -117,4 +120,28 @@ class StringHeapLex : private StringHeap {
StringHeapLex& operator= (const StringHeapLex&);
};
/*
* $Log: StringHeap.h,v $
* Revision 1.6 2005/06/14 19:13:43 steve
* gcc3/4 compile errors.
*
* Revision 1.5 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items.
*
* Revision 1.4 2003/03/01 06:25:30 steve
* Add the lex_strings string handler, and put
* scope names and system task/function names
* into this table. Also, permallocate event
* names from the beginning.
*
* Revision 1.3 2003/01/16 21:44:46 steve
* Keep some debugging status.
*
* Revision 1.2 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.1 2002/08/04 19:13:16 steve
* dll uses StringHeap for named items.
*
*/
#endif
+41
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: _pli_types.h.in,v 1.8 2007/06/05 21:32:30 steve Exp $"
#endif
# undef HAVE_INTTYPES_H
@@ -85,4 +88,42 @@ typedef char PLI_BYTE8;
typedef unsigned char PLI_UBYTE8;
#endif
/*
* $Log: _pli_types.h.in,v $
* Revision 1.8 2007/06/05 21:32:30 steve
* More standard PLI_BYTE8.
*
* Revision 1.7 2003/11/12 02:38:44 steve
* Clean up manual definitions of PLI_UINT64_FMT.
*
* Revision 1.6 2003/11/08 20:06:21 steve
* Spelling fixes in comments.
*
* Revision 1.5 2003/10/29 03:28:27 steve
* Add the PLU_UINT64_FMT string for formatting output.
*
* Revision 1.4 2003/10/29 03:23:12 steve
* Portably handle time format of VCD prints.
*
* Revision 1.3 2003/10/02 21:30:06 steve
* Use configured TIME_FMT in vcd dump printf.
*
* Revision 1.2 2003/10/02 19:33:44 steve
* Put libraries in libdir64.
*
* Revision 1.1 2003/09/30 01:33:13 steve
* Add PLI_UINT64 to _pli_types.h.
*
* Revision 1.2 2003/05/26 04:39:16 steve
* Typo type name.
*
* Revision 1.1 2003/02/17 06:39:47 steve
* Add at least minimal implementations for several
* acc_ functions. Add support for standard ACC
* string handling.
*
* Add the _pli_types.h header file to carry the
* IEEE1364-2001 standard PLI type declarations.
*
*/
#endif
+81
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: acc_user.h,v 1.20 2003/12/17 15:45:07 steve Exp $"
#endif
/*
* This header file contains the definitions and declarations needed
@@ -270,4 +273,82 @@ extern char* acc_version(void);
EXTERN_C_END
/*
* $Log: acc_user.h,v $
* Revision 1.20 2003/12/17 15:45:07 steve
* Add acc_set_scope function.
*
* Revision 1.19 2003/10/10 02:57:45 steve
* Some PLI1 stubs.
*
* Revision 1.18 2003/06/13 19:23:41 steve
* Add a bunch more PLI1 routines.
*
* Revision 1.17 2003/06/04 01:56:20 steve
* 1) Adds configure logic to clean up compiler warnings
* 2) adds acc_compare_handle, acc_fetch_range, acc_next_scope and
* tf_isetrealdelay, acc_handle_scope
* 3) makes acc_next reentrant
* 4) adds basic vpiWire type support
* 5) fills in some acc_object_of_type() and acc_fetch_{full}type()
* 6) add vpiLeftRange/RigthRange to signals
*
* Revision 1.16 2003/05/30 04:18:31 steve
* Add acc_next function.
*
* Revision 1.15 2003/05/29 02:35:41 steve
* acc_fetch_type supports module.
*
* Revision 1.14 2003/05/29 02:21:45 steve
* Implement acc_fetch_defname and its infrastructure in vvp.
*
* Revision 1.13 2003/05/24 03:02:04 steve
* Add implementation of acc_handle_by_name.
*
* Revision 1.12 2003/05/18 00:16:35 steve
* Add PLI_TRACE tracing of PLI1 modules.
*
* Add tf_isetdelay and friends, and add
* callback return values for acc_vcl support.
*
* Revision 1.11 2003/04/24 18:57:05 steve
* Add acc_fetch_fulltype function.
*
* Revision 1.10 2003/04/20 02:48:39 steve
* Support value change callbacks.
*
* Revision 1.9 2003/04/12 18:57:13 steve
* More acc_ function stubs.
*
* Revision 1.8 2003/03/13 04:35:09 steve
* Add a bunch of new acc_ and tf_ functions.
*
* Revision 1.7 2003/02/17 06:39:47 steve
* Add at least minimal implementations for several
* acc_ functions. Add support for standard ACC
* string handling.
*
* Add the _pli_types.h header file to carry the
* IEEE1364-2001 standard PLI type declarations.
*
* Revision 1.6 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.5 2002/06/11 15:19:12 steve
* Add acc_fetch_argc/argv/version (mruff)
*
* Revision 1.4 2002/06/07 02:58:58 steve
* Add a bunch of acc/tf functions. (mruff)
*
* Revision 1.3 2002/06/02 19:03:29 steve
* Add acc_handle_tfarg and acc_next_topmode
*
* Revision 1.2 2002/05/30 02:06:05 steve
* Implement acc_product_version.
*
* Revision 1.1 2002/05/23 03:46:42 steve
* Add the acc_user.h header file.
*
*/
#endif
Vendored
+25 -17
View File
@@ -1,21 +1,29 @@
# 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"
# AX_CPP_IDENT
# ------------
# Check if the C compiler supports #ident
# Define and substitute ident_support if so.
#
# It would be simpler and more consistent with the rest of the autoconf
# structure to AC_DEFINE(HAVE_CPP_IDENT) instead of
# ident_support='-DHAVE_CVS_IDENT=1' and AC_SUBST(ident_support), but that
# change would require all C files in the icarus top level directory to
# put #include <config.h> before the #ifdef HAVE_CVS_IDENT (and change
# HAVE_CVS_IDENT to HAVE_CPP_IDENT). That would also remove all special
# ident_support handling from the Makefile. Manyana.
#
AC_DEFUN([AX_CPP_IDENT],
[AC_CACHE_CHECK([for ident support in C compiler], ax_cv_cpp_ident,
[AC_TRY_COMPILE([
#ident "$Id: aclocal.m4,v 1.7 2007/05/16 23:59:12 steve Exp $"
],[while (0) {}],
[AS_VAR_SET(ax_cv_cpp_ident, yes)],
[AS_VAR_SET(ax_cv_cpp_ident, no)])])
if test $ax_cv_cpp_ident = yes; then
ident_support='-DHAVE_CVS_IDENT=1'
fi
AC_SUBST(install_suffix)
])# AX_ENABLE_SUFFIX
AC_SUBST(ident_support)
])# AC_CPP_IDENT
# _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=.. )
+5 -7
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,14 +30,14 @@ bindir = @bindir@
libdir = @libdir@
includedir = $(prefix)/include
vpidir = @libdir@/ivl$(suffix)
vpidir = @libdir@/ivl
CC = @CC@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
CPPFLAGS = -I$(srcdir) -I$(srcdir)/.. -I.. @CPPFLAGS@ @DEFS@ @PICFLAG@
CPPFLAGS = @ident_support@ -I$(srcdir) -I$(srcdir)/.. -I.. @CPPFLAGS@ @DEFS@ @PICFLAG@
CFLAGS = -Wall @CFLAGS@
LDFLAGS = @LDFLAGS@
@@ -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 -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)
@@ -58,4 +56,6 @@ AX_C_UNDERSCORES_TRAILING
## end of test for underscores
#######################
AX_CPP_IDENT
AC_OUTPUT(Makefile)
+30 -11
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: ivl_dlfcn.h,v 1.3 2004/10/04 01:10:56 steve Exp $"
#endif
#if defined(__MINGW32__)
# include <windows.h>
@@ -32,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();
@@ -58,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 _ */
@@ -70,25 +73,41 @@ 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
/*
* $Log: ivl_dlfcn.h,v $
* Revision 1.3 2004/10/04 01:10:56 steve
* Clean up spurious trailing white space.
*
* Revision 1.2 2003/12/12 05:43:08 steve
* Some systems dlsym requires leading _ or not on whim.
*
* Revision 1.1 2003/02/17 00:01:25 steve
* Use a variant of ivl_dlfcn to do dynamic loading
* from within the cadpli module.
*
* Change the +cadpli flag to -cadpli, to keep the
* plusargs namespace clear.
*
*/
#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;
+44 -1
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: config.h.in,v 1.12 2007/02/02 04:33:00 steve Exp $"
#endif
#if defined(__cplusplus)
# if !defined(__GNUC__)
@@ -50,4 +53,44 @@
# include <inttypes.h>
#endif
#endif /* __config_H */
/*
* $Log: config.h.in,v $
* Revision 1.12 2007/02/02 04:33:00 steve
* Use inttypes.h instead of stdint.h for portability.
*
* Revision 1.11 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space.
*
* Revision 1.10 2003/08/26 16:26:01 steve
* ifdef idents correctly.
*
* Revision 1.9 2003/07/03 16:29:55 steve
* spemm WORDS_BIGENDIAN correctly.
*
* Revision 1.8 2003/03/07 02:44:33 steve
* Implement $realtobits.
*
* Revision 1.7 2003/02/20 00:49:24 steve
* detect -lz and -lbz2 libraries.
*
* Revision 1.6 2003/01/10 19:01:04 steve
* Only use libiberty.h if available.
*
* Revision 1.5 2002/08/11 23:39:33 steve
* Remove VVM option.
*
* Revision 1.4 2002/02/16 03:18:53 steve
* Make vvm optional, normally off.
*
* Revision 1.3 2001/10/18 16:16:23 steve
* Include HAVE_SYS_WAIT in config.h (PR#306)
*
* Revision 1.2 2001/09/15 18:27:04 steve
* Make configure detect malloc.h
*
* Revision 1.1 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)
*
*/
#endif // __config_H
+3 -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.
@@ -121,7 +119,9 @@ AX_C_UNDERSCORES_TRAILING
## end of test for underscores
#######################
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);
}
+17 -157
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)
@@ -136,17 +135,6 @@ ostream& operator <<(ostream&o, struct __ScopePathManip marg)
return o;
}
void NetBranch::dump(ostream&o, unsigned ind) const
{
static const char*pin_names[2] = {
"terminal0",
"terminal1" };
o << setw(ind) << "" << "branch island=" << get_island();
o << " // " << get_fileline() << endl;
dump_node_pins(o, ind+4, pin_names);
}
void NetDelaySrc::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "specify delay";
@@ -199,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());
@@ -252,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:
@@ -308,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);
}
@@ -328,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): " <<
@@ -354,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);
}
@@ -590,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);
}
@@ -689,7 +639,7 @@ void NetTaskDef::dump(ostream&o, unsigned ind) const
void NetTran::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << type_ << " " << name()
<< " island " << get_island();
<< " island " << island;
if (type_ == IVL_SW_TRAN_VP) {
o << " width=" << vector_width()
<< " part=" << part_width()
@@ -713,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;
@@ -731,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_) {
@@ -804,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;
@@ -896,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 ";
@@ -962,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 ";
@@ -994,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;
@@ -1092,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)
@@ -1109,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 ";
@@ -1160,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 << " = " <<
@@ -1168,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="
@@ -1185,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
@@ -1276,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') {
@@ -1522,19 +1391,10 @@ void Design::dump(ostream&o) const
} while (cur != nodes_->node_next_);
}
o << "ELABORATED BRANCHES:" << endl;
if (branches_) {
for (NetBranch*cur = branches_ ; cur ; cur = cur->next_)
cur->dump(o, 0);
}
o << "ELABORATED PROCESSES:" << endl;
// Dump the processes.
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.
+7 -7
View File
@@ -19,21 +19,21 @@
# include "discipline.h"
ivl_nature_s::ivl_nature_s(perm_string name__, perm_string access__)
: name_(name__), access_(access__)
nature_t::nature_t(perm_string name, perm_string access)
: name_(name), access_(access)
{
}
ivl_nature_s::~ivl_nature_s()
nature_t::~nature_t()
{
}
ivl_discipline_s::ivl_discipline_s(perm_string name__, ivl_dis_domain_t domain__,
ivl_nature_t pot, ivl_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()
{
}
+19 -21
View File
@@ -28,15 +28,15 @@
# 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 ivl_nature_s : public LineInfo {
class nature_t : public LineInfo {
public:
explicit ivl_nature_s(perm_string name, perm_string access);
~ivl_nature_s();
explicit nature_t(perm_string name, perm_string access);
~nature_t();
perm_string name() const { return name_; }
// Identifier for the access function for this nature
@@ -47,31 +47,29 @@ class ivl_nature_s : 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,
ivl_nature_t pot, ivl_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_; }
const ivl_nature_t potential() const { return potential_; }
const ivl_nature_t flow() const { return flow_; }
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_;
ivl_nature_t potential_;
ivl_nature_t flow_;
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,ivl_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,ivl_nature_t> access_function_nature;
extern map<perm_string,nature_t*> natures;
extern map<perm_string,discipline_t*> disciplines;
#endif
+5 -10
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
@@ -43,7 +39,7 @@ INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
CPPFLAGS = -I. -I$(srcdir)/.. -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@
CPPFLAGS = @ident_support@ -I. -I$(srcdir)/.. -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@
CFLAGS = -Wall @CFLAGS@
LDFLAGS = @LDFLAGS@
@@ -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"
+14 -10
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");
@@ -511,16 +511,20 @@ static void setup_ivl_environment()
}
/* Build up the CFLAGS option string */
assign(&gstr.pCFLAGS,IVERILOG_VPI_CFLAGS " -I");
assign(&gstr.pCFLAGS,IVERILOG_VPI_CFLAGS);
append(&gstr.pCFLAGS," -I");
append(&gstr.pCFLAGS,gstr.pIVL);
appendBackSlash(&gstr.pCFLAGS);
append(&gstr.pCFLAGS,"\\include\\\\iverilog" IVERILOG_SUFFIX);
append(&gstr.pCFLAGS, "\\");
append(&gstr.pCFLAGS,"include");
/* Build up the LDFLAGS option string */
assign(&gstr.pLDLIBS,"-L");
append(&gstr.pLDLIBS,gstr.pIVL);
appendBackSlash(&gstr.pLDLIBS);
append(&gstr.pLDLIBS,"\\lib " IVERILOG_VPI_LDLIBS);
append(&gstr.pLDLIBS, "\\");
append(&gstr.pLDLIBS,"lib ");
append(&gstr.pLDLIBS,IVERILOG_VPI_LDLIBS);
}
/* compile source modules */
+16 -18
View File
@@ -20,8 +20,6 @@ SHELL = /bin/sh
VERSION = 0.9.devel
suffix = @install_suffix@
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
@@ -43,7 +41,7 @@ INSTALL_DATA = @INSTALL_DATA@
MAN = @MAN@
PS2PDF = @PS2PDF@
CPPFLAGS = -I. -I.. -I$(srcdir)/.. -I$(srcdir) -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@
CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir)/.. -I$(srcdir) -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@
CFLAGS = -Wall @CFLAGS@
LDFLAGS = @LDFLAGS@
@@ -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]; }
+35
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: globals.h,v 1.21 2007/04/19 02:52:53 steve Exp $"
#endif
# include <stddef.h>
@@ -75,4 +78,36 @@ extern char warning_flags[];
extern char* library_flags;
extern char* library_flags2;
/*
* $Log: globals.h,v $
* Revision 1.21 2007/04/19 02:52:53 steve
* Add support for -v flag in command file.
*
* Revision 1.20 2007/03/07 04:24:59 steve
* Make integer width controllable.
*
* Revision 1.19 2003/11/18 06:31:46 steve
* Remove the iverilog.conf file.
*
* Revision 1.18 2003/11/13 04:09:49 steve
* Pass flags through the temporary config file.
*
* Revision 1.17 2003/11/01 04:21:57 steve
* Add support for a target static config file.
*
* Revision 1.16 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
* Revision 1.15 2002/06/23 20:10:51 steve
* Variable substitution in command files.
*
* Revision 1.14 2002/05/28 20:40:37 steve
* ivl indexes the search path for libraries, and
* supports case insensitive module-to-file lookup.
*
* Revision 1.13 2002/05/28 00:50:40 steve
* Add the ivl -C flag for bulk configuration
* from the driver, and use that to run library
* modules through the preprocessor.
*/
#endif
+13 -9
View File
@@ -1,4 +1,4 @@
.TH iverilog 1 "April 22nd, 2008" "" "Version 0.9.devel"
.TH iverilog 1 "April 22nd, 2008" Version "0.9.devel"
.SH NAME
iverilog - Icarus Verilog compiler
@@ -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
@@ -68,7 +68,7 @@ other tools.
Enable or disable (default) support for Verilog-AMS.
.TP 8
.B -gspecify\fI|\fP-gno-specify
Enable or disable (default) specify block support. When enabled,
Enable (default) or disable specify block support. When enabled,
specify block code is elaborated. When disabled, specify blocks are
parsed but ignored. Specify blocks are commonly not needed for RTL
simulation, and in fact can hurt performance of the
@@ -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])
+82 -154
View File
@@ -31,9 +31,9 @@ const char NOTICE[] =
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
" GNU General Public License for more details.\n"
"\n"
" You should have received a copy of the GNU General Public License along\n"
" with this program; if not, write to the Free Software Foundation, Inc.,\n"
" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n"
" You should have received a copy of the GNU General Public License\n"
" along with this program; if not, write to the Free Software\n"
" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\n"
;
const char HELP[] =
@@ -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,8 +106,8 @@ const char*npath = 0;
const char*targ = "vvp";
const char*depfile = 0;
const char*generation = "2005";
const char*gen_specify = "no-specify";
const char*generation = "2x";
const char*gen_specify = "specify";
const char*gen_xtypes = "xtypes";
const char*gen_icarus = "icarus-misc";
const char*gen_io_range_error = "io-range-error";
@@ -260,120 +259,18 @@ static const char*my_tempfile(const char*str, FILE**fout)
return pathbuf;
}
static int t_version_only(void)
{
int rc;
remove(source_path);
free(source_path);
fflush(0);
snprintf(tmp, sizeof tmp, "%s%civlpp -V", pbase, sep);
rc = system(tmp);
if (rc != 0) {
fprintf(stderr, "Unable to get version from \"%s\"\n", tmp);
}
fflush(0);
snprintf(tmp, sizeof tmp, "%s%civl -V -C%s -C%s", pbase, sep,
iconfig_path, iconfig_common_path);
rc = system(tmp);
if (rc != 0) {
fprintf(stderr, "Unable to get version from \"%s\"\n", 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);
@@ -426,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
}
@@ -613,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"
@@ -630,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)
@@ -640,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;
@@ -759,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;
@@ -778,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);
@@ -851,8 +745,11 @@ int main(int argc, char **argv)
if (version_flag || verbose_flag) {
printf("Icarus Verilog version " VERSION " (" VERSION_TAG ")\n\n");
printf("Copyright 1998-2008 Stephen Williams\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. */
@@ -867,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");
}
@@ -935,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
@@ -951,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());
+49 -1
View File
@@ -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: elab_anet.cc,v 1.13 2007/03/22 16:08:14 steve Exp $"
#endif
# include "config.h"
@@ -112,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) {
@@ -164,3 +167,48 @@ NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
return sig;
}
/*
* $Log: elab_anet.cc,v $
* Revision 1.13 2007/03/22 16:08:14 steve
* Spelling fixes from Larry
*
* Revision 1.12 2006/05/01 20:47:58 steve
* More explicit datatype setup.
*
* Revision 1.11 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.10 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space.
*
* Revision 1.9 2003/09/19 03:50:12 steve
* Remove find_memory method from Design class.
*
* Revision 1.8 2003/06/21 01:21:43 steve
* Harmless fixup of warnings.
*
* Revision 1.7 2003/03/06 00:28:41 steve
* All NetObj objects have lex_string base names.
*
* Revision 1.6 2003/01/27 05:09:17 steve
* Spelling fixes.
*
* Revision 1.5 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.4 2001/12/03 04:47:14 steve
* Parser and pform use hierarchical names as hname_t
* objects instead of encoded strings.
*
* Revision 1.3 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.2 2001/01/06 02:29:36 steve
* Support arrays of integers.
*
* Revision 1.1 2000/12/06 06:31:09 steve
* Check lvalue of procedural continuous assign (PR#29)
*
*/
+339 -1440
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 -188
View File
@@ -57,66 +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*PEBLeftWidth::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;
}
NetExpr*tmp = elaborate_expr_leaf(des, lp, rp, -2);
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
@@ -192,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);
}
@@ -327,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;
}
+170 -516
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,15 +71,27 @@ 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;
tmp->high_open_flag = range->high_open_flag;
if (range->low_expr) {
probe_expr_width(des, scope, range->low_expr);
tmp->low_expr = elab_and_eval(des, scope, range->low_expr, -1);
ivl_assert(*range->low_expr, tmp->low_expr);
} else {
@@ -131,7 +108,6 @@ static void elaborate_parm_item_(perm_string name,
tmp->high_expr = tmp->low_expr;
} else if (range->high_expr) {
probe_expr_width(des, scope, range->high_expr);
tmp->high_expr = elab_and_eval(des, scope, range->high_expr, -1);
ivl_assert(*range->high_expr, tmp->high_expr);
} else {
@@ -142,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 "
@@ -339,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
@@ -369,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
@@ -392,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.
@@ -444,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;
}
@@ -463,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: "
@@ -495,7 +391,6 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
// The initial value for the genvar does not need (nor can it
// use) the genvar itself, so we can evaluate this expression
// the same way any other parameter value is evaluated.
probe_expr_width(des, container, loop_init);
NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1);
NetEConst*init = dynamic_cast<NetEConst*> (init_ex);
if (init == 0) {
@@ -525,15 +420,9 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
cerr << get_fileline() << ": debug: genvar init = " << genvar << endl;
container->genvar_tmp = loop_index;
container->genvar_tmp_val = genvar;
probe_expr_width(des, container, loop_test);
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
@@ -578,15 +467,9 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
elaborate_subscope_(des, scope);
// Calculate the step for the loop variable.
probe_expr_width(des, container, loop_step);
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;
@@ -595,7 +478,6 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
container->genvar_tmp_val = genvar;
delete step;
delete test_ex;
probe_expr_width(des, container, loop_test);
test_ex = elab_and_eval(des, container, loop_test, -1);
test = dynamic_cast<NetEConst*>(test_ex);
assert(test);
@@ -610,15 +492,9 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else_flag)
{
probe_expr_width(des, container, loop_test);
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.
@@ -641,26 +517,14 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
des->errors += 1;
return false;
}
if (debug_scopes)
cerr << get_fileline() << ": debug: Generate condition "
<< (else_flag? "(else)" : "(if)")
<< " value=" << test->value() << ": Generate scope="
<< use_name << endl;
probe_for_direct_nesting_();
if (direct_nested_) {
if (debug_scopes)
cerr << get_fileline() << ": debug: Generate condition "
<< (else_flag? "(else)" : "(if)")
<< " detected direct nesting." << endl;
elaborate_subscope_direct_(des, container);
return true;
}
// If this is not directly nested, then generate a scope
// for myself. That is what I will pass to the subscope.
NetScope*scope = new NetScope(container, use_name, NetScope::GENBLOCK);
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
elaborate_subscope_(des, scope);
@@ -670,15 +534,12 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
{
probe_expr_width(des, container, loop_test);
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 "
@@ -687,45 +548,37 @@ 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 );
// Detect that the item is a default.
if (item->item_test.size() == 0) {
if (item->loop_test == 0) {
default_item = item;
cur ++;
continue;
}
bool match_flag = false;
for (unsigned idx = 0 ; idx < item->item_test.size() && !match_flag ; idx +=1 ) {
probe_expr_width(des, container, item->item_test[idx]);
NetExpr*item_value_ex = elab_and_eval(des, container, item->item_test[idx], -1);
NetEConst*item_value_co = dynamic_cast<NetEConst*>(item_value_ex);
assert(item_value_co);
NetExpr*item_value_ex = elab_and_eval(des, container, item->loop_test, -1);
NetEConst*item_value_co = dynamic_cast<NetEConst*>(item_value_ex);
assert(item_value_co);
if (debug_scopes)
cerr << get_fileline() << ": debug: Generate case "
<< "item value=" << item_value_co->value() << endl;
if (case_value_co->value() == item_value_co->value())
match_flag = true;
// If we stumble on the item that matches, then break
// out now.
if (case_value_co->value() == item_value_co->value()) {
delete item_value_co;
break;
}
// If we stumble on the item that matches, then break out now.
if (match_flag)
break;
delete item_value_co;
cur ++;
}
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;
@@ -737,18 +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);
item->probe_for_direct_nesting_();
if (item->direct_nested_) {
if (debug_scopes)
cerr << get_fileline() << ": debug: Generate case item " << scope_name
<< " detected direct nesting." << endl;
item->elaborate_subscope_direct_(des, container);
return true;
}
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
@@ -757,38 +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_direct_(Design*des, NetScope*scope)
{
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);
}
}
void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
{
// Scan the generated scope for nested generate schemes,
@@ -796,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;
@@ -822,58 +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);
if (debug_scopes)
cerr << get_fileline() << ": debug: Generated scope " << scope_path(scope)
<< " by generate block " << scope_name << endl;
// 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() == "") {
@@ -920,38 +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
{
if (msb_) probe_expr_width(des, sc, msb_);
if (lsb_) probe_expr_width(des, sc, lsb_);
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);
@@ -1039,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 ++;
}
}
@@ -1057,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;
}
@@ -1118,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);
}
@@ -1145,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);
}
@@ -1196,39 +874,15 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
des->errors += 1;
return;
}
if (debug_scopes)
cerr << get_fileline() << ": debug: "
<< "Elaborate block scope " << use_name
<< " within " << scope_path(scope) << endl;
my_scope = new NetScope(scope, use_name, bl_type_==BL_PAR
? 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);
}
/*
+62 -151
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];
@@ -412,9 +402,6 @@ bool PGModule::elaborate_sig_udp_(Design*des, NetScope*scope, PUdp*udp) const
bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
{
if (direct_nested_)
return elaborate_sig_direct_(des, container);
bool flag = true;
// Handle the special case that this is a CASE scheme. In this
@@ -428,10 +415,10 @@ 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->direct_nested_ || !item->scope_list_.empty()) {
if (! item->scope_list_.empty()) {
flag &= item->elaborate_sig(des, container);
}
}
@@ -457,32 +444,6 @@ bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
return flag;
}
bool PGenerate::elaborate_sig_direct_(Design*des, NetScope*container) const
{
if (debug_elaborate)
cerr << get_fileline() << ": debug: "
<< "Direct nesting " << scope_name
<< " (scheme_type=" << scheme_type << ")"
<< " elaborate_sig in scope "
<< scope_path(container) << "." << endl;
// Elaborate_sig for a direct nested generated scheme knows
// that there are only sub_schemes to be elaborated. There
// should be exactly 1 active generate scheme, search for it
// using this loop.
bool flag = true;
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++) {
PGenerate*item = *cur;
if (item->direct_nested_ || !item->scope_list_.empty()) {
// Found the item, and it is direct nested.
flag &= item->elaborate_sig(des, container);
}
}
return flag;
}
bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
{
// Scan the declared PWires to elaborate the obvious signals
@@ -500,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);
}
@@ -515,13 +473,6 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
(*cur) ->elaborate_sig(des, scope);
}
typedef list<PProcess*>::const_iterator proc_it_t;
for (proc_it_t cur = behaviors.begin()
; cur != behaviors.end() ; cur ++ ) {
(*cur) -> statement() -> elaborate_sig(des, scope);
}
return true;
}
@@ -559,9 +510,6 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
case PTF_REG:
case PTF_REG_S:
if (return_type_.range) {
probe_expr_width(des, scope, (*return_type_.range)[0]);
probe_expr_width(des, scope, (*return_type_.range)[1]);
NetExpr*me = elab_and_eval(des, scope,
(*return_type_.range)[0], -1);
assert(me);
@@ -628,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);
@@ -852,35 +792,28 @@ 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) {
probe_expr_width(des, scope, port_msb_);
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;
probe_expr_width(des, scope, port_lsb_);
texpr = elab_and_eval(des, scope, port_lsb_, -1);
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;
@@ -892,33 +825,27 @@ 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) {
probe_expr_width(des, scope, net_msb_);
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;
probe_expr_width(des, scope, net_lsb_);
texpr = elab_and_eval(des, scope, net_lsb_, -1);
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;
@@ -971,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)
@@ -1000,9 +923,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (lidx_ || ridx_) {
assert(lidx_ && ridx_);
probe_expr_width(des, scope, lidx_);
probe_expr_width(des, scope, ridx_);
NetExpr*lexp = elab_and_eval(des, scope, lidx_, -1);
NetExpr*rexp = elab_and_eval(des, scope, ridx_, -1);
@@ -1022,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
@@ -1072,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;
}
@@ -1101,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>
+744 -1242
View File
File diff suppressed because it is too large Load Diff
-74
View File
@@ -1,74 +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
{
probe_expr_width(des, scope, lval_);
probe_expr_width(des, scope, rval_);
NetExpr*lval = elab_and_eval(des, scope, lval_, -1);
NetExpr*rval = elab_and_eval(des, scope, rval_, -1);
NetEAccess*lacc = dynamic_cast<NetEAccess*> (lval);
if (lacc == 0) {
cerr << get_fileline() << ": error: The l-value of a contribution"
<< " statement must be a branch probe access function." << endl;
des->errors += 1;
return 0;
}
NetContribution*st = new NetContribution(lacc, 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 -60
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,26 +180,16 @@ bool NetProcTop::emit(struct target_t*tgt) const
return tgt->process(this);
}
bool NetAnalogTop::emit(struct target_t*tgt) const
{
return tgt->process(this);
}
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
@@ -239,11 +219,6 @@ bool NetCondit::emit_proc(struct target_t*tgt) const
return tgt->proc_condit(this);
}
bool NetContribution::emit_proc(struct target_t*tgt) const
{
return tgt->proc_contribution(this);
}
bool NetDeassign::emit_proc(struct target_t*tgt) const
{
return tgt->proc_deassign(this);
@@ -265,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);
@@ -383,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_);
}
}
@@ -455,11 +427,6 @@ int Design::emit(struct target_t*tgt) const
}
bool branches_rc = true;
for (NetBranch*cur = branches_ ; cur ; cur = cur->next_) {
branches_rc = tgt->branch(cur) && branches_rc;
}
// emit task and function definitions
bool tasks_rc = true;
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
@@ -471,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);
@@ -482,17 +447,10 @@ int Design::emit(struct target_t*tgt) const
return -2;
if (proc_rc == false)
return -3;
if (branches_rc == false)
return -4;
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);
@@ -568,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;
+44 -10
View File
@@ -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: eval_attrib.cc,v 1.9 2007/06/04 19:14:06 steve Exp $"
#endif
# include "config.h"
# include "util.h"
@@ -50,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;
@@ -73,3 +71,39 @@ attrib_list_t* evaluate_attributes(const map<perm_string,PExpr*>&att,
return table;
}
/*
* $Log: eval_attrib.cc,v $
* Revision 1.9 2007/06/04 19:14:06 steve
* Build errors in picky GCC compilers.
*
* Revision 1.8 2005/11/27 17:01:57 steve
* Fix for stubborn compiler.
*
* Revision 1.7 2004/02/20 18:53:35 steve
* Addtrbute keys are perm_strings.
*
* Revision 1.6 2003/01/27 05:09:17 steve
* Spelling fixes.
*
* Revision 1.5 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
* Revision 1.4 2002/08/10 21:59:39 steve
* The default attribute value is 1.
*
* Revision 1.3 2002/06/06 18:57:18 steve
* Use standard name for iostream.
*
* Revision 1.2 2002/06/03 03:55:14 steve
* compile warnings.
*
* Revision 1.1 2002/05/23 03:08:51 steve
* Add language support for Verilog-2001 attribute
* syntax. Hook this support into existing $attribute
* handling, and add number and void value types.
*
* Add to the ivl_target API new functions for access
* 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:
+169 -398
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(), *this);
rsig = pad_to_width(des, rsig, expr_width(), *this);
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,11 +154,14 @@ 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, *this);
rsig = pad_to_width(des, rsig, width, *this);
lsig = pad_to_width(des, lsig, width);
rsig = pad_to_width(des, rsig, width);
assert(lsig->vector_width() == rsig->vector_width());
NetNet*osig = new NetNet(scope, scope->local_symbol(),
@@ -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, *this);
else
lsig = pad_to_width(des, lsig, width, *this);
if (rsig->get_signed())
rsig = pad_to_width_signed(des, rsig, width, *this);
else
rsig = pad_to_width(des, rsig, width, *this);
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();
@@ -745,54 +709,45 @@ NetNet* NetEConcat::synthesize(Design*des, NetScope*scope)
des->add_node(concat);
connect(concat->pin(0), osig->pin(0));
unsigned count_input_width = 0;
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;
count_input_width += tmp[concat_item]->vector_width();
}
}
if (count_input_width != osig->vector_width()) {
cerr << get_fileline() << ": internal error: "
<< "NetEConcat input width = " << count_input_width
<< ", expecting " << osig->vector_width()
<< " (repeat=" << repeat() << ")" << endl;
des->errors += 1;
}
delete[]tmp;
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());
osig->set_line(*this);
NetConst*con = new NetConst(scope, scope->local_symbol(), value());
des->add_node(con);
con->set_line(*this);
connect(osig->pin(0), con->pin(0));
des->add_node(con);
return osig;
}
/*
* 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);
@@ -813,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;
@@ -827,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);
@@ -852,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;
@@ -909,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());
@@ -931,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;
@@ -953,119 +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();
unsigned select_width = expr_width();
// Return 'bx for a constant undefined selections.
if (!base_tmp.is_defined()) {
NetNet*result = make_const_x(des, scope, select_width);
result->set_line(*this);
return result;
}
long base_val = base_tmp.as_long();
// Any below X bits?
NetNet*below = 0;
if (base_val < 0) {
unsigned below_width = abs(base_val);
base_val = 0;
if (below_width > select_width) {
below_width = select_width;
select_width = 0;
} else {
select_width -= below_width;
}
below = make_const_x(des, scope, below_width);
below->set_line(*this);
// All the selected bits are below the signal.
if (select_width == 0) return below;
}
// Any above bits?
NetNet*above = 0;
if ((unsigned)base_val+select_width > sub->vector_width()) {
if (base_val > (long)sub->vector_width()) {
select_width = 0;
} else {
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);
// All the selected bits are above the signal.
if (select_width == 0) return above;
}
// 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);
@@ -1146,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) {
@@ -1177,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);
@@ -1185,8 +1001,8 @@ NetNet* NetETernary::synthesize(Design *des, NetScope*scope)
osig->local_flag(true);
/* Make sure both value operands are the right width. */
tsig = crop_to_width(des, pad_to_width(des, tsig, width, *this), width);
fsig = crop_to_width(des, pad_to_width(des, fsig, width, *this), width);
tsig = crop_to_width(des, pad_to_width(des, tsig, width), width);
fsig = crop_to_width(des, pad_to_width(des, fsig, width), width);
assert(width == tsig->vector_width());
assert(width == fsig->vector_width());
@@ -1209,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();
@@ -1236,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());
@@ -1244,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 "
@@ -1332,8 +1103,8 @@ 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],
def->port(idx)->vector_width(), *this);
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;
}
}
}
+2 -2
View File
@@ -1,4 +1,4 @@
.TH iverilog-vpi 1 "November 19th, 2008" "" "Version 0.9.devel"
.TH iverilog-vpi 1 "$Date: 2004/10/04 01:10:53 $" Version "$Date: 2004/10/04 01:10:53 $"
.SH NAME
iverilog-vpi - Compile front end for VPI modules
@@ -129,7 +129,7 @@ iverilog(1), vvp(1),
.SH COPYRIGHT
.nf
Copyright \(co 2002-2008 Stephen Williams
Copyright \(co 2002 Stephen Williams
This document can be freely redistributed according to the terms of the
GNU General Public License version 2.0
+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
-21
View File
@@ -1,12 +1,7 @@
EXPORTS
ivl_branch_island
ivl_branch_terminal
ivl_design_const
ivl_design_consts
ivl_design_discipline
ivl_design_disciplines
ivl_design_flag
ivl_design_process
ivl_design_root
@@ -20,11 +15,6 @@ ivl_const_signed
ivl_const_type
ivl_const_width
ivl_discipline_domain
ivl_discipline_flow
ivl_discipline_name
ivl_discipline_potential
ivl_event_any
ivl_event_basename
ivl_event_name
@@ -37,14 +27,12 @@ ivl_event_scope
ivl_expr_type
ivl_expr_bits
ivl_expr_branch
ivl_expr_def
ivl_expr_dvalue
ivl_expr_event
ivl_expr_file
ivl_expr_lineno
ivl_expr_name
ivl_expr_nature
ivl_expr_opcode
ivl_expr_oper1
ivl_expr_oper2
@@ -117,15 +105,12 @@ ivl_lval_part_off
ivl_lval_sig
ivl_lval_width
ivl_nature_name
ivl_nexus_get_private
ivl_nexus_name
ivl_nexus_ptrs
ivl_nexus_ptr
ivl_nexus_set_private
ivl_nexus_ptr_branch
ivl_nexus_ptr_con
ivl_nexus_ptr_drive0
ivl_nexus_ptr_drive1
@@ -158,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
@@ -187,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
@@ -206,11 +189,8 @@ ivl_signal_width
ivl_path_delay
ivl_path_source
ivl_process_analog
ivl_process_attr_cnt
ivl_process_attr_val
ivl_process_file
ivl_process_lineno
ivl_process_scope
ivl_process_stmt
ivl_process_type
@@ -232,7 +212,6 @@ ivl_stmt_delay_val
ivl_stmt_events
ivl_stmt_file
ivl_stmt_lineno
ivl_stmt_lexp
ivl_stmt_lval
ivl_stmt_lvals
ivl_stmt_lwidth
+3
View File
@@ -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: ivl_assert.h,v 1.1 2007/01/31 04:21:10 steve Exp $"
#endif
#ifndef __ivl_assert_h
#define __ivl_assert_h
+11 -106
View File
@@ -60,9 +60,6 @@ _BEGIN_DECL
* This object represent an array that can be a memory or a net
* array. (They are the same from the perspective of ivl_target.h.)
*
* ivl_branch_t
* this object represents an analog branch.
*
* ivl_design_t
* This object represents the entire elaborated design. Various
* global properties and methods are available from this.
@@ -152,10 +149,8 @@ _BEGIN_DECL
* throughout the design.
*/
typedef struct ivl_array_s *ivl_array_t;
typedef struct ivl_branch_s *ivl_branch_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;
@@ -164,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;
@@ -182,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,
@@ -205,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,
@@ -267,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,
@@ -355,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,
@@ -365,7 +349,6 @@ typedef enum ivl_statement_type_e {
IVL_ST_CASEZ = 7,
IVL_ST_CASSIGN = 8,
IVL_ST_CONDIT = 9,
IVL_ST_CONTRIB = 27,
IVL_ST_DEASSIGN = 10,
IVL_ST_DELAY = 11,
IVL_ST_DELAYX = 12,
@@ -373,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,
@@ -420,20 +402,6 @@ struct ivl_attribute_s {
};
typedef const struct ivl_attribute_s*ivl_attribute_t;
/* BRANCH
* Branches are analog constructs, a pair of terminals that is used in
* branch access functions. Terminal-1 is the reference node (The
* "ground") for the purposes of the access function that accesses it.
*
* SEMANTIC NOTES
* All the branches in an island are connected by terminals or by
* expressions. The island is the connection of branches that must be
* solved together.
*/
/* extern ivl_scope_t ivl_branch_scope(ivl_branch_t obj); */
extern ivl_nexus_t ivl_branch_terminal(ivl_branch_t obj, int idx);
extern ivl_island_t ivl_branch_island(ivl_branch_t obj);
/* DELAYPATH
* Delaypath objects represent delay paths called out by a specify
* block in the Verilog source file. The destination signal references
@@ -518,9 +486,6 @@ extern int ivl_design_time_precision(ivl_design_t des);
extern unsigned ivl_design_consts(ivl_design_t des);
extern ivl_net_const_t ivl_design_const(ivl_design_t, unsigned idx);
extern unsigned ivl_design_disciplines(ivl_design_t des);
extern ivl_discipline_t ivl_design_discipline(ivl_design_t des, unsigned idx);
/* LITERAL CONSTANTS
* Literal constants are nodes with no input and a single constant
* output. The form of the output depends on the type of the node.
@@ -534,8 +499,7 @@ extern ivl_discipline_t ivl_design_discipline(ivl_design_t des, 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.
@@ -573,32 +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);
extern ivl_nature_t ivl_discipline_potential(ivl_discipline_t net);
extern ivl_nature_t ivl_discipline_flow(ivl_discipline_t net);
extern const char* ivl_nature_name(ivl_nature_t net);
/* EVENTS
*
* Events are a unification of named events and implicit events
@@ -742,16 +680,12 @@ extern unsigned ivl_expr_lineno(ivl_expr_t net);
/* IVL_EX_NUMBER */
extern const char* ivl_expr_bits(ivl_expr_t net);
/* IVL_EX_BACCESS */
extern ivl_branch_t ivl_expr_branch(ivl_expr_t net);
/* IVL_EX_UFUNC */
extern ivl_scope_t ivl_expr_def(ivl_expr_t net);
/* IVL_EX_REALNUM */
extern double ivl_expr_dvalue(ivl_expr_t net);
/* IVL_EX_SIGNAL, IVL_EX_SFUNC, IVL_EX_VARIABLE */
extern const char* ivl_expr_name(ivl_expr_t net);
/* IVL_EX_BACCESS */
extern ivl_nature_t ivl_expr_nature(ivl_expr_t net);
/* IVL_EX_BINARY IVL_EX_UNARY */
extern char ivl_expr_opcode(ivl_expr_t net);
/* IVL_EX_BINARY IVL_EX_UNARY, IVL_EX_MEMORY IVL_EX_TERNARY */
@@ -1052,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
@@ -1318,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);
@@ -1410,7 +1343,6 @@ extern void* ivl_nexus_get_private(ivl_nexus_t net);
extern ivl_drive_t ivl_nexus_ptr_drive0(ivl_nexus_ptr_t net);
extern ivl_drive_t ivl_nexus_ptr_drive1(ivl_nexus_ptr_t net);
extern unsigned ivl_nexus_ptr_pin(ivl_nexus_ptr_t net);
extern ivl_branch_t ivl_nexus_ptr_branch(ivl_nexus_ptr_t net);
extern ivl_net_const_t ivl_nexus_ptr_con(ivl_nexus_ptr_t net);
extern ivl_net_logic_t ivl_nexus_ptr_log(ivl_nexus_ptr_t net);
extern ivl_lpm_t ivl_nexus_ptr_lpm(ivl_nexus_ptr_t net);
@@ -1513,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
@@ -1592,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);
@@ -1645,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
@@ -1716,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);
@@ -1747,16 +1670,12 @@ extern ivl_attribute_t ivl_signal_attr_val(ivl_signal_t net, unsigned idx);
* is translated into a type and a single statement. (The statement
* may be a compound statement.)
*
* ivl_process_type
* ivl_process_analog
* The ivl_process_type function returns the type of the process,
* an "initial" or "always" statement. The ivl_process_analog
* returns true if the process is analog.
* The ivl_process_type function gets the type of the process,
* an "initial" or "always" statement.
*
* ivl_process_scope
* A process is placed in a scope. The statement within the process
* operates within the scope of the process unless there are calls
* outside the scope.
* A process is placed in a scope. The statement within the process
* operates within the scope of the process unless there are calls
* outside the scope.
*
* The ivl_process_stmt function gets the statement that forms the
* process. See the statement related functions for how to manipulate
@@ -1766,7 +1685,6 @@ extern ivl_attribute_t ivl_signal_attr_val(ivl_signal_t net, unsigned idx);
* attr_val methods return those attributes.
*/
extern ivl_process_type_t ivl_process_type(ivl_process_t net);
extern int ivl_process_analog(ivl_process_t net);
extern ivl_scope_t ivl_process_scope(ivl_process_t net);
@@ -1775,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
@@ -1862,12 +1777,6 @@ extern unsigned ivl_stmt_lineno(ivl_statement_t net);
* that constant value. If the expression is non-constant, the code
* generator is supposed to know what to do about that, too.
*
* - IVL_ST_CONTRIB
* This is an analog contribution statement. The ivl_stmt_lexp
* function returns the l-value expression which is guaranteed to be a
* branch access expression. The ivl_stmt_rval returns the r-value
* expression for the assignment.
*
* - IVL_ST_DELAY, IVL_ST_DELAYX
* These statement types are delay statements. They are a way to
* attach a delay to a statement. The ivl_stmt_sub_stmt() function
@@ -1933,8 +1842,6 @@ extern uint64_t ivl_stmt_delay_val(ivl_statement_t net);
/* IVL_ST_WAIT IVL_ST_TRIGGER */
extern unsigned ivl_stmt_nevent(ivl_statement_t net);
extern ivl_event_t ivl_stmt_events(ivl_statement_t net, unsigned idx);
/* IVL_ST_CONTRIB */
extern ivl_expr_t ivl_stmt_lexp(ivl_statement_t net);
/* IVL_ST_ASSIGN IVL_ST_ASSIGN_NB IVL_ST_CASSIGN IVL_ST_DEASSIGN
IVL_ST_FORCE IVL_ST_RELEASE */
extern ivl_lval_t ivl_stmt_lval(ivl_statement_t net, unsigned idx);
@@ -1949,8 +1856,7 @@ extern const char* ivl_stmt_name(ivl_statement_t net);
extern ivl_expr_t ivl_stmt_parm(ivl_statement_t net, unsigned idx);
/* IVL_ST_STASK */
extern unsigned ivl_stmt_parm_count(ivl_statement_t net);
/* IVL_ST_ASSIGN IVL_ST_ASSIGN_NB IVL_ST_CASSIGN IVL_ST_CONTRIB
IVL_ST_FORCE */
/* IVL_ST_ASSIGN IVL_ST_ASSIGN_NB IVL_ST_CASSIGN IVL_ST_FORCE */
extern ivl_expr_t ivl_stmt_rval(ivl_statement_t net);
/* IVL_ST_DELAY, IVL_ST_DELAYX, IVL_ST_FOREVER, IVL_ST_REPEAT
IVL_ST_WAIT, IVL_ST_WHILE */
@@ -2011,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
@@ -2029,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 -44
View File
@@ -1,5 +1,5 @@
#ifndef __ivl_target_priv_H
#define __ivl_target_priv_H
#define __ivl_target_H
/*
* Copyright (c) 2008 Stephen Williams (steve@icarus.com)
*
@@ -19,64 +19,26 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "ivl_target.h"
# include <inttypes.h>
# include <vector>
# include <valarray>
/*
* This header has declarations related to the ivl_target.h API that
* This deader has declarations related to the ivl_target.h API that
* are not to be exported outside of the core via the ivl_target.h
* interface.
*
* (NOTE: A lot of similar definitions exist in the t-dll.h header
* file. That is a legacy from an earlier time before the
* ivl_target_priv.h header file was started, and those definitions
* should gradually be moved over to this header file.)
*/
/*
* This is the root of a design, from the ivl_target point of few. The
* ivl_target API uses this as the root for getting at everything else
* in the design.
*/
struct ivl_design_s {
int time_precision;
ivl_process_t threads_;
ivl_scope_t *roots_;
unsigned nroots_;
// Keep an array of constants objects.
std::valarray<ivl_net_const_t> consts;
// Keep a handy array of all of the disciplines in the design.
std::valarray<ivl_discipline_t> disciplines;
const class Design*self;
};
/*
* A branch is a pair of terminals. The elaborator assures that the
* terminals have compatible disciplines.
*/
struct ivl_branch_s {
ivl_nexus_t pins[2];
ivl_island_t island;
};
/*
* Information about islands. Connected branches within a net are
* collected into islands. Branches that are purely ddiscrete do not
* have disciplines and do not belong to islands.
*/
class discipline_t;
struct ivl_island_s {
ivl_discipline_t discipline;
discipline_t*discipline;
// user accessible flags. They are initially false, always.
std::vector<bool> flags;
vector<bool> flags;
};
#endif
+10 -9
View File
@@ -18,11 +18,12 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.18 2006/10/30 22:45:37 steve Exp $"
#
#
SHELL = /bin/sh
VERSION = 0.9.devel
suffix = @install_suffix@
VERSION = 0.0
prefix = @prefix@
exec_prefix = @exec_prefix@
@@ -39,7 +40,7 @@ INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
CPPFLAGS = -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@
@@ -59,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
+18 -76
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()
@@ -1463,7 +1439,12 @@ static void do_include()
else
{
*cp = '\0';
include_dir[0] = strdup(path);
/* We do not need a strdup here since the path is read before
* it is overridden. If the search order is changed add a
* strdup here and a free below.
*/
include_dir[0] = path;
}
for (idx = start ; idx < include_cnt ; idx += 1)
@@ -1472,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;
}
@@ -1485,15 +1464,11 @@ static void do_include()
code_that_switches_buffers:
/* Clear the current files path from the search list. */
free(include_dir[0]);
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;
@@ -1551,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);
@@ -1620,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;
}
@@ -1758,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)
{
@@ -1789,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;
@@ -1799,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
}
+13 -37
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"
@@ -31,11 +30,13 @@ const char NOTICE[] =
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
" GNU General Public License for more details.\n"
"\n"
" You should have received a copy of the GNU General Public License along\n"
" with this program; if not, write to the Free Software Foundation, Inc.,\n"
" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n"
" You should have received a copy of the GNU General Public License\n"
" along with this program; if not, write to the Free Software\n"
" 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, "%s\n\n", COPYRIGHT);
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
+12
View File
@@ -18,7 +18,19 @@
* 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: lexor_keyword.h,v 1.2 2002/08/12 01:34:59 steve Exp $"
#endif
extern int lexor_keyword_code (const char*str, unsigned len);
/*
* $Log: lexor_keyword.h,v $
* Revision 1.2 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
* Revision 1.1 2000/03/12 17:09:41 steve
* Support localparam.
*
*/
#endif
+9 -7
View File
@@ -16,9 +16,11 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.36 2007/02/06 05:07:32 steve Exp $"
#
#
SHELL = /bin/sh
suffix = @install_suffix@
prefix = @prefix@
exec_prefix = @exec_prefix@
@@ -35,7 +37,7 @@ INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
CPPFLAGS = -I. -I.. -I$(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@ @PICFLAG@
CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@ @PICFLAG@
CFLAGS = -Wall @CFLAGS@
LDFLAGS = @LDFLAGS@
RANLIB = @RANLIB@
@@ -84,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);
}
+18
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: config.h.in,v 1.2 2003/08/26 16:26:02 steve Exp $"
#endif
# define SIZEOF_UNSIGNED_LONG_LONG 0
# define SIZEOF_UNSIGNED_LONG 0
@@ -37,4 +40,19 @@ typedef unsigned long ivl_u64_t;
# endif
#endif
/*
* $Log: config.h.in,v $
* Revision 1.2 2003/08/26 16:26:02 steve
* ifdef idents correctly.
*
* Revision 1.1 2003/06/04 01:56:20 steve
* 1) Adds configure logic to clean up compiler warnings
* 2) adds acc_compare_handle, acc_fetch_range, acc_next_scope and
* tf_isetrealdelay, acc_handle_scope
* 3) makes acc_next reentrant
* 4) adds basic vpiWire type support
* 5) fills in some acc_object_of_type() and acc_fetch_{full}type()
* 6) add vpiLeftRange/RigthRange to signals
*
*/
#endif
+1 -2
View File
@@ -8,8 +8,7 @@ AC_PROG_INSTALL
AC_PROG_RANLIB
AC_EXEEXT
AX_ENABLE_SUFFIX
AX_CPP_IDENT
AC_CHECK_HEADERS(malloc.h)
+20
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: priv.h,v 1.2 2003/05/18 00:16:35 steve Exp $"
#endif
# include <stdio.h>
@@ -33,4 +36,21 @@ extern char* __acc_newstring(const char*txt);
*/
FILE* pli_trace;
/*
* $Log: priv.h,v $
* Revision 1.2 2003/05/18 00:16:35 steve
* Add PLI_TRACE tracing of PLI1 modules.
*
* Add tf_isetdelay and friends, and add
* callback return values for acc_vcl support.
*
* Revision 1.1 2003/02/17 06:39:47 steve
* Add at least minimal implementations for several
* acc_ functions. Add support for standard ACC
* string handling.
*
* Add the _pli_types.h header file to carry the
* IEEE1364-2001 standard PLI type declarations.
*
*/
#endif
+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);
+84 -5
View File
@@ -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: link_const.cc,v 1.18 2007/04/14 03:10:51 steve Exp $"
#endif
# include "config.h"
@@ -57,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());
@@ -78,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;
@@ -172,3 +174,80 @@ verinum::V Nexus::driven_value() const
return val;
}
/*
* $Log: link_const.cc,v $
* Revision 1.18 2007/04/14 03:10:51 steve
* Properly account for tri0 connected to otherwise open mux input.
*
* Revision 1.17 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space.
*
* Revision 1.16 2003/06/21 01:21:43 steve
* Harmless fixup of warnings.
*
* Revision 1.15 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
* Revision 1.14 2002/06/25 01:33:22 steve
* Cache calculated driven value.
*
* Revision 1.13 2002/06/24 01:49:39 steve
* Make link_drive_constant cache its results in
* the Nexus, to improve cprop performance.
*
* Revision 1.12 2002/06/19 04:18:46 steve
* Shuffle link_drivers_constant for speed.
*
* Revision 1.11 2001/08/25 23:50:03 steve
* Change the NetAssign_ class to refer to the signal
* instead of link into the netlist. This is faster
* and uses less space. Make the NetAssignNB carry
* the delays instead of the NetAssign_ lval objects.
*
* Change the vvp code generator to support multiple
* l-values, i.e. concatenations of part selects.
*
* Revision 1.10 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.9 2001/07/07 03:01:37 steve
* Detect and make available to t-dll the right shift.
*
* Revision 1.8 2001/02/16 03:27:07 steve
* links to root inputs are not constant.
*
* Revision 1.7 2000/11/20 01:41:12 steve
* Whoops, return the calculated constant value rom driven_value.
*
* Revision 1.6 2000/11/20 00:58:40 steve
* Add support for supply nets (PR#17)
*
* Revision 1.5 2000/07/14 06:12:57 steve
* Move inital value handling from NetNet to Nexus
* objects. This allows better propogation of inital
* values.
*
* Clean up constant propagation a bit to account
* for regs that are not really values.
*
* Revision 1.4 2000/06/25 19:59:42 steve
* Redesign Links to include the Nexus class that
* carries properties of the connected set of links.
*
* Revision 1.3 2000/05/14 17:55:04 steve
* Support initialization of FF Q value.
*
* Revision 1.2 2000/05/07 04:37:56 steve
* Carry strength values from Verilog source to the
* pform and netlist for gates.
*
* Change vvm constants to use the driver_t to drive
* a constant value. This works better if there are
* multiple drivers on a signal.
*
* Revision 1.1 2000/04/20 00:28:03 steve
* Catch some simple identity compareoptimizations.
*
*/

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