Compare commits

..
1 Commits
Author SHA1 Message Date
steve e67952240b Installation fixes for Debian. 1999-12-03 17:43:49 +00:00
656 changed files with 24615 additions and 208274 deletions
+12
View File
@@ -0,0 +1,12 @@
parse.h
parse.cc
parse.cc.output
lexor.cc
ivl
dep
configure
Makefile
verilog
config.status
config.log
config.cache
-109
View File
@@ -1,109 +0,0 @@
# Lines that start with '#' are comments.
#
# This file is for the development branch of Icarus Verilog.
#
# The following files will be ignored by git.
# Normal editor rules
*.swp
*~
# Top level generic files
tags
TAGS
cscope.*
*.patch
# Object files and libraries
*.[oa]
gmon*.out
gmon*.txt
# From autoconf
configure
config.log
config.status
Makefile
/_pli_types.h
config.h
/tgt-pcb/pcb_config.h
/tgt-vvp/vvp_config.h
/tgt-vhdl/vhdl_config.h
/vpi/vpi_config.h
stamp-*-h
/version.h
/version_tag.h
# Directories
autom4te.cache
dep
# Compiler back end and library files
/tgt-vvp/*.conf
*.tgt
*.vpi
/cadpli/cadpli.vpl
# lex, yacc and gperf output
/driver/cflexor.c
/driver/cfparse.c
/driver/cfparse.h
/driver/cfparse.output
/ivlpp/lexor.c
/vhdlpp/lexor.cc
/vhdlpp/lexor_keyword.cc
/vhdlpp/parse.cc
/vhdlpp/parse.h
/vhdlpp/parse.output
/vhdlpp/vhdlpp_config.h
/vhdlpp/vhdlpp
/lexor.cc
/lexor_keyword.cc
/parse.cc
/parse.h
/parse.output
/syn-rules.cc
/syn-rules.output
/vpi/sdf_lexor.c
/vpi/sdf_parse.c
/vpi/sdf_parse.h
/vpi/sdf_parse.output
/vpi/sys_readmem_lex.c
/vpi/table_mod_lexor.c
/vpi/table_mod_parse.c
/vpi/table_mod_parse.h
/vpi/table_mod_parse.output
/vvp/dump.*
/vvp/lexor.cc
/vvp/parse.cc
/vvp/parse.h
/vvp/parse.output
# Program created files
/vvp/tables.cc
/iverilog-vpi.man
/driver-vpi/res.rc
/driver/iverilog.man
/vvp/vvp.man
# The executables.
*.exe
/driver/iverilog
/iverilog-vpi
/ivl
/ivlpp/ivlpp
/vvp/vvp
/ivl.exp
/vvp/vvp.exp
# Check output
/check.vvp
-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
-101
View File
@@ -1,101 +0,0 @@
/*
* Copyright (c) 2000-2010 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* 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 "Attrib.h"
# include <cassert>
Attrib::Attrib()
{
nlist_ = 0;
list_ = 0;
}
Attrib::~Attrib()
{
delete[] list_;
}
const verinum& Attrib::attribute(perm_string key) const
{
for (unsigned idx = 0 ; idx < nlist_ ; idx += 1) {
if (key == list_[idx].key)
return list_[idx].val;
}
static const verinum null;
return null;
}
void Attrib::attribute(perm_string key, const verinum&value)
{
unsigned idx;
for (idx = 0 ; idx < nlist_ ; idx += 1) {
if (key == list_[idx].key) {
list_[idx].val = value;
return;
}
}
struct cell_*tmp = new struct cell_[nlist_+1];
for (idx = 0 ; idx < nlist_ ; idx += 1)
tmp[idx] = list_[idx];
tmp[nlist_].key = key;
tmp[nlist_].val = value;
nlist_ += 1;
delete[]list_;
list_ = tmp;
}
bool Attrib::has_compat_attributes(const Attrib&that) const
{
unsigned idx;
for (idx = 0 ; idx < that.nlist_ ; idx += 1) {
verinum tmp = attribute(that.list_[idx].key);
if (tmp != that.list_[idx].val)
return false;
}
return true;
}
unsigned Attrib::attr_cnt() const
{
return nlist_;
}
perm_string Attrib::attr_key(unsigned idx) const
{
assert(idx < nlist_);
return list_[idx].key;
}
const verinum& Attrib::attr_value(unsigned idx) const
{
assert(idx < nlist_);
return list_[idx].val;
}
-60
View File
@@ -1,60 +0,0 @@
#ifndef __Attrib_H
#define __Attrib_H
/*
* Copyright (c) 2000-2009 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 "StringHeap.h"
# include "verinum.h"
/*
* This class keeps a map of key/value pairs. The map can be set from
* an STL map, or by setting individual mappings.
*/
class Attrib {
public:
Attrib();
virtual ~Attrib();
const verinum&attribute(perm_string key) const;
void attribute(perm_string key, const verinum&value);
bool has_compat_attributes(const Attrib&that) const;
/* Provide a means of iterating over the entries in the map. */
unsigned attr_cnt() const;
perm_string attr_key(unsigned idx) const;
const verinum& attr_value(unsigned idx) const;
private:
struct cell_ {
perm_string key;
verinum val;
};
unsigned nlist_;
struct cell_*list_;
private: // not implemented
Attrib(const Attrib&);
Attrib& operator= (const Attrib&);
};
#endif
+58 -80
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
- anything else you think relevant.
- Library version, and
- anything else you think relevent.
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,62 +28,61 @@ 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).
You tell me that it fails to compile for you, and I find that it
compiles for me, then hooray I fixed it. It can happen, you
know. What's on my disk is more recent than the latest snapshot.
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,
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
* The Output is Correct, But Less Then Ideal
If the output is strictly correct, but just not good enough for
practical use, I would like to know. These sorts of problems are
likely to be more subjective than a core dump, but are worthy of
likely to be more subjective then a core dump, but are worthy of
consideration. However, realize that outright errors will get more
attention than missed optimizations.
attention then missed optimizations.
THE MAKING OF A GOOD TEST PROGRAM
@@ -93,45 +91,24 @@ 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
given.
So when you send a test case, ask yourself "Can poor overworked Steve
invoke the error without any Verilog other than what is included?" And
invoke the error without any Verilog other then 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.
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 bug database supports basic keyword searches, and you can
optionally limit your search to active bugs, or fixed bugs. You may
also browse the bug database, just to get an idea what is still
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.
make it all nice and legal.
HOW TO SEND PATCHES
@@ -139,26 +116,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-1999 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 +140,9 @@ 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.2 1999/08/06 04:05:28 steve Exp $
$Log: BUGS.txt,v $
Revision 1.2 1999/08/06 04:05:28 steve
Handle scope of parameters.
-502
View File
@@ -1,502 +0,0 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!
-93
View File
@@ -1,93 +0,0 @@
/*
* Copyright (c) 2001-2010 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* 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 "HName.h"
# include <iostream>
# include <cstring>
# include <cstdlib>
# include <climits>
hname_t::hname_t()
{
number_ = INT_MIN;
}
hname_t::hname_t(perm_string text)
{
name_ = text;
number_ = INT_MIN;
}
hname_t::hname_t(perm_string text, int num)
{
name_ = text;
number_ = num;
}
hname_t::hname_t(const hname_t&that)
{
name_ = that.name_;
number_ = that.number_;
}
hname_t& hname_t::operator = (const hname_t&that)
{
name_ = that.name_;
number_ = that.number_;
return *this;
}
bool operator < (const hname_t&l, const hname_t&r)
{
int cmp = strcmp(l.peek_name(), r.peek_name());
if (cmp < 0) return true;
if (cmp > 0) return false;
if (l.has_number() && r.has_number())
return l.peek_number() < r.peek_number();
else
return false;
}
bool operator == (const hname_t&l, const hname_t&r)
{
if (l.peek_name() == r.peek_name()) {
if (l.has_number() && r.has_number())
return l.peek_number() == r.peek_number();
else
return true;
}
return false;
}
ostream& operator<< (ostream&out, const hname_t&that)
{
if (that.peek_name() == 0) {
out << "";
return out;
}
out << that.peek_name();
if (that.has_number())
out << "[" << that.peek_number() << "]";
return out;
}
-105
View File
@@ -1,105 +0,0 @@
#ifndef __HName_H
#define __HName_H
/*
* Copyright (c) 2001-2010 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* 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 <iostream>
# include <list>
# include "StringHeap.h"
# include <climits>
#ifdef __GNUC__
#if __GNUC__ > 2
using namespace std;
#endif
#endif
/*
* This class represents a component of a Verilog hierarchical name. A
* hierarchical component contains a name string (represented here
* with a perm_string) and an optional signed number. This signed
* number is used if the scope is part of an array, for example an
* array of module instances or a loop generated scope.
*/
class hname_t {
public:
hname_t ();
explicit hname_t (perm_string text);
explicit hname_t (perm_string text, int num);
hname_t (const hname_t&that);
~hname_t();
hname_t& operator= (const hname_t&);
// Return the string part of the hname_t.
perm_string peek_name(void) const;
bool has_number() const;
int peek_number() const;
private:
perm_string name_;
// If the number is anything other than INT_MIN, then this is
// the numeric part of the name. Otherwise, it is not part of
// the name at all.
int number_;
private: // not implemented
};
inline hname_t::~hname_t()
{
}
inline perm_string hname_t::peek_name(void) const
{
return name_;
}
inline int hname_t::peek_number() const
{
return number_;
}
inline bool hname_t::has_number() const
{
return number_ != INT_MIN;
}
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 bool operator != (const hname_t&l, const hname_t&r)
{ return ! (l == r); }
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;
}
#endif
+76
View File
@@ -0,0 +1,76 @@
#ifndef __LineInfo_H
#define __LineInfo_H
/*
* Copyright (c) 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
* 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
*/
#if !defined(WINNT)
#ident "$Id: LineInfo.h,v 1.3 1999/02/15 02:06:15 steve Exp $"
#endif
# include <cstdio>
# include <string>
class LineInfo {
public:
LineInfo() : lineno_(0) { }
string get_line() const
{ char buf[8];
sprintf(buf, "%u", lineno_);
return file_ + ":" + buf;
}
void set_line(const LineInfo&that)
{ file_ = that.file_;
lineno_ = that.lineno_;
}
void set_file(const string&f) { file_ = f; }
void set_lineno(unsigned n) { lineno_ = n; }
private:
string file_;
unsigned lineno_;
};
/*
* $Log: LineInfo.h,v $
* Revision 1.3 1999/02/15 02:06:15 steve
* Elaborate gate ranges.
*
* Revision 1.2 1999/02/01 00:26:48 steve
* Carry some line info to the netlist,
* Dump line numbers for processes.
* Elaborate prints errors about port vector
* width mismatch
* Emit better handles null statements.
*
* Revision 1.1 1999/01/25 05:45:56 steve
* Add the LineInfo class to carry the source file
* location of things. PGate, Statement and PProcess.
*
* elaborate handles module parameter mismatches,
* missing or incorrect lvalues for procedural
* assignment, and errors are propogated to the
* top of the elaboration call tree.
*
* Attach line numbers to processes, gates and
* assignment statements.
*
*/
#endif
+81 -322
View File
@@ -3,7 +3,9 @@
# and/or modify it in source code form under the terms of the GNU
# Library General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version.
# any later version. In order to redistribute the software in
# binary form, you will need a Picture Elements Binary Software
# License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -16,369 +18,126 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.24.2.1 1999/12/03 17:43:49 steve Exp $"
#
#
SHELL = /bin/sh
# The interesting make targets are:
#
# make version
# Force the version_tag.h file to be rebuilt. Otherwise, it will only
# be built if it is missing.
#
# make all
# make install
#
# The "suffix" 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 configuration leaves suffix empty
suffix = @install_suffix@
VERSION = 0.0
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
datarootdir = @datarootdir@
SUBDIRS = ivlpp vhdlpp vvp vpi libveriuser cadpli tgt-null tgt-stub tgt-vvp \
tgt-vhdl tgt-vlog95 tgt-pcb driver
# Only run distclean for these directories.
NOTUSED = tgt-fpga tgt-pal tgt-verilog
VPATH = $(srcdir)
ifeq (@MINGW32@,yes)
SUBDIRS += driver-vpi
else
NOTUSED += driver-vpi
endif
# To get the version headers to build correctly we only want to look
# for C++ files in the source directory. All other files will require
# an explicit $(srcdir). The one exception to this is if we need to
# rebuild the lexor_keyword.cc file. If we do, then we want to use the
# local version instead of the one is $(srcdir).
vpath lexor_keyword.cc .
vpath %.cc $(srcdir)/libmisc
vpath %.cc $(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)
bindir = $(exec_prefix)/bin
libdir = $(exec_prefix)/lib
mandir = @mandir@
dllib=@DLLIB@
# For a cross compile these defines will need to be set accordingly.
HOSTCC = @CC@
HOSTCFLAGS = @WARNING_FLAGS@ @CFLAGS@
includedir = $(prefix)/include
CC = @CC@
CXX = @CXX@
DLLTOOL = @DLLTOOL@
INSTALL = @INSTALL@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
LEX = @LEX@
YACC = @YACC@
MAN = @MAN@
PS2PDF = @PS2PDF@
GIT = @GIT@
STRIP = @STRIP@
ifeq (@srcdir@,.)
INCLUDE_PATH = -I. -Ilibmisc
else
INCLUDE_PATH = -I. -Ilibmisc -I$(srcdir) -I$(srcdir)/libmisc
endif
CPPFLAGS = @CPPFLAGS@ @DEFS@
CXXFLAGS = @CXXFLAGS@ -I$(srcdir)
LDFLAGS = @LDFLAGS@
CPPFLAGS = @DEFS@ $(INCLUDE_PATH) @CPPFLAGS@
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@
PICFLAGS = @PICFLAG@
LDFLAGS = @rdynamic@ @LDFLAGS@
# Source files in the libmisc directory
M = LineInfo.o StringHeap.o
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o t-dll-analog.o
FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o
O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
elab_expr.o elaborate_analog.o elab_lval.o elab_net.o \
elab_scope.o elab_sig.o elab_sig_analog.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 \
netenum.o netstruct.o net_event.o net_expr.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_pclass.o pform_struct_type.o \
pform_types.o \
symbol_search.o sync.o sys_funcs.o verinum.o verireal.o target.o \
Attrib.o HName.o Module.o PClass.o PDelays.o PEvent.o PExpr.o PGate.o \
PGenerate.o PScope.o PSpec.o PTask.o PUdp.o PFunction.o PWire.o \
Statement.o AStatement.o $M $(FF) $(TT)
all: dep config.h _pli_types.h version_tag.h ivl@EXEEXT@ version.exe iverilog-vpi.man
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
# In the windows world, the installer will need a dosify program to
# dosify text files.
ifeq (@MINGW32@,yes)
all: dosify.exe
dosify.exe: $(srcdir)/dosify.c
$(HOSTCC) $(HOSTCFLAGS) -o dosify.exe $(srcdir)/dosify.c
endif
# This rule rules the compiler in the trivial hello.vl program to make
# sure the basics were compiled properly.
check: all
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
test -r check.conf || cp $(srcdir)/check.conf .
driver/iverilog -B. -BPivlpp -tcheck -ocheck.vvp $(srcdir)/examples/hello.vl
ifeq (@WIN32@,yes)
ifeq (@install_suffix@,)
vvp/vvp -M- -M./vpi ./check.vvp | grep 'Hello, World'
else
# On Windows if we have a suffix we must run the vvp part of
# the test with a suffix since it was built/linked that way.
ln vvp/vvp.exe vvp/vvp$(suffix).exe
vvp/vvp$(suffix) -M- -M./vpi ./check.vvp | grep 'Hello, World'
rm vvp/vvp$(suffix).exe
endif
else
vvp/vvp -M- -M./vpi ./check.vvp | grep 'Hello, World'
endif
all: ivl verilog
cd vpi ; $(MAKE) all
cd vvm ; $(MAKE) all
cd ivlpp ; $(MAKE) all
clean:
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
rm -f *.o parse.cc parse.h lexor.cc
rm -f ivl.exp iverilog-vpi.man iverilog-vpi.pdf iverilog-vpi.ps
rm -f parse.output syn-rules.output dosify.exe ivl@EXEEXT@ check.vvp
rm -f lexor_keyword.cc libivl.a libvpi.a iverilog-vpi syn-rules.cc
rm -rf dep
rm -f version.exe
rm -f *.o parse.cc parse.cc.output parse.h dep/*.d lexor.cc verilog
cd vpi ; $(MAKE) clean
cd vvm ; $(MAKE) clean
cd ivlpp ; $(MAKE) clean
distclean: clean
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
$(foreach dir,$(NOTUSED),$(MAKE) -C $(dir) $@ && ) true
rm -f Makefile config.status config.log config.cache
rm -f stamp-config-h config.h
rm -f stamp-_pli_types-h _pli_types.h
ifneq (@srcdir@,.)
rm -f version_tag.h check.conf
rmdir $(SUBDIRS) $(NOTUSED)
endif
rm -rf autom4te.cache
rm -f vpi/Makefile
rm -f vvm/Makefile
rm -f ivlpp/Makefile
rm -f config.status config.cache config.log
rm -f Makefile
cppcheck: $(O:.o=.cc) $(srcdir)/dosify.c $(srcdir)/version.c
cppcheck --enable=all -f --suppressions $(srcdir)/cppcheck.sup \
$(INCLUDE_PATH) $^
TT = t-null.o t-verilog.o t-vvm.o t-xnf.o
FF = nobufz.o propinit.o sigfold.o xnfio.o xnfsyn.o
cppcheck-all:
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) cppcheck && ) true
$(foreach dir,$(NOTUSED),$(MAKE) -C $(dir) cppcheck && ) true
$(MAKE) cppcheck
O = main.o cprop.o design_dump.o elaborate.o elab_expr.o emit.o eval.o \
eval_tree.o functor.o \
lexor.o lexor_keyword.o mangle.o netlist.o pad_to_width.o \
parse.o parse_misc.o pform.o pform_dump.o \
set_width.o \
verinum.o verireal.o target.o targets.o Module.o PDelays.o PExpr.o PGate.o \
PTask.o PFunction.o PWire.o Statement.o \
$(FF) $(TT)
Makefile: $(srcdir)/Makefile.in config.status
./config.status --file=$@
dep:
mkdir dep
stamp-config-h: $(srcdir)/config.h.in config.status
@rm -f $@
./config.status config.h
config.h: stamp-config-h
stamp-_pli_types-h: $(srcdir)/_pli_types.h.in config.status
@rm -f $@
./config.status _pli_types.h
_pli_types.h: stamp-_pli_types-h
$(srcdir)/configure: $(srcdir)/configure.in $(srcdir)/aclocal.m4
cd $(srcdir) && autoconf
config.status: $(srcdir)/configure
./config.status --recheck
Makefile: Makefile.in config.status
./config.status
ifeq (@WIN32@,yes)
# Under Windows (mingw) I need to make the ivl.exe in two steps.
# The first step makes an ivl.exe that dlltool can use to make an
# export and import library, and the last link makes a, ivl.exe
# that really exports the things that the import library imports.
ivl@EXEEXT@: $O $(srcdir)/ivl.def
$(CXX) -o ivl@EXEEXT@ $O $(dllib) @EXTRALIBS@
$(DLLTOOL) --dllname ivl@EXEEXT@ --def $(srcdir)/ivl.def \
--output-lib libivl.a --output-exp ivl.exp
$(CXX) $(LDFLAGS) -o ivl@EXEEXT@ ivl.exp $O $(dllib) @EXTRALIBS@
else
ivl@EXEEXT@: $O
$(CXX) $(LDFLAGS) -o ivl@EXEEXT@ $O $(dllib)
endif
# Make the actual verilog program from the script template. This
# simply invloves editing the substitution strings in the script into
# the configured copy.
tmp1 = bindir
tmp2 = libdir
tmp3 = includedir
tmp4 = CXX
verilog: $(srcdir)/verilog.sh
sed -e 's;@$(tmp1)@;@bindir@;' \
-e 's;@$(tmp2)@;@libdir@;' \
-e 's;@$(tmp3)@;@includedir@;' \
-e 's;@$(tmp4)@;@CXX@;' < $< > $@
ifeq (@MINGW32@,no)
all: iverilog-vpi
ivl: $O
$(CXX) $(CXXFLAGS) -o ivl $O
iverilog-vpi: $(srcdir)/iverilog-vpi.sh Makefile
sed -e 's;@SHARED@;@shared@;' -e 's;@PIC@;@PICFLAG@;' \
-e 's;@SUFFIX@;$(suffix);' \
-e 's;@IVCC@;$(CC);' \
-e 's;@IVCXX@;$(CXX);' \
-e 's;@IVCFLAGS@;$(CFLAGS);' \
-e 's;@IVCXXFLAGS@;$(CXXFLAGS);' \
-e 's;@INCLUDEDIR@;$(includedir);' \
-e 's;@LIBDIR@;@libdir@;' $< > $@
chmod +x $@
endif
version.exe: $(srcdir)/version.c $(srcdir)/version_base.h version_tag.h
$(HOSTCC) $(HOSTCFLAGS) -o version.exe -I. -I$(srcdir) $(srcdir)/version.c
%.o: %.cc config.h
$(CXX) $(CPPFLAGS) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o
%.o dep/%.d: %.cc
@[ -d dep ] || mkdir dep
$(CXX) $(CXXFLAGS) -MD -c $< -o $*.o
mv $*.d dep/$*.d
# Here are some explicit dependencies needed to get things going.
main.o: main.cc version_tag.h
lexor.o: lexor.cc parse.h
lexor.o dep/lexor.d: lexor.cc parse.h
parse.o: parse.cc
parse.o dep/parse.d: parse.cc
# Build this in two steps to avoid parallel build issues (see pr3462585)
parse.cc: $(srcdir)/parse.y
$(YACC) --verbose -t -p VL -d -o $@ $<
parse.h: parse.cc
mv parse.cc.h $@ 2>/dev/null || mv parse.hh $@
syn-rules.cc: $(srcdir)/syn-rules.y
$(YACC) --verbose -t -p syn_ -o $@ $<
parse.h parse.cc: $(srcdir)/parse.y
bison --verbose -t -p VL -d $(srcdir)/parse.y -o parse.cc
mv parse.cc.h parse.h
lexor.cc: $(srcdir)/lexor.lex
$(LEX) -s -t $< > $@
flex -PVL -s -olexor.cc $(srcdir)/lexor.lex
lexor_keyword.o: lexor_keyword.cc parse.h
install: all installdirs $(bindir)/verilog $(libdir)/ivl/ivl $(mandir)/man1/verilog.1
cd vpi ; $(MAKE) install
cd vvm ; $(MAKE) install
cd ivlpp ; $(MAKE) install
lexor_keyword.cc: $(srcdir)/lexor_keyword.gperf
gperf -o -i 7 -C -k 1-4,6,9,$$ -L ANSI-C -H keyword_hash -N check_identifier -t $(srcdir)/lexor_keyword.gperf > lexor_keyword.cc || (rm -f lexor_keyword.cc ; false)
$(bindir)/verilog: ./verilog
$(INSTALL_PROGRAM) ./verilog $(bindir)/verilog
iverilog-vpi.man: $(srcdir)/iverilog-vpi.man.in version.exe
./version.exe `head -1 $(srcdir)/iverilog-vpi.man.in`'\n' > $@
tail -n +2 $(srcdir)/iverilog-vpi.man.in >> $@
$(libdir)/ivl/ivl: ivl
$(INSTALL_PROGRAM) ./ivl $(libdir)/ivl/ivl
$(STRIP) $(libdir)/ivl/ivl
iverilog-vpi.ps: iverilog-vpi.man
$(MAN) -t ./iverilog-vpi.man > iverilog-vpi.ps
$(mandir)/man1/verilog.1: $(srcdir)/verilog.1
$(INSTALL_DATA) $(srcdir)/verilog.1 $(mandir)/man1/verilog.1
iverilog-vpi.pdf: iverilog-vpi.ps
$(PS2PDF) iverilog-vpi.ps iverilog-vpi.pdf
# For VERSION_TAG in driver/main.c, first try git-describe, then look for a
# version_tag.h file in the source tree (included in snapshots and releases),
# and finally use nothing.
# "true" and "false" in the next few lines are Unix shell command names
ifeq ($(GIT),none)
GIT_PRESENT = false
else
GIT_PRESENT = true
endif
version_tag.h version:
@if $(GIT_PRESENT) && test -d $(srcdir)/.git; then \
echo "Using git-describe for VERSION_TAG"; \
tmp=`$(GIT) --git-dir $(srcdir)/.git describe --always --dirty \
| sed -e 's;\(.*\);#define VERSION_TAG "\1";'`; \
echo "$$tmp" | diff - version_tag.h > /dev/null 2>&1 || echo "$$tmp" > version_tag.h || exit 1; \
elif test -r $(srcdir)/version_tag.h; then \
echo "Using $(srcdir)/version_tag.h for VERSION_TAG"; \
diff $(srcdir)/version_tag.h version_tag.h > /dev/null 2>&1 || cp $(srcdir)/version_tag.h version_tag.h; \
else \
echo "Using empty VERSION_TAG"; \
echo '#define VERSION_TAG ""' > version_tag.h; \
fi
ifeq (@MINGW32@,yes)
ifeq ($(MAN),none)
INSTALL_DOC = $(mandir)/man1/iverilog-vpi$(suffix).1
else
ifeq ($(PS2PDF),none)
INSTALL_DOC = $(mandir)/man1/iverilog-vpi$(suffix).1
else
INSTALL_DOC = $(prefix)/iverilog-vpi$(suffix).pdf $(mandir)/man1/iverilog-vpi$(suffix).1
all: dep iverilog-vpi.pdf
endif
endif
INSTALL_DOCDIR = $(mandir)/man1
else
INSTALL_DOC = $(mandir)/man1/iverilog-vpi$(suffix).1
INSTALL_DOCDIR = $(mandir)/man1
endif
ifeq (@MINGW32@,yes)
WIN32_INSTALL =
else
WIN32_INSTALL = $(bindir)/iverilog-vpi$(suffix)
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)/sv_vpi_user.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
$(bindir)/iverilog-vpi$(suffix): ./iverilog-vpi
$(INSTALL_SCRIPT) ./iverilog-vpi "$(DESTDIR)$(bindir)/iverilog-vpi$(suffix)"
$(libdir)/ivl$(suffix)/ivl@EXEEXT@: ./ivl@EXEEXT@
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ "$(DESTDIR)$(libdir)/ivl$(suffix)/ivl@EXEEXT@"
$(libdir)/ivl$(suffix)/include/constants.vams: $(srcdir)/constants.vams
$(INSTALL_DATA) $(srcdir)/constants.vams "$(DESTDIR)$(libdir)/ivl$(suffix)/include/constants.vams"
$(libdir)/ivl$(suffix)/include/disciplines.vams: $(srcdir)/disciplines.vams
$(INSTALL_DATA) $(srcdir)/disciplines.vams "$(DESTDIR)$(libdir)/ivl$(suffix)/include/disciplines.vams"
$(includedir)/ivl_target.h: $(srcdir)/ivl_target.h
$(INSTALL_DATA) $(srcdir)/ivl_target.h "$(DESTDIR)$(includedir)/ivl_target.h"
$(includedir)/_pli_types.h: _pli_types.h
$(INSTALL_DATA) $< "$(DESTDIR)$(includedir)/_pli_types.h"
$(includedir)/sv_vpi_user.h: $(srcdir)/sv_vpi_user.h
$(INSTALL_DATA) $(srcdir)/sv_vpi_user.h "$(DESTDIR)$(includedir)/sv_vpi_user.h"
$(includedir)/vpi_user.h: $(srcdir)/vpi_user.h
$(INSTALL_DATA) $(srcdir)/vpi_user.h "$(DESTDIR)$(includedir)/vpi_user.h"
$(includedir)/acc_user.h: $(srcdir)/acc_user.h
$(INSTALL_DATA) $(srcdir)/acc_user.h "$(DESTDIR)$(includedir)/acc_user.h"
$(includedir)/veriuser.h: $(srcdir)/veriuser.h
$(INSTALL_DATA) $(srcdir)/veriuser.h "$(DESTDIR)$(includedir)/veriuser.h"
$(mandir)/man1/iverilog-vpi$(suffix).1: iverilog-vpi.man
$(INSTALL_DATA) iverilog-vpi.man "$(DESTDIR)$(mandir)/man1/iverilog-vpi$(suffix).1"
$(prefix)/iverilog-vpi$(suffix).pdf: iverilog-vpi.pdf
$(INSTALL_DATA) iverilog-vpi.pdf "$(DESTDIR)$(prefix)/iverilog-vpi$(suffix).pdf"
installdirs: $(srcdir)/mkinstalldirs
$(srcdir)/mkinstalldirs "$(DESTDIR)$(bindir)" \
"$(DESTDIR)$(includedir)" \
"$(DESTDIR)$(libdir)/ivl$(suffix)" \
"$(DESTDIR)$(libdir)/ivl$(suffix)/include" \
"$(DESTDIR)$(mandir)" \
"$(DESTDIR)$(mandir)/man1"
installdirs: mkinstalldirs
$(srcdir)/mkinstalldirs $(bindir) $(mandir)/man1
uninstall:
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
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@; \
do rm -f "$(DESTDIR)$(bindir)/$$f"; done
for f in ivl_target.h vpi_user.h _pli_types.h sv_vpi_user.h acc_user.h veriuser.h; \
do rm -f "$(DESTDIR)$(includedir)/$$f"; done
-test X$(suffix) = X || rmdir "$(DESTDIR)/$(includedir)"
rm -f "$(DESTDIR)$(mandir)/man1/iverilog-vpi$(suffix).1" "$(DESTDIR)$(prefix)/iverilog-vpi$(suffix).pdf"
rm -f $(bindir)/ivl
rm -f $(bindir)/verilog
rm -f $(mandir)/man1/verilog.1
cd vpi ; $(MAKE) uninstall
cd vvm ; $(MAKE) uninstall
cd ivlpp ; $(MAKE) uninstall
-include $(patsubst %.o, dep/%.d, $O)
+79 -58
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2010 Stephen Williams ([email protected])
* Copyright (c) 1998 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,31 +16,26 @@
* 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"
#if !defined(WINNT)
#ident "$Id: Module.cc,v 1.7 1999/09/17 02:06:25 steve Exp $"
#endif
# include "Module.h"
# include "PGate.h"
# include "PWire.h"
# include <cassert>
list<Module::named_expr_t> Module::user_defparms;
/* n is a permallocated string. */
Module::Module(perm_string n)
: PScopeExtra(n)
{
library_flag = false;
is_cell = false;
uc_drive = UCD_NONE;
timescale_warn_done = false;
time_unit = 0;
time_precision = 0;
time_from_timescale = false;
}
Module::~Module()
Module::Module(const string&name, const svector<Module::port_t*>*pp)
: name_(name)
{
if (pp) {
ports_ = *pp;
for (unsigned idx = 0 ; idx < ports_.count() ; idx += 1) {
port_t*cur = ports_[idx];
if (cur == 0)
continue;
for (unsigned jdx = 0 ; jdx < cur->wires.count() ; jdx += 1)
add_wire(cur->wires[jdx]);
}
}
}
void Module::add_gate(PGate*gate)
@@ -48,61 +43,87 @@ void Module::add_gate(PGate*gate)
gates_.push_back(gate);
}
void Module::add_task(const string&name, PTask*task)
{
tasks_[name] = task;
}
void Module::add_function(const string &name, PFunction *func)
{
funcs_[name] = func;
}
void Module::add_wire(PWire*wire)
{
wires_.push_back(wire);
}
void Module::add_behavior(PProcess*b)
{
behaviors_.push_back(b);
}
unsigned Module::port_count() const
{
return ports.size();
return ports_.count();
}
/*
* Return the array of PEIdent object that are at this port of the
* module. If the port is internally unconnected, return an empty
* array.
*/
const vector<PEIdent*>& Module::get_port(unsigned idx) const
const svector<PWire*>& Module::get_port(unsigned idx) const
{
assert(idx < ports.size());
static const vector<PEIdent*> zero;
if (ports[idx])
return ports[idx]->expr;
else
return zero;
assert(idx < ports_.count());
return ports_[idx]->wires;
}
unsigned Module::find_port(const char*name) const
unsigned Module::find_port(const string&name) const
{
assert(name != 0);
for (unsigned idx = 0 ; idx < ports.size() ; idx += 1) {
if (ports[idx] == 0) {
/* It is possible to have undeclared ports. These
are ports that are skipped in the declaration,
for example like so: module foo(x ,, y); The
port between x and y is unnamed and thus
inaccessible to binding by name. */
continue;
}
assert(ports[idx]);
if (ports[idx]->name == name)
assert(name != "");
for (unsigned idx = 0 ; idx < ports_.count() ; idx += 1)
if (ports_[idx]->name == name)
return idx;
}
return ports.size();
return ports_.count();
}
PGate* Module::get_gate(perm_string name)
PWire* Module::get_wire(const string&name)
{
for (list<PGate*>::iterator cur = gates_.begin()
; cur != gates_.end() ; ++ cur ) {
for (list<PWire*>::iterator cur = wires_.begin()
; cur != wires_.end()
; cur ++ ) {
if ((*cur)->get_name() == name)
if ((*cur)->name() == name)
return *cur;
}
return 0;
}
const list<PGate*>& Module::get_gates() const
{
return gates_;
}
/*
* $Log: Module.cc,v $
* Revision 1.7 1999/09/17 02:06:25 steve
* Handle unconnected module ports.
*
* Revision 1.6 1999/08/04 02:13:02 steve
* Elaborate module ports that are concatenations of
* module signals.
*
* Revision 1.5 1999/08/03 04:14:49 steve
* Parse into pform arbitrarily complex module
* port declarations.
*
* Revision 1.4 1999/07/31 19:14:47 steve
* Add functions up to elaboration (Ed Carter)
*
* Revision 1.3 1999/07/03 02:12:51 steve
* Elaborate user defined tasks.
*
* Revision 1.2 1999/06/17 05:34:42 steve
* Clean up interface of the PWire class,
* Properly match wire ranges.
*
* Revision 1.1 1998/11/03 23:28:51 steve
* Introduce verilog to CVS.
*
*/
+84 -74
View File
@@ -1,7 +1,7 @@
#ifndef __Module_H
#define __Module_H
/*
* Copyright (c) 1998-2010 Stephen Williams ([email protected])
* Copyright (c) 1998 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,24 +18,16 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: Module.h,v 1.10 1999/11/27 19:07:57 steve Exp $"
#endif
# include <list>
# include <map>
# include <vector>
# include <utility>
# include "StringHeap.h"
# include "HName.h"
# include "named.h"
# include "PScope.h"
# include "LineInfo.h"
# include "netlist.h"
# include "pform_types.h"
# include "svector.h"
# include <string>
class PExpr;
class PEIdent;
class PGate;
class PGenerate;
class PSpecPath;
class PTask;
class PFunction;
class PWire;
@@ -49,7 +41,7 @@ class NetScope;
* therefore the handle for grasping the described circuit.
*/
class Module : public PScopeExtra, public LineInfo {
class Module {
/* The module ports are in general a vector of port_t
objects. Each port has a name and an ordered list of
@@ -58,39 +50,20 @@ class Module : public PScopeExtra, public LineInfo {
the port. */
public:
struct port_t {
perm_string name;
vector<PEIdent*> expr;
string name;
svector<PWire*>wires;
port_t(int c=0) : wires(c) { }
};
public:
/* The name passed here is the module name, not the instance
name. This make must be a permallocated string. */
explicit Module(perm_string name);
~Module();
explicit Module(const string&name, const svector<port_t*>*);
/* Initially false. This is set to true if the module has been
declared as a library module. This makes the module
ineligible for being chosen as an implicit root. It has no
other effect. */
bool library_flag;
bool is_cell;
enum UCDriveType { UCD_NONE, UCD_PULL0, UCD_PULL1 };
UCDriveType uc_drive;
/* specparams are simpler than other params, in that they have
no type information. They are merely constant
expressions. */
map<perm_string,PExpr*>specparams;
/* The module also has defparam assignments which don't create
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;
static list<named_expr_t>user_defparms;
/* The module has parameters that are evaluated when the
module is elaborated. During parsing, I put the parameters
into this map. */
map<string,PExpr*>parameters;
/* Parameters may be overridden at instantiation time;
the overrides do not contain explicit parameter names,
@@ -98,53 +71,90 @@ class Module : public PScopeExtra, public LineInfo {
appear in the instantiated module. Therefore a
list of names in module-order is needed to pass from
a parameter-index to its name. */
list<perm_string> param_names;
list<string> param_names;
/* This is an array of port descriptors, which is in turn a
named array of PEident pointers. */
vector<port_t*> ports;
map<perm_string,PExpr*> attributes;
/* These are the timescale for this module. The default is
set by the `timescale directive. */
int time_unit, time_precision;
bool time_from_timescale;
bool timescale_warn_done;
/* The module has a list of generate schemes that appear in
the module definition. These are used at elaboration time. */
list<PGenerate*> generate_schemes;
list<PSpecPath*> specify_paths;
// The mod_name() is the name of the module type.
perm_string mod_name() const { return pscope_name(); }
const string&get_name() const { return name_; }
void add_gate(PGate*gate);
void add_wire(PWire*wire);
void add_behavior(PProcess*behave);
void add_task(const string&name, PTask*def);
void add_function(const string&name, PFunction*def);
unsigned port_count() const;
const vector<PEIdent*>& get_port(unsigned idx) const;
unsigned find_port(const char*name) const;
const svector<PWire*>& get_port(unsigned idx) const;
unsigned find_port(const string&) const;
PGate* get_gate(perm_string name);
// Find a wire by name. This is used for connecting gates to
// existing wires, etc.
PWire* get_wire(const string&name);
const list<PGate*>& get_gates() const;
const list<PWire*>& get_wires() const { return wires_; }
const list<PGate*>& get_gates() const { return gates_; }
const list<PProcess*>& get_behaviors() const { return behaviors_; }
void dump(ostream&out) const;
bool elaborate(Design*, NetScope*scope) const;
typedef map<perm_string,PExpr*> replace_t;
bool elaborate_scope(Design*, NetScope*scope, const replace_t&rep);
bool elaborate_sig(Design*, NetScope*scope) const;
bool elaborate(Design*, NetScope*scope, svector<PExpr*>*overrides_) const;
private:
const string name_;
svector<port_t*> ports_;
list<PWire*> wires_;
list<PGate*> gates_;
list<PProcess*> behaviors_;
map<string,PTask*> tasks_;
map<string,PFunction*> funcs_;
private: // Not implemented
Module(const Module&);
Module& operator= (const Module&);
};
/*
* $Log: Module.h,v $
* Revision 1.10 1999/11/27 19:07:57 steve
* Support the creation of scopes.
*
* Revision 1.9 1999/08/23 16:48:39 steve
* Parameter overrides support from Peter Monta
* AND and XOR support wide expressions.
*
* Revision 1.8 1999/08/04 02:13:02 steve
* Elaborate module ports that are concatenations of
* module signals.
*
* Revision 1.7 1999/08/03 04:14:49 steve
* Parse into pform arbitrarily complex module
* port declarations.
*
* Revision 1.6 1999/07/31 19:14:47 steve
* Add functions up to elaboration (Ed Carter)
*
* Revision 1.5 1999/07/03 02:12:51 steve
* Elaborate user defined tasks.
*
* Revision 1.4 1999/06/15 03:44:53 steve
* Get rid of the STL vector template.
*
* Revision 1.3 1999/02/21 17:01:57 steve
* Add support for module parameters.
*
* Revision 1.2 1999/01/25 05:45:56 steve
* Add the LineInfo class to carry the source file
* location of things. PGate, Statement and PProcess.
*
* elaborate handles module parameter mismatches,
* missing or incorrect lvalues for procedural
* assignment, and errors are propogated to the
* top of the elaboration call tree.
*
* Attach line numbers to processes, gates and
* assignment statements.
*
* Revision 1.1 1998/11/03 23:28:52 steve
* Introduce verilog to CVS.
*
*/
#endif
-30
View File
@@ -1,30 +0,0 @@
/*
* Copyright (c) 2012 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* 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 "PClass.h"
PClass::PClass(perm_string name, LexicalScope*parent)
: PScopeExtra(name, parent)
{
}
PClass::~PClass()
{
}
-40
View File
@@ -1,40 +0,0 @@
#ifndef __PClass_H
#define __PClass_H
/*
* Copyright (c) 2012 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* 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 "PScope.h"
# include "LineInfo.h"
# include "StringHeap.h"
/*
* SystemVerilog supports class declarations with their own lexical
* scope, etc. The parser arranges for these to be created and
* collected.
*/
class PClass : public PScopeExtra, public LineInfo {
public:
explicit PClass (perm_string name, LexicalScope*parent);
~PClass();
};
#endif
+39 -136
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2011 Stephen Williams ([email protected])
* Copyright (c) 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,34 +16,24 @@
* 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 <iostream>
#if !defined(WINNT)
#ident "$Id: PDelays.cc,v 1.1 1999/09/04 19:11:46 steve Exp $"
#endif
# include "PDelays.h"
# include "PExpr.h"
# include "verinum.h"
# include "netmisc.h"
bool dly_used_no_timescale = false;
bool dly_used_timescale = false;
bool display_ts_dly_warning = true;
PDelays::PDelays()
{
delete_flag_ = true;
for (unsigned idx = 0 ; idx < 3 ; idx += 1)
delay_[idx] = 0;
}
PDelays::~PDelays()
{
if (delete_flag_) {
for (unsigned idx = 0 ; idx < 3 ; idx += 1)
delete delay_[idx];
}
for (unsigned idx = 0 ; idx < 3 ; idx += 1)
delete delay_[idx];
}
void PDelays::set_delay(PExpr*del)
@@ -51,141 +41,46 @@ void PDelays::set_delay(PExpr*del)
assert(del);
assert(delay_[0] == 0);
delay_[0] = del;
delete_flag_ = true;
}
void PDelays::set_delays(const list<PExpr*>*del, bool df)
void PDelays::set_delays(const svector<PExpr*>*del)
{
assert(del);
assert(del->size() <= 3);
list<PExpr*>::const_iterator cur = del->begin();
for (unsigned idx = 0 ; cur != del->end() ; idx += 1, ++cur)
delay_[idx] = *cur;
delete_flag_ = df;
assert(del->count() <= 3);
for (unsigned idx = 0 ; idx < del->count() ; idx += 1)
delay_[idx] = (*del)[idx];
}
unsigned PDelays::delay_count() const
void PDelays::eval_delays(Design*des, const string&path,
unsigned long&rise_time,
unsigned long&fall_time,
unsigned long&decay_time) const
{
unsigned dly_cnt = 0;
for (unsigned idx = 0 ; idx < 3 ; idx += 1)
if (delay_[idx]) dly_cnt += 1;
return dly_cnt;
}
static NetExpr*calculate_val(Design*des, NetScope*scope, PExpr*expr)
{
NetExpr*dex = elab_and_eval(des, scope, expr, -1);
/* Print a warning if we find default and `timescale based
* delays in the design, since this is likely an error. */
if (scope->time_from_timescale()) dly_used_timescale = true;
else dly_used_no_timescale = true;
if (display_ts_dly_warning &&
dly_used_no_timescale && dly_used_timescale) {
cerr << "warning: Found both default and "
"`timescale based delays. Use" << endl;
cerr << " -Wtimescale to find the "
"module(s) with no `timescale." << endl;
display_ts_dly_warning = false;
}
/* If the delay expression is a real constant or vector
constant, then evaluate it, scale it to the local time
units, and return an adjusted value. */
if (NetECReal*tmp = dynamic_cast<NetECReal*>(dex)) {
uint64_t delay = get_scaled_time_from_real(des, scope, tmp);
delete tmp;
NetEConst*tmp2 = new NetEConst(verinum(delay, 64));
tmp2->set_line(*expr);
return tmp2;
}
if (NetEConst*tmp = dynamic_cast<NetEConst*>(dex)) {
verinum fn = tmp->value();
uint64_t delay = des->scale_to_precision(fn.as_ulong64(), scope);
delete tmp;
NetEConst*tmp2 = new NetEConst(verinum(delay, 64));
tmp2->set_line(*expr);
return tmp2;
}
/* Oops, cannot evaluate down to a constant. */
return dex;
}
static NetExpr* make_delay_nets(Design*des, NetScope*scope, NetExpr*expr)
{
if (expr == 0)
return 0;
if (dynamic_cast<NetESignal*> (expr))
return expr;
if (dynamic_cast<NetEConst*> (expr))
return expr;
NetNet*sig = expr->synthesize(des, scope, expr);
if (sig == 0) {
cerr << expr->get_fileline() << ": error: Expression " << *expr
<< " is not suitable as a delay expression." << endl;
des->errors += 1;
return 0;
}
expr = new NetESignal(sig);
return expr;
}
static NetExpr* calc_decay_time(NetExpr *rise, NetExpr *fall)
{
NetEConst *c_rise = dynamic_cast<NetEConst*>(rise);
NetEConst *c_fall = dynamic_cast<NetEConst*>(fall);
if (c_rise && c_fall) {
if (c_rise->value() < c_fall->value()) return rise;
else return fall;
}
return 0;
}
void PDelays::eval_delays(Design*des, NetScope*scope,
NetExpr*&rise_time,
NetExpr*&fall_time,
NetExpr*&decay_time,
bool as_nets_flag) const
{
assert(scope);
verinum*dv;
if (delay_[0]) {
rise_time = calculate_val(des, scope, delay_[0]);
if (as_nets_flag)
rise_time = make_delay_nets(des, scope, rise_time);
dv = delay_[0]->eval_const(des, path);
assert(dv);
rise_time = dv->as_ulong();
delete dv;
if (delay_[1]) {
fall_time = calculate_val(des, scope, delay_[1]);
if (as_nets_flag)
fall_time = make_delay_nets(des, scope, fall_time);
dv = delay_[1]->eval_const(des, path);
assert(dv);
fall_time = dv->as_ulong();
delete dv;
if (delay_[2]) {
decay_time = calculate_val(des, scope, delay_[2]);
if (as_nets_flag)
decay_time = make_delay_nets(des, scope,
decay_time);
dv = delay_[2]->eval_const(des, path);
assert(dv);
decay_time = dv->as_ulong();
delete dv;
} else {
// If this is zero then we need to do the min()
// at run time.
decay_time = calc_decay_time(rise_time, fall_time);
if (rise_time < fall_time)
decay_time = rise_time;
else
decay_time = fall_time;
}
} else {
assert(delay_[2] == 0);
@@ -198,3 +93,11 @@ void PDelays::eval_delays(Design*des, NetScope*scope,
decay_time = 0;
}
}
/*
* $Log: PDelays.cc,v $
* Revision 1.1 1999/09/04 19:11:46 steve
* Add support for delayed non-blocking assignments.
*
*/
+16 -24
View File
@@ -1,7 +1,7 @@
#ifndef __PDelays_H
#define __PDelays_H
/*
* Copyright (c) 1999-2010 Stephen Williams ([email protected])
* Copyright (c) 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
@@ -18,22 +18,15 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: PDelays.h,v 1.1 1999/09/04 19:11:46 steve Exp $"
#endif
# include "svector.h"
# include <string>
# include <list>
# include <iostream>
#ifdef __GNUC__
#if __GNUC__ > 2
using namespace std;
#endif
#endif
class Design;
class NetScope;
class NetExpr;
class PExpr;
class ostream;
/*
* Various PForm objects can carry delays. These delays include rise,
@@ -45,25 +38,18 @@ class PDelays {
PDelays();
~PDelays();
/* Set the delay expressions. If the delete_flag is true, then
this object takes ownership of the expressions, and will
delete it in the destructor. */
void set_delay(PExpr*);
void set_delays(const list<PExpr*>*del, bool delete_flag=true);
void set_delays(const svector<PExpr*>*del);
unsigned delay_count() const;
void eval_delays(Design*des, NetScope*scope,
NetExpr*&rise_time,
NetExpr*&fall_time,
NetExpr*&decay_time,
bool as_nets_flag =false) const;
void eval_delays(Design*des, const string&path,
unsigned long&rise_time,
unsigned long&fall_time,
unsigned long&decay_time) const;
void dump_delays(ostream&out) const;
private:
PExpr* delay_[3];
bool delete_flag_;
private: // not implemented
PDelays(const PDelays&);
@@ -72,4 +58,10 @@ class PDelays {
ostream& operator << (ostream&o, const PDelays&);
/*
* $Log: PDelays.h,v $
* Revision 1.1 1999/09/04 19:11:46 steve
* Add support for delayed non-blocking assignments.
*
*/
#endif
-54
View File
@@ -1,54 +0,0 @@
#ifndef __PEvent_H
#define __PEvent_H
/*
* Copyright (c) 2000-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
* 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 "LineInfo.h"
# include "StringHeap.h"
# include <string>
class Design;
class NetScope;
/*
* The PEvent class represents event objects. These are things that
* are declared in Verilog as ``event foo;'' The name passed to the
* constructor is the "foo" part of the declaration.
*/
class PEvent : public LineInfo {
public:
// The name is a perm-allocated string. It is the simple name
// of the event, without any scope.
explicit PEvent(perm_string name);
~PEvent();
perm_string name() const;
void elaborate_scope(Design*des, NetScope*scope) const;
private:
perm_string name_;
private: // not implemented
PEvent(const PEvent&);
PEvent& operator= (const PEvent&);
};
#endif
+83 -375
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2012 Stephen Williams <[email protected]>
* Copyright (c) 1998 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,220 +16,66 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: PExpr.cc,v 1.11 1999/10/31 04:11:27 steve Exp $"
#endif
# include "config.h"
# include <iostream>
# include "compiler.h"
# include "PExpr.h"
# include "PWire.h"
# include "Module.h"
# include "netmisc.h"
# include "util.h"
# include <typeinfo>
PExpr::PExpr()
{
expr_type_ = IVL_VT_NO_TYPE;
expr_width_ = 0;
min_width_ = 0;
signed_flag_ = false;
}
PExpr::~PExpr()
{
}
void PExpr::declare_implicit_nets(LexicalScope*, NetNet::Type)
{
}
bool PExpr::has_aa_term(Design*, NetScope*) const
{
return false;
}
bool PExpr::is_the_same(const PExpr*that) const
{
return typeid(this) == typeid(that);
}
NetNet* PExpr::elaborate_lnet(Design*, NetScope*) const
{
cerr << get_fileline() << ": error: "
<< "expression not valid in assign l-value: "
<< *this << endl;
return 0;
}
NetNet* PExpr::elaborate_bi_net(Design*, NetScope*) const
{
cerr << get_fileline() << ": error: "
<< "expression not valid as argument to inout port: "
<< *this << endl;
return 0;
}
bool PExpr::is_collapsible_net(Design*, NetScope*) const
bool PExpr::is_constant(Module*) const
{
return false;
}
PEBinary::PEBinary(char op, PExpr*l, PExpr*r)
: op_(op), left_(l), right_(r)
NetNet* PExpr::elaborate_net(Design*des, const string&path, unsigned,
unsigned long,
unsigned long,
unsigned long) const
{
cerr << "Don't know how to elaborate `" << *this
<< "' as gates." << endl;
return 0;
}
PEBinary::~PEBinary()
NetNet* PExpr::elaborate_lnet(Design*des, const string&path) const
{
cerr << get_line() << ": expression not valid in assign l-value: "
<< *this << endl;
return 0;
}
void PEBinary::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
bool PEBinary::is_constant(Module*mod) const
{
assert(left_ && right_);
left_->declare_implicit_nets(scope, type);
right_->declare_implicit_nets(scope, type);
return left_->is_constant(mod) && right_->is_constant(mod);
}
bool PEBinary::has_aa_term(Design*des, NetScope*scope) const
PECallFunction::PECallFunction(const string &n, const svector<PExpr *> &parms)
: name_(n), parms_(parms)
{
assert(left_ && right_);
return left_->has_aa_term(des, scope) || right_->has_aa_term(des, scope);
}
PECastSize::PECastSize(unsigned si, PExpr*b)
: size_(si), base_(b)
{
}
PECastSize::~PECastSize()
{
}
PEBComp::PEBComp(char op, PExpr*l, PExpr*r)
: PEBinary(op, l, r)
{
l_width_ = 0;
r_width_ = 0;
}
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)
{
}
PEBShift::~PEBShift()
{
}
PECallFunction::PECallFunction(const pform_name_t&n, const vector<PExpr *> &parms)
: path_(n), parms_(parms)
{
}
static pform_name_t pn_from_ps(perm_string n)
{
name_component_t tmp_name (n);
pform_name_t tmp;
tmp.push_back(tmp_name);
return tmp;
}
PECallFunction::PECallFunction(perm_string n, const vector<PExpr*>&parms)
: path_(pn_from_ps(n)), parms_(parms)
{
}
PECallFunction::PECallFunction(perm_string n)
: path_(pn_from_ps(n))
{
}
// NOTE: Anachronism. Try to work all use of svector out.
PECallFunction::PECallFunction(const pform_name_t&n, const list<PExpr *> &parms)
: path_(n), parms_(parms.size())
{
int tmp_idx = 0;
assert(parms_.size() == parms.size());
for (list<PExpr*>::const_iterator idx = parms.begin()
; idx != parms.end() ; ++idx)
parms_[tmp_idx++] = *idx;
}
PECallFunction::PECallFunction(perm_string n, const list<PExpr*>&parms)
: path_(pn_from_ps(n)), parms_(parms.size())
{
int tmp_idx = 0;
assert(parms_.size() == parms.size());
for (list<PExpr*>::const_iterator idx = parms.begin()
; idx != parms.end() ; ++idx)
parms_[tmp_idx++] = *idx;
}
PECallFunction::~PECallFunction()
{
}
void PECallFunction::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
bool PEConcat::is_constant(Module *mod) const
{
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
parms_[idx]->declare_implicit_nets(scope, type);
bool constant = repeat_? repeat_->is_constant(mod) : true;
for (unsigned i = 0; constant && i < parms_.count(); ++i) {
constant = constant && parms_[i]->is_constant(mod);
}
}
bool PECallFunction::has_aa_term(Design*des, NetScope*scope) const
{
bool flag = false;
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
flag = parms_[idx]->has_aa_term(des, scope) || flag;
}
return flag;
}
PEConcat::PEConcat(const list<PExpr*>&p, PExpr*r)
: parms_(p.size()), width_modes_(SIZED, p.size()), repeat_(r)
{
int tmp_idx = 0;
assert(parms_.size() == p.size());
for (list<PExpr*>::const_iterator idx = p.begin()
; idx != p.end() ; ++idx)
parms_[tmp_idx++] = *idx;
tested_scope_ = 0;
repeat_count_ = 1;
return constant;
}
PEConcat::~PEConcat()
@@ -237,154 +83,14 @@ PEConcat::~PEConcat()
delete repeat_;
}
void PEConcat::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
/*
* An identifier can be in a constant expresion if (and only if) it is
* a parameter.
*/
bool PEIdent::is_constant(Module*mod) const
{
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
parms_[idx]->declare_implicit_nets(scope, type);
}
}
bool PEConcat::has_aa_term(Design*des, NetScope*scope) const
{
bool flag = false;
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
flag = parms_[idx]->has_aa_term(des, scope) || flag;
}
if (repeat_)
flag = repeat_->has_aa_term(des, scope) || flag;
return flag;
}
PEEvent::PEEvent(PEEvent::edge_t t, PExpr*e)
: type_(t), expr_(e)
{
}
PEEvent::~PEEvent()
{
}
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_;
}
PEFNumber::PEFNumber(verireal*v)
: value_(v)
{
}
PEFNumber::~PEFNumber()
{
delete value_;
}
const verireal& PEFNumber::value() const
{
return *value_;
}
PEIdent::PEIdent(const pform_name_t&that)
: path_(that), no_implicit_sig_(false)
{
}
PEIdent::PEIdent(perm_string s, bool no_implicit_sig)
: no_implicit_sig_(no_implicit_sig)
{
path_.push_back(name_component_t(s));
}
PEIdent::~PEIdent()
{
}
void PEIdent::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
{
/* We create an implicit wire if:
- this is a simple identifier
- an identifier of that name has not already been declared in
any enclosing scope.
- this is not an implicit named port connection */
if (no_implicit_sig_)
return;
if ((path_.size() == 1) && (path_.front().index.size() == 0)) {
perm_string name = path_.front().name;
LexicalScope*ss = scope;
while (ss) {
if (ss->wires.find(name) != ss->wires.end())
return;
if (ss->localparams.find(name) != ss->localparams.end())
return;
if (ss->parameters.find(name) != ss->parameters.end())
return;
if (ss->genvars.find(name) != ss->genvars.end())
return;
if (ss->events.find(name) != ss->events.end())
return;
/* Strictly speaking, we should also check for name clashes
with tasks, functions, named blocks, module instances,
and generate blocks. However, this information is not
readily available. As these names would not be legal in
this context, we can declare implicit nets here and rely
on later checks for name clashes to report the error. */
ss = ss->parent_scope();
}
PWire*net = new PWire(name, type, NetNet::NOT_A_PORT, IVL_VT_LOGIC);
net->set_file(get_file());
net->set_lineno(get_lineno());
net->set_range_scalar(SR_NET);
scope->wires[name] = net;
if (warn_implicit) {
cerr << get_fileline() << ": warning: implicit "
"definition of wire '" << name << "'." << endl;
}
}
}
bool PEIdent::has_aa_term(Design*des, NetScope*scope) const
{
NetNet* net = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
const NetExpr*ex1, *ex2;
scope = symbol_search(0, des, scope, path_, net, par, eve, ex1, ex2);
if (scope)
return scope->is_auto();
else
return false;
}
PENumber::PENumber(verinum*vp)
: value_(vp)
{
assert(vp);
}
PENumber::~PENumber()
{
delete value_;
}
const verinum& PENumber::value() const
{
return *value_;
map<string,PExpr*>::const_iterator cur = mod->parameters.find(text_);
return cur != mod->parameters.end();
}
bool PENumber::is_the_same(const PExpr*that) const
@@ -396,19 +102,14 @@ bool PENumber::is_the_same(const PExpr*that) const
return *value_ == *obj->value_;
}
PEString::PEString(char*s)
: text_(s)
bool PENumber::is_constant(Module*) const
{
return true;
}
PEString::~PEString()
bool PEString::is_constant(Module*) const
{
delete[]text_;
}
string PEString::value() const
{
return text_;
return true;
}
PETernary::PETernary(PExpr*e, PExpr*t, PExpr*f)
@@ -420,47 +121,54 @@ PETernary::~PETernary()
{
}
void PETernary::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
bool PETernary::is_constant(Module*) const
{
assert(expr_ && tru_ && fal_);
expr_->declare_implicit_nets(scope, type);
tru_->declare_implicit_nets(scope, type);
fal_->declare_implicit_nets(scope, type);
return false;
}
bool PETernary::has_aa_term(Design*des, NetScope*scope) const
{
assert(expr_ && tru_ && fal_);
return expr_->has_aa_term(des, scope)
|| tru_->has_aa_term(des, scope)
|| fal_->has_aa_term(des, scope);
}
/*
* $Log: PExpr.cc,v $
* Revision 1.11 1999/10/31 04:11:27 steve
* Add to netlist links pin name and instance number,
* and arrange in vvm for pin connections by name
* and instance number.
*
* Revision 1.10 1999/09/25 02:57:29 steve
* Parse system function calls.
*
* Revision 1.9 1999/09/16 04:18:15 steve
* elaborate concatenation repeats.
*
* Revision 1.8 1999/09/15 04:17:52 steve
* separate assign lval elaboration for error checking.
*
* Revision 1.7 1999/07/22 02:05:20 steve
* is_constant method for PEConcat.
*
* Revision 1.6 1999/07/17 19:50:59 steve
* netlist support for ternary operator.
*
* Revision 1.5 1999/06/16 03:13:29 steve
* More syntax parse with sorry stubs.
*
* Revision 1.4 1999/06/10 04:03:52 steve
* Add support for the Ternary operator,
* Add support for repeat concatenation,
* Correct some seg faults cause by elaboration
* errors,
* Parse the casex anc casez statements.
*
* Revision 1.3 1999/05/16 05:08:42 steve
* Redo constant expression detection to happen
* after parsing.
*
* Parse more operators and expressions.
*
* Revision 1.2 1998/11/11 00:01:51 steve
* Check net ranges in declarations.
*
* Revision 1.1 1998/11/03 23:28:53 steve
* Introduce verilog to CVS.
*
*/
PEUnary::PEUnary(char op, PExpr*ex)
: op_(op), expr_(ex)
{
}
PEUnary::~PEUnary()
{
}
void PEUnary::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
{
assert(expr_);
expr_->declare_implicit_nets(scope, type);
}
bool PEUnary::has_aa_term(Design*des, NetScope*scope) const
{
assert(expr_);
return expr_->has_aa_term(des, scope);
}
PEVoid::PEVoid()
{
}
PEVoid::~PEVoid()
{
}
+238 -589
View File
@@ -1,7 +1,7 @@
#ifndef __PExpr_H
#define __PExpr_H
/*
* Copyright (c) 1998-2011 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
@@ -18,164 +18,67 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: PExpr.h,v 1.25 1999/11/21 00:13:08 steve Exp $"
#endif
# include <string>
# include <vector>
# include <valarray>
# include "netlist.h"
# include "verinum.h"
# include "verireal.h"
# include "LineInfo.h"
# include "pform_types.h"
class Design;
class Module;
class LexicalScope;
class NetNet;
class NetExpr;
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 {
public:
enum width_mode_t { SIZED, EXPAND, LOSSLESS, UNSIZED };
// Flag values that can be passed to elaborate_expr.
static const unsigned NO_FLAGS = 0x0;
static const unsigned NEED_CONST = 0x1;
static const unsigned SYS_TASK_ARG = 0x2;
PExpr();
virtual ~PExpr();
virtual void dump(ostream&) const;
// This method tests whether the expression contains any identifiers
// that have not been previously declared in the specified scope or
// in any containing scope. Any such identifiers are added to the
// specified scope as scalar nets of the specified type.
//
// This operation must be performed by the parser, to ensure that
// subsequent declarations do not affect the decision to create an
// implicit net.
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
// Procedural elaboration of the expression.
virtual NetExpr*elaborate_expr(Design*des, const string&path) 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 type and width that the expression wants
// to be. It should be called before elaborating an expression to
// figure out the type and width of the expression. It also figures
// out the minimum width that can be used to evaluate the expression
// without changing the result. This allows the expression width to
// be pruned when not all bits of the result are used.
//
// Normally mode should be initialised to SIZED before starting to
// test the width of an expression. In SIZED mode the expression
// width will be calculated strictly according to the IEEE standard
// rules for expression width.
// If the expression contains an unsized literal, mode will be
// changed to LOSSLESS. In LOSSLESS mode the expression width will
// be calculated as the minimum width necessary to avoid arithmetic
// overflow or underflow.
// If the expression both contains an unsized literal and contains
// an operation that coerces a vector operand to a different type
// (signed <-> unsigned), mode is changed to UNSIZED. UNSIZED mode
// is the same as LOSSLESS, except that the final expression width
// will be forced to be at least integer_width. This is necessary
// to ensure compatibility with the IEEE standard, which requires
// unsized literals to be treated as having the same width as an
// integer. The lossless width calculation is inadequate in this
// case because coercing an operand to a different type means that
// the expression no longer obeys the normal rules of arithmetic.
//
// If mode is initialised to EXPAND instead of SIZED, the expression
// width will be calculated as the minimum width necessary to avoid
// arithmetic overflow or underflow, even if it contains no unsized
// literals. mode will be changed LOSSLESS or UNSIZED as described
// above. This supports a non-standard mode of expression width
// calculation.
//
// When the final value of mode is UNSIZED, the width returned by
// this method is the calculated lossless width, but the width
// returned by a subsequent call to the expr_width method will be
// the final expression width.
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
// 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_; }
unsigned min_width() const { return min_width_; }
bool has_sign() const { return signed_flag_; }
// This method allows the expression type (signed/unsigned)
// to be propagated down to any context-dependant operands.
void cast_signed(bool flag) { signed_flag_ = flag; }
// Procedural elaboration of the expression. The expr_width is
// the required width of the expression.
//
// The sys_task_arg flag is true if expressions are allowed to
// be incomplete.
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid,
unsigned flags) 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, const string&path,
unsigned lwidth,
unsigned long rise,
unsigned long fall,
unsigned long decay) 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;
// This is similar to elaborate_lnet, except that the
// expression is evaluated to be bi-directional. This is
// useful for arguments to inout ports of module instances and
// ports of tran primitives.
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
// Expressions that can be in the l-value of procedural
// assignments can be elaborated with this method. If the
// is_force flag is true, then the set of valid l-value types
// is slightly modified to accommodate the Verilog force
// statement
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const;
virtual NetNet* elaborate_lnet(Design*des, const string&path) const;
// This attempts to evaluate a constant expression, and return
// a verinum as a result. If the expression cannot be
// evaluated, return 0.
virtual verinum* eval_const(Design*des, NetScope*sc) const;
// This method returns true if the expression represents a
// structural net that can have multiple drivers. This is
// used to test whether an input port connection can be
// collapsed to a single wire.
virtual bool is_collapsible_net(Design*des, NetScope*scope) const;
virtual verinum* eval_const(const Design*des, const string&path) const;
// This method returns true if that expression is the same as
// this expression. This method is used for comparing
// expressions that must be structurally "identical".
virtual bool is_the_same(const PExpr*that) const;
protected:
unsigned fix_width_(width_mode_t mode);
// 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 expresions.
virtual bool is_constant(Module*) const;
// The derived class test_width methods should fill these in.
ivl_variable_type_t expr_type_;
unsigned expr_width_;
unsigned min_width_;
bool signed_flag_;
private: // not implemented
PExpr(const PExpr&);
PExpr& operator= (const PExpr&);
};
ostream& operator << (ostream&, const PExpr&);
@@ -183,340 +86,141 @@ ostream& operator << (ostream&, const PExpr&);
class PEConcat : public PExpr {
public:
PEConcat(const list<PExpr*>&p, PExpr*r =0);
PEConcat(const svector<PExpr*>&p, PExpr*r =0)
: parms_(p), repeat_(r) { }
~PEConcat();
virtual verinum* eval_const(Design*des, NetScope*sc) const;
virtual void dump(ostream&) const;
virtual NetNet* elaborate_lnet(Design*des, const string&path) const;
virtual NetNet* elaborate_net(Design*des, const string&path,
unsigned width,
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
virtual bool is_constant(Module*) const;
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
unsigned flags) const;
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const;
virtual bool is_collapsible_net(Design*des, NetScope*scope) const;
private:
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
bool bidirectional_flag) const;
private:
vector<PExpr*>parms_;
std::valarray<width_mode_t>width_modes_;
svector<PExpr*>parms_;
PExpr*repeat_;
NetScope*tested_scope_;
unsigned repeat_count_;
};
/*
* Event expressions are expressions that can be combined with the
* event "or" operator. These include "posedge foo" and similar, and
* also include named events. "edge" events are associated with an
* expression, whereas named events simply have a name, which
* represents an event variable.
*/
class PEEvent : public PExpr {
public:
enum edge_t {ANYEDGE, POSEDGE, NEGEDGE, POSITIVE};
PEEvent(NetNEvent::Type t, PExpr*e)
: type_(t), expr_(e)
{ }
// Use this constructor to create events based on edges or levels.
PEEvent(edge_t t, PExpr*e);
~PEEvent();
edge_t type() const;
PExpr* expr() const;
virtual void dump(ostream&) const;
virtual bool has_aa_term(Design*des, NetScope*scope) const;
private:
edge_t type_;
PExpr *expr_;
};
/*
* This holds a floating point constant in the source.
*/
class PEFNumber : public PExpr {
public:
explicit PEFNumber(verireal*vp);
~PEFNumber();
const verireal& value() const;
/* The eval_const method as applied to a floating point number
gets the *integer* value of the number. This accounts for
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,
width_mode_t&mode);
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
unsigned flags) const;
NetNEvent::Type type() const { return type_; }
PExpr* expr() const { return expr_; }
virtual void dump(ostream&) const;
private:
verireal*value_;
NetNEvent::Type type_;
PExpr*expr_;
};
class PEIdent : public PExpr {
public:
explicit PEIdent(perm_string, bool no_implicit_sig=false);
explicit PEIdent(const pform_name_t&);
~PEIdent();
// Add another name to the string of hierarchy that is the
// current identifier.
void append_name(perm_string);
explicit PEIdent(const string&s)
: text_(s), msb_(0), lsb_(0), idx_(0) { }
virtual void dump(ostream&) const;
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
// Identifiers are allowed (with restrictions) is assign l-values.
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_lnet(Design*des, const string&path) const;
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
// Structural r-values are OK.
virtual NetNet* elaborate_net(Design*des, const string&path,
unsigned lwidth,
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
// Identifiers are also allowed as procedural assignment l-values.
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const;
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
unsigned flags) const;
virtual bool is_constant(Module*) const;
verinum* eval_const(const Design*des, const string&path) const;
// Elaborate the PEIdent as a port to a module. This method
// only applies to Ident expressions.
NetNet* elaborate_port(Design*des, NetScope*sc) const;
verinum* eval_const(Design*des, NetScope*sc) const;
virtual bool is_collapsible_net(Design*des, NetScope*scope) const;
const pform_name_t& path() const { return path_; }
// XXXX
string name() const { return text_; }
private:
pform_name_t path_;
bool no_implicit_sig_;
string text_;
private:
// Common functions to calculate parts of part/bit
// selects. These methods return true if the expressions
// elaborate/calculate, or false if there is some sort of
// source error.
public:
// Use these to support bit- and part-select operators.
PExpr*msb_;
PExpr*lsb_;
bool calculate_bits_(Design*, NetScope*, long&msb, bool&defined) const;
// If this is a reference to a memory, this is the index
// expression.
PExpr*idx_;
// The calculate_parts_ method calculates the range
// expressions of a part select for the current object. The
// part select expressions are elaborated and evaluated, and
// the values written to the msb/lsb arguments. If there are
// invalid bits (xz) in either expression, then the defined
// flag is set to *false*.
bool calculate_parts_(Design*, NetScope*, long&msb, long&lsb, bool&defined) const;
NetExpr* calculate_up_do_base_(Design*, NetScope*, bool need_const) const;
bool calculate_param_range_(Design*, NetScope*,
const NetExpr*msb_ex, long&msb,
const NetExpr*lsb_ex, long&lsb,
long length) const;
bool calculate_up_do_width_(Design*, NetScope*, unsigned long&wid) const;
// Evaluate the prefix indices. All but the final index in a
// chain of indices must be a single value and must evaluate
// to constants at compile time. For example:
// [x] - OK
// [1][2][x] - OK
// [1][x:y] - OK
// [2:0][x] - BAD
// [y][x] - BAD
// Leave the last index for special handling.
bool calculate_packed_indices_(Design*des, NetScope*scope, NetNet*net,
std::list<long>&prefix_indices) const;
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;
bool elaborate_lval_net_packed_member_(Design*, NetScope*,
NetAssign_*,
const perm_string&) const;
private:
NetExpr*elaborate_expr_param_(Design*des,
NetScope*scope,
const NetExpr*par,
NetScope*found_in,
const NetExpr*par_msb,
const NetExpr*par_lsb,
unsigned expr_wid,
unsigned flags) const;
NetExpr*elaborate_expr_param_part_(Design*des,
NetScope*scope,
const NetExpr*par,
NetScope*found_in,
const NetExpr*par_msb,
const NetExpr*par_lsb,
unsigned expr_wid) const;
NetExpr*elaborate_expr_param_idx_up_(Design*des,
NetScope*scope,
const NetExpr*par,
NetScope*found_in,
const NetExpr*par_msb,
const NetExpr*par_lsb,
bool need_const) const;
NetExpr*elaborate_expr_param_idx_do_(Design*des,
NetScope*scope,
const NetExpr*par,
NetScope*found_in,
const NetExpr*par_msb,
const NetExpr*par_lsb,
bool need_const) const;
NetExpr*elaborate_expr_net(Design*des,
NetScope*scope,
NetNet*net,
NetScope*found,
unsigned expr_wid,
unsigned flags) const;
NetExpr*elaborate_expr_net_word_(Design*des,
NetScope*scope,
NetNet*net,
NetScope*found,
unsigned expr_wid,
unsigned flags) const;
NetExpr*elaborate_expr_net_part_(Design*des,
NetScope*scope,
NetESignal*net,
NetScope*found,
unsigned expr_wid) const;
NetExpr*elaborate_expr_net_idx_up_(Design*des,
NetScope*scope,
NetESignal*net,
NetScope*found,
bool need_const) const;
NetExpr*elaborate_expr_net_idx_do_(Design*des,
NetScope*scope,
NetESignal*net,
NetScope*found,
bool need_const) const;
NetExpr*elaborate_expr_net_bit_(Design*des,
NetScope*scope,
NetESignal*net,
NetScope*found,
bool need_const) const;
private:
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
bool bidirectional_flag) const;
bool eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
long&midx, long&lidx) const;
NetNet* elaborate_net_ram_(Design*des, const string&path,
NetMemory*mem, unsigned lwidth,
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
};
class PENumber : public PExpr {
public:
explicit PENumber(verinum*vp);
~PENumber();
explicit PENumber(verinum*vp)
: value_(vp) { assert(vp); }
~PENumber() { delete value_; }
const verinum& value() const;
const verinum& value() const { return *value_; }
virtual void dump(ostream&) const;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid, unsigned) const;
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
virtual NetNet* elaborate_net(Design*des, const string&path,
unsigned lwidth,
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
virtual verinum* eval_const(const Design*des, const string&path) const;
virtual bool is_the_same(const PExpr*that) const;
virtual bool is_constant(Module*) const;
private:
verinum*const value_;
};
/*
* This represents a string constant in an expression.
*
* The s parameter to the PEString constructor is a C string that this
* class instance will take for its own. The caller should not delete
* the string, the destructor will do it.
*/
class PEString : public PExpr {
public:
explicit PEString(char*s);
~PEString();
explicit PEString(const string&s)
: text_(s) { }
string value() const;
string value() const { return text_; }
virtual void dump(ostream&) const;
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid, unsigned) const;
verinum* eval_const(Design*, NetScope*) const;
virtual bool is_constant(Module*) const;
private:
char*text_;
const string text_;
};
class PEUnary : public PExpr {
public:
explicit PEUnary(char op, PExpr*ex);
~PEUnary();
explicit PEUnary(char op, PExpr*ex)
: op_(op), expr_(ex) { }
virtual void dump(ostream&out) const;
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
unsigned flags) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
public:
inline char get_op() const { return op_; }
inline PExpr*get_expr() const { return expr_; }
private:
NetExpr* elaborate_expr_bits_(NetExpr*operand, unsigned expr_wid) const;
virtual NetNet* elaborate_net(Design*des, const string&path,
unsigned width,
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
private:
char op_;
@@ -526,122 +230,40 @@ class PEUnary : public PExpr {
class PEBinary : public PExpr {
public:
explicit PEBinary(char op, PExpr*l, PExpr*r);
~PEBinary();
explicit PEBinary(char op, PExpr*l, PExpr*r)
: op_(op), left_(l), right_(r) { }
virtual bool is_constant(Module*) const;
virtual void dump(ostream&out) const;
virtual NetNet* elaborate_net(Design*des, const string&path,
unsigned width,
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
virtual verinum* eval_const(const Design*des, const string&path) const;
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
unsigned flags) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
protected:
private:
char op_;
PExpr*left_;
PExpr*right_;
NetExpr*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp,
unsigned expr_wid) const;
NetExpr*elaborate_eval_expr_base_(Design*, NetExpr*lp, NetExpr*rp,
unsigned expr_wid) const;
NetExpr*elaborate_expr_base_bits_(Design*, NetExpr*lp, NetExpr*rp,
unsigned expr_wid) const;
NetExpr*elaborate_expr_base_div_(Design*, NetExpr*lp, NetExpr*rp,
unsigned expr_wid) const;
NetExpr*elaborate_expr_base_mult_(Design*, NetExpr*lp, NetExpr*rp,
unsigned expr_wid) const;
NetExpr*elaborate_expr_base_add_(Design*, NetExpr*lp, NetExpr*rp,
unsigned expr_wid) const;
};
/*
* Here are a few specialized classes for handling specific binary
* operators.
*/
class PEBComp : public PEBinary {
public:
explicit PEBComp(char op, PExpr*l, PExpr*r);
~PEBComp();
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
NetExpr* elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, unsigned flags) const;
private:
unsigned l_width_;
unsigned r_width_;
};
/*
* 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,
width_mode_t&mode);
NetExpr* elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, unsigned flags) 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,
unsigned expr_wid) const =0;
protected:
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid,
unsigned flags) 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,
unsigned expr_wid) const;
};
class PEBShift : public PEBLeftWidth {
public:
explicit PEBShift(char op, PExpr*l, PExpr*r);
~PEBShift();
NetExpr*elaborate_expr_leaf(Design*des, NetExpr*lp, NetExpr*rp,
unsigned expr_wid) const;
NetNet* elaborate_net_add_(Design*des, const string&path,
unsigned lwidth,
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
NetNet* elaborate_net_cmp_(Design*des, const string&path,
unsigned lwidth,
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
NetNet* elaborate_net_shift_(Design*des, const string&path,
unsigned lwidth,
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
};
/*
@@ -654,24 +276,16 @@ 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 void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
unsigned flags) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
private:
NetExpr* elab_and_eval_alternative_(Design*des, NetScope*scope,
PExpr*expr, unsigned expr_wid,
unsigned flags) const;
virtual NetNet* elaborate_net(Design*des, const string&path,
unsigned width,
unsigned long rise =0,
unsigned long fall =0,
unsigned long decay =0) const;
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
virtual verinum* eval_const(const Design*des, const string&path) const;
private:
PExpr*expr_;
@@ -680,89 +294,124 @@ class PETernary : public PExpr {
};
/*
* This class represents a parsed call to a function, including calls
* to system functions. The parameters in the parms list are the
* expressions that are passed as input to the ports of the function.
* This class represents a parsed call to a function.
*/
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 list<PExpr *> &parms);
explicit PECallFunction(perm_string n, const list<PExpr *> &parms);
explicit PECallFunction(const string &n, const svector<PExpr *> &parms);
~PECallFunction();
virtual void dump(ostream &) const;
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid,
unsigned flags) const;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
private:
pform_name_t path_;
vector<PExpr *> parms_;
string name_;
svector<PExpr *> parms_;
bool check_call_matches_definition_(Design*des, NetScope*dscope) const;
NetExpr* cast_to_width_(NetExpr*expr, unsigned wid) const;
NetExpr* elaborate_sfunc_(Design*des, NetScope*scope,
unsigned expr_wid,
unsigned flags) const;
NetExpr* elaborate_access_func_(Design*des, NetScope*scope, ivl_nature_t,
unsigned expr_wid) const;
unsigned test_width_sfunc_(Design*des, NetScope*scope,
width_mode_t&mode);
NetESFunc* elaborate_sfunc_(Design*des, const string&path) const;
};
/*
* Support the SystemVerilog cast to size.
* $Log: PExpr.h,v $
* Revision 1.25 1999/11/21 00:13:08 steve
* Support memories in continuous assignments.
*
* Revision 1.24 1999/11/14 20:24:28 steve
* Add support for the LPM_CLSHIFT device.
*
* Revision 1.23 1999/11/05 21:45:19 steve
* Fix NetConst being set to zero width, and clean
* up elaborate_set_cmp_ for NetEBinary.
*
* Revision 1.22 1999/10/31 20:08:24 steve
* Include subtraction in LPM_ADD_SUB device.
*
* Revision 1.21 1999/10/31 04:11:27 steve
* Add to netlist links pin name and instance number,
* and arrange in vvm for pin connections by name
* and instance number.
*
* Revision 1.20 1999/09/25 02:57:29 steve
* Parse system function calls.
*
* Revision 1.19 1999/09/15 04:17:52 steve
* separate assign lval elaboration for error checking.
*
* Revision 1.18 1999/08/31 22:38:29 steve
* Elaborate and emit to vvm procedural functions.
*
* Revision 1.17 1999/08/01 21:18:55 steve
* elaborate rise/fall/decay for continuous assign.
*
* Revision 1.16 1999/07/31 19:14:47 steve
* Add functions up to elaboration (Ed Carter)
*
* Revision 1.15 1999/07/22 02:05:20 steve
* is_constant method for PEConcat.
*
* Revision 1.14 1999/07/17 19:50:59 steve
* netlist support for ternary operator.
*
* Revision 1.13 1999/06/16 03:13:29 steve
* More syntax parse with sorry stubs.
*
* Revision 1.12 1999/06/15 02:50:02 steve
* Add lexical support for real numbers.
*
* Revision 1.11 1999/06/10 04:03:52 steve
* Add support for the Ternary operator,
* Add support for repeat concatenation,
* Correct some seg faults cause by elaboration
* errors,
* Parse the casex anc casez statements.
*
* Revision 1.10 1999/06/09 03:00:05 steve
* Add support for procedural concatenation expression.
*
* Revision 1.9 1999/05/16 05:08:42 steve
* Redo constant expression detection to happen
* after parsing.
*
* Parse more operators and expressions.
*
* Revision 1.8 1999/05/10 00:16:57 steve
* Parse and elaborate the concatenate operator
* in structural contexts, Replace vector<PExpr*>
* and list<PExpr*> with svector<PExpr*>, evaluate
* constant expressions with parameters, handle
* memories as lvalues.
*
* Parse task declarations, integer types.
*
* Revision 1.7 1999/05/01 02:57:52 steve
* Handle much more complex event expressions.
*
* Revision 1.6 1999/04/29 02:16:26 steve
* Parse OR of event expressions.
*
* Revision 1.5 1999/04/19 01:59:36 steve
* Add memories to the parse and elaboration phases.
*
* Revision 1.4 1998/11/11 00:01:51 steve
* Check net ranges in declarations.
*
* Revision 1.3 1998/11/09 18:55:33 steve
* Add procedural while loops,
* Parse procedural for loops,
* Add procedural wait statements,
* Add constant nodes,
* Add XNOR logic gate,
* Make vvm output look a bit prettier.
*
* Revision 1.2 1998/11/07 17:05:05 steve
* Handle procedural conditional, and some
* of the conditional expressions.
*
* Elaborate signals and identifiers differently,
* allowing the netlist to hold signal information.
*
* Revision 1.1 1998/11/03 23:28:54 steve
* Introduce verilog to CVS.
*
*/
class PECastSize : public PExpr {
public:
explicit PECastSize(unsigned expr_wid, PExpr*base);
~PECastSize();
void dump(ostream &out) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid,
unsigned flags) const;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
private:
unsigned size_;
PExpr* base_;
};
/*
* This class is used for error recovery. All methods do nothing and return
* null or default values.
*/
class PEVoid : public PExpr {
public:
explicit PEVoid();
~PEVoid();
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid,
unsigned flags) const;
};
#endif
+15 -21
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2008,2010 Stephen Williams ([email protected])
* Copyright (c) 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,36 +16,30 @@
* 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"
#if !defined(WINNT)
#ident "$Id: PFunction.cc,v 1.2 1999/08/25 22:22:41 steve Exp $"
#endif
#include "PTask.h"
PFunction::PFunction(perm_string name, LexicalScope*parent, bool is_auto__)
: PScope(name, parent), ports_(0), statement_(0)
PFunction::PFunction(svector<PWire*>*p, Statement*s)
: out_(0), ports_(p), statement_(s)
{
is_auto_ = is_auto__;
return_type_.type = PTF_NONE;
}
PFunction::~PFunction()
{
}
void PFunction::set_ports(svector<PWire *>*p)
void PFunction::set_output(PWire*o)
{
assert(ports_ == 0);
ports_ = p;
assert(out_ == 0);
out_ = o;
}
void PFunction::set_statement(Statement*s)
{
assert(s != 0);
assert(statement_ == 0);
statement_ = s;
}
void PFunction::set_return(PTaskFuncArg t)
{
return_type_ = t;
}
/*
* $Log: PFunction.cc,v $
* Revision 1.2 1999/08/25 22:22:41 steve
* elaborate some aspects of functions.
*
*/
+51 -225
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2010 Stephen Williams ([email protected])
* Copyright (c) 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,82 +16,40 @@
* 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"
#if !defined(WINNT)
#ident "$Id: PGate.cc,v 1.5 1999/09/14 01:50:35 steve Exp $"
#endif
# include "PGate.h"
# include "PExpr.h"
# include "verinum.h"
# include <cassert>
# include <assert.h>
void PGate::set_pins_(list<PExpr*>*pins)
PGate::PGate(const string&name,
svector<PExpr*>*pins,
const svector<PExpr*>*del)
: name_(name), pins_(pins)
{
assert(pins);
assert(pins->size() == pins_.size());
for (size_t idx = 0 ; idx < pins_.size() ; idx += 1) {
pins_[idx] = pins->front();
pins->pop_front();
}
assert(pins->empty());
delete pins;
}
PGate::PGate(perm_string name, list<PExpr*>*pins, const list<PExpr*>*del)
: name_(name), pins_(pins? pins->size() : 0)
{
if (pins) set_pins_(pins);
if (del) delay_.set_delays(del);
str0_ = IVL_DR_STRONG;
str1_ = IVL_DR_STRONG;
}
PGate::PGate(perm_string name, list<PExpr*>*pins, PExpr*del)
: name_(name), pins_(pins? pins->size() : 0)
PGate::PGate(const string&name,
svector<PExpr*>*pins,
PExpr*del)
: name_(name), pins_(pins)
{
if (pins) set_pins_(pins);
if (del) delay_.set_delay(del);
str0_ = IVL_DR_STRONG;
str1_ = IVL_DR_STRONG;
}
PGate::PGate(perm_string name, list<PExpr*>*pins)
: name_(name), pins_(pins? pins->size() : 0)
PGate::PGate(const string&name, svector<PExpr*>*pins)
: name_(name), pins_(pins)
{
if (pins) set_pins_(pins);
str0_ = IVL_DR_STRONG;
str1_ = IVL_DR_STRONG;
}
PGate::~PGate()
{
}
ivl_drive_t PGate::strength0() const
{
return str0_;
}
void PGate::strength0(ivl_drive_t s)
{
str0_ = s;
}
ivl_drive_t PGate::strength1() const
{
return str1_;
}
void PGate::strength1(ivl_drive_t s)
{
str1_ = s;
}
void PGate::elaborate_scope(Design*, NetScope*) const
{
}
/*
* This method is used during elaboration to calculate the
* rise/fall/decay times for the gate. These values were set in pform
@@ -100,48 +58,39 @@ void PGate::elaborate_scope(Design*, NetScope*) const
* parameters. This method understands how to handle the different
* numbers of expressions.
*/
void PGate::eval_delays(Design*des, NetScope*scope,
NetExpr*&rise_expr,
NetExpr*&fall_expr,
NetExpr*&decay_expr,
bool as_net_flag) const
void PGate::eval_delays(Design*des, const string&path,
unsigned long&rise_time,
unsigned long&fall_time,
unsigned long&decay_time) const
{
delay_.eval_delays(des, scope,
rise_expr, fall_expr, decay_expr,
as_net_flag);
delay_.eval_delays(des, path, rise_time, fall_time, decay_time);
}
unsigned PGate::delay_count() const
PGAssign::PGAssign(svector<PExpr*>*pins)
: PGate("", pins)
{
return delay_.delay_count();
assert(pins->count() == 2);
}
PGAssign::PGAssign(list<PExpr*>*pins)
: PGate(perm_string(), pins)
PGAssign::PGAssign(svector<PExpr*>*pins, svector<PExpr*>*dels)
: PGate("", pins, dels)
{
assert(pin_count() == 2);
}
PGAssign::PGAssign(list<PExpr*>*pins, list<PExpr*>*dels)
: PGate(perm_string(), pins, dels)
{
assert(pin_count() == 2);
assert(pins->count() == 2);
}
PGAssign::~PGAssign()
{
}
PGBuiltin::PGBuiltin(Type t, perm_string name,
list<PExpr*>*pins,
list<PExpr*>*del)
PGBuiltin::PGBuiltin(Type t, const string&name,
svector<PExpr*>*pins,
svector<PExpr*>*del)
: PGate(name, pins, del), type_(t), msb_(0), lsb_(0)
{
}
PGBuiltin::PGBuiltin(Type t, perm_string name,
list<PExpr*>*pins,
PGBuiltin::PGBuiltin(Type t, const string&name,
svector<PExpr*>*pins,
PExpr*del)
: PGate(name, pins, del), type_(t), msb_(0), lsb_(0)
{
@@ -161,147 +110,24 @@ void PGBuiltin::set_range(PExpr*msb, PExpr*lsb)
lsb_ = lsb;
}
const char* PGBuiltin::gate_name() const
{
switch(type_) {
case AND:
return "AND";
break;
case NAND:
return "NAND";
break;
/*
* $Log: PGate.cc,v $
* Revision 1.5 1999/09/14 01:50:35 steve
* Handle gates without delays.
*
* Revision 1.4 1999/09/04 19:11:46 steve
* Add support for delayed non-blocking assignments.
*
* Revision 1.3 1999/08/01 21:18:55 steve
* elaborate rise/fall/decay for continuous assign.
*
* Revision 1.2 1999/08/01 16:34:50 steve
* Parse and elaborate rise/fall/decay times
* for gates, and handle the rules for partial
* lists of times.
*
* Revision 1.1 1999/02/15 02:06:15 steve
* Elaborate gate ranges.
*
*/
case OR:
return "OR";
break;
case NOR:
return "NOR";
break;
case XOR:
return "XOR";
break;
case XNOR:
return "XNOR";
break;
case BUF:
return "BUF";
break;
case NOT:
return "NOT";
break;
case BUFIF0:
return "BUFIF0";
break;
case NOTIF0:
return "NOTIF0";
break;
case BUFIF1:
return "BUFIF1";
break;
case NOTIF1:
return "NOTIF1";
break;
case NMOS:
return "NMOS";
break;
case RNMOS:
return "RNMOS";
break;
case PMOS:
return "PMOS";
break;
case RPMOS:
return "RPMOS";
break;
case TRAN:
return "TRAN";
break;
case RTRAN:
return "RTRAN";
break;
case TRANIF0:
return "TRANIF0";
break;
case RTRANIF0:
return "RTRANIF0";
break;
case TRANIF1:
return "TRANIF1";
break;
case RTRANIF1:
return "RTRANIF1";
break;
case CMOS:
return "CMOS";
break;
case RCMOS:
return "RCMOS";
break;
case PULLUP:
return "PULLUP";
break;
case PULLDOWN:
return "PULLDOWN";
break;
}
return "<unknown>";
}
PGModule::PGModule(perm_string type, perm_string name, list<PExpr*>*pins)
: PGate(name, pins), overrides_(0), pins_(0),
npins_(0), parms_(0), nparms_(0), msb_(0), lsb_(0)
{
type_ = type;
}
PGModule::PGModule(perm_string type, perm_string name,
named<PExpr*>*pins, unsigned npins)
: PGate(name, 0), overrides_(0), pins_(pins),
npins_(npins), parms_(0), nparms_(0), msb_(0), lsb_(0)
{
type_ = type;
}
PGModule::~PGModule()
{
}
void PGModule::set_parameters(list<PExpr*>*o)
{
assert(overrides_ == 0);
overrides_ = o;
}
void PGModule::set_parameters(named<PExpr*>*pa, unsigned npa)
{
assert(parms_ == 0);
assert(overrides_ == 0);
parms_ = pa;
nparms_ = npa;
}
void PGModule::set_range(PExpr*msb, PExpr*lsb)
{
assert(msb_ == 0);
assert(lsb_ == 0);
msb_ = msb;
lsb_ = lsb;
}
perm_string PGModule::get_type() const
{
return type_;
}
+107 -128
View File
@@ -1,7 +1,7 @@
#ifndef __PGate_H
#define __PGate_H
/*
* Copyright (c) 1998-2011 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
@@ -18,19 +18,16 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: PGate.h,v 1.10 1999/09/04 19:11:46 steve Exp $"
#endif
# include "svector.h"
# include "StringHeap.h"
# include "named.h"
# include "LineInfo.h"
# include "PDelays.h"
# include "netlist.h"
# include <map>
# include <list>
# include <vector>
# include <string>
class PExpr;
class PUdp;
class Design;
class Module;
/*
@@ -41,67 +38,43 @@ class Module;
* This pins of a gate are connected to expressions. The elaboration
* step will need to convert expressions to a network of gates in
* order to elaborate expression inputs, but that can easily be done.
*
* The PGate base class also carries the strength0 and strength1
* strengths for those gates where the driver[s] can be described by a
* single strength pair. There is a strength of the 0 drive, and a
* strength of the 1 drive.
*/
class PGate : public LineInfo {
public:
explicit PGate(perm_string name, list<PExpr*>*pins,
const list<PExpr*>*del);
explicit PGate(const string&name, svector<PExpr*>*pins,
const svector<PExpr*>*del);
explicit PGate(perm_string name, list<PExpr*>*pins,
explicit PGate(const string&name, svector<PExpr*>*pins,
PExpr*del);
explicit PGate(perm_string name, list<PExpr*>*pins);
explicit PGate(const string&name, svector<PExpr*>*pins);
virtual ~PGate();
perm_string get_name() const { return name_; }
const string& get_name() const { return name_; }
// This evaluates the delays as far as possible, but returns
// an expression, and do not signal errors.
void eval_delays(Design*des, NetScope*scope,
NetExpr*&rise_time,
NetExpr*&fall_time,
NetExpr*&decay_time,
bool as_net_flag =false) const;
void eval_delays(Design*des, const string&path,
unsigned long&rise_time,
unsigned long&fall_time,
unsigned long&decay_time) const;
unsigned delay_count() const;
unsigned pin_count() const { return pins_? pins_->count() : 0; }
const PExpr*pin(unsigned idx) const { return (*pins_)[idx]; }
unsigned pin_count() const { return pins_.size(); }
PExpr*pin(unsigned idx) const { return pins_[idx]; }
ivl_drive_t strength0() const;
ivl_drive_t strength1() const;
void strength0(ivl_drive_t);
void strength1(ivl_drive_t);
map<perm_string,PExpr*> attributes;
virtual void dump(ostream&out, unsigned ind =4) const;
virtual void elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*sc) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(ostream&out) const;
virtual void elaborate(Design*des, const string&path) const;
protected:
const vector<PExpr*>& get_pins() const { return pins_; }
const svector<PExpr*>* get_pins() const { return pins_; }
void dump_pins(ostream&out) const;
void dump_delays(ostream&out) const;
private:
perm_string name_;
const string name_;
PDelays delay_;
vector<PExpr*>pins_;
ivl_drive_t str0_, str1_;
void set_pins_(list<PExpr*>*pins);
svector<PExpr*>*pins_;
private: // not implemented
PGate(const PGate&);
@@ -115,13 +88,12 @@ class PGate : public LineInfo {
class PGAssign : public PGate {
public:
explicit PGAssign(list<PExpr*>*pins);
explicit PGAssign(list<PExpr*>*pins, list<PExpr*>*dels);
explicit PGAssign(svector<PExpr*>*pins);
explicit PGAssign(svector<PExpr*>*pins, svector<PExpr*>*dels);
~PGAssign();
void dump(ostream&out, unsigned ind =4) const;
virtual void elaborate(Design*des, NetScope*scope) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
void dump(ostream&out) const;
virtual void elaborate(Design*des, const string&path) const;
private:
};
@@ -146,36 +118,23 @@ class PGBuiltin : public PGate {
TRANIF1, RTRANIF0, RTRANIF1 };
public:
explicit PGBuiltin(Type t, perm_string name,
list<PExpr*>*pins,
list<PExpr*>*del);
explicit PGBuiltin(Type t, perm_string name,
list<PExpr*>*pins,
explicit PGBuiltin(Type t, const string&name,
svector<PExpr*>*pins,
svector<PExpr*>*del);
explicit PGBuiltin(Type t, const string&name,
svector<PExpr*>*pins,
PExpr*del);
~PGBuiltin();
Type type() const { return type_; }
const char * gate_name() const;
void set_range(PExpr*msb, PExpr*lsb);
virtual void dump(ostream&out, unsigned ind =4) const;
virtual void elaborate(Design*, NetScope*scope) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(ostream&out) const;
virtual void elaborate(Design*, const string&path) const;
private:
unsigned calculate_array_count_(Design*, NetScope*,
long&high, long&low) const;
void calculate_gate_and_lval_count_(unsigned&gate_count,
unsigned&lval_count) const;
NetNode* create_gate_for_output_(Design*, NetScope*,
perm_string gate_name,
unsigned instance_width) const;
bool check_delay_count(Design*des) const;
Type type_;
PExpr*msb_;
PExpr*lsb_;
};
@@ -189,70 +148,90 @@ class PGBuiltin : public PGate {
class PGModule : public PGate {
public:
// The name is the *instance* name of the gate.
// If the binding of ports is by position, this constructor
// builds everything all at once.
explicit PGModule(perm_string type, perm_string name,
list<PExpr*>*pins);
explicit PGModule(const string&type, const string&name,
svector<PExpr*>*overrides, svector<PExpr*>*pins)
: PGate(name, pins), type_(type), overrides_(overrides), pins_(0), npins_(0) { }
// If the binding of ports is by name, this constructor takes
// the bindings and stores them for later elaboration.
explicit PGModule(perm_string type, perm_string name,
named<PExpr*>*pins, unsigned npins);
struct bind_t {
string name;
PExpr* parm;
};
explicit PGModule(const string&type, const string&name,
svector<PExpr*>*overrides, bind_t*pins, unsigned npins)
: PGate(name, 0), type_(type), overrides_(overrides), pins_(pins), npins_(npins) { }
~PGModule();
// Parameter overrides can come as an ordered list, or a set
// of named expressions.
void set_parameters(list<PExpr*>*o);
void set_parameters(named<PExpr*>*pa, unsigned npa);
// Modules can be instantiated in ranges. The parser uses this
// method to pass the range to the pform.
void set_range(PExpr*msb, PExpr*lsb);
virtual void dump(ostream&out, unsigned ind =4) const;
virtual void elaborate(Design*, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*sc) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
// This returns the module name of this module. It is a
// permallocated string.
perm_string get_type() const;
virtual void dump(ostream&out) const;
virtual void elaborate(Design*, const string&path) const;
private:
perm_string type_;
list<PExpr*>*overrides_;
named<PExpr*>*pins_;
string type_;
svector<PExpr*>*overrides_;
bind_t*pins_;
unsigned npins_;
// These members support parameter override by name
named<PExpr*>*parms_;
unsigned nparms_;
// Arrays of modules are give if these are set.
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;
unsigned calculate_instance_count_(Design*, NetScope*,
long&high, long&low,
perm_string name) 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;
// Not currently used.
#if 0
bool elaborate_sig_udp_(Design*des, NetScope*scope, PUdp*udp) const;
#endif
NetNet*resize_net_to_port_(Design*des, NetScope*scope,
NetNet*sig, unsigned port_wid,
NetNet::PortType dir, bool as_signed) const;
void elaborate_mod_(Design*, Module*mod, const string&path) const;
void elaborate_udp_(Design*, PUdp *udp, const string&path) const;
};
/*
* $Log: PGate.h,v $
* Revision 1.10 1999/09/04 19:11:46 steve
* Add support for delayed non-blocking assignments.
*
* Revision 1.9 1999/08/23 16:48:39 steve
* Parameter overrides support from Peter Monta
* AND and XOR support wide expressions.
*
* Revision 1.8 1999/08/01 21:18:55 steve
* elaborate rise/fall/decay for continuous assign.
*
* Revision 1.7 1999/08/01 16:34:50 steve
* Parse and elaborate rise/fall/decay times
* for gates, and handle the rules for partial
* lists of times.
*
* Revision 1.6 1999/05/29 02:36:17 steve
* module parameter bind by name.
*
* Revision 1.5 1999/05/10 00:16:58 steve
* Parse and elaborate the concatenate operator
* in structural contexts, Replace vector<PExpr*>
* and list<PExpr*> with svector<PExpr*>, evaluate
* constant expressions with parameters, handle
* memories as lvalues.
*
* Parse task declarations, integer types.
*
* Revision 1.4 1999/02/15 02:06:15 steve
* Elaborate gate ranges.
*
* Revision 1.3 1999/01/25 05:45:56 steve
* Add the LineInfo class to carry the source file
* location of things. PGate, Statement and PProcess.
*
* elaborate handles module parameter mismatches,
* missing or incorrect lvalues for procedural
* assignment, and errors are propogated to the
* top of the elaboration call tree.
*
* Attach line numbers to processes, gates and
* assignment statements.
*
* 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/03 23:28:54 steve
* Introduce verilog to CVS.
*
*/
#endif
-114
View File
@@ -1,114 +0,0 @@
/*
* Copyright (c) 2006-2011 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* 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 "PGenerate.h"
# include "PWire.h"
# include "ivl_assert.h"
PGenerate::PGenerate(LexicalScope*parent, unsigned id)
: LexicalScope(parent), id_number(id)
{
direct_nested_ = false;
scheme_type = GS_NONE;
loop_init = 0;
loop_test = 0;
loop_step = 0;
}
PGenerate::~PGenerate()
{
}
void PGenerate::add_gate(PGate*gate)
{
gates.push_back(gate);
}
void PGenerate::probe_for_direct_nesting_(void)
{
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.empty()) return;
if (! funcs.empty()) return;
if (! gates.empty()) return;
if (! parameters.empty()) return;
if (! localparams.empty()) return;
if (! events.empty()) return;
if (! wires.empty()) return;
if (! genvars.empty()) return;
if (! behaviors.empty()) return;
if (! analog_behaviors.empty()) return;
if (generate_schemes.empty()) 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;
}
-141
View File
@@ -1,141 +0,0 @@
#ifndef __PGenerate_H
#define __PGenerate_H
/*
* Copyright (c) 2006-2010 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* 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 "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;
/*
* This represents a generate scheme. The interpretation of the
* members depends on the scheme_type.
*
* GS_LOOP
*
* GS_CASE
* loop_test is the expression to be compared.
* generates contains only GS_CASE_ITEM schemes.
* GS_CASE_ITEM
* 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 {
public:
explicit PGenerate(LexicalScope*parent, unsigned id_number);
~PGenerate();
// Generate schemes have an ID number, for when the scope is
// implicit.
const unsigned id_number;
perm_string scope_name;
// This is used during parsing to stack lexical scopes within
// this generate scheme.
// LexicalScope*lexical_scope;
enum scheme_t {GS_NONE, GS_LOOP, GS_CONDIT, GS_ELSE,
GS_CASE, GS_CASE_ITEM, GS_NBLOCK};
scheme_t scheme_type;
// generate loops have an index variable and three
// expressions: for (index = <init>; <test>; index=<step>)
perm_string loop_index;
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;
list<PGate*> gates;
void add_gate(PGate*);
// Tasks instantiated within this scheme.
map<perm_string,PTask*> tasks;
map<perm_string,PFunction*>funcs;
// genvars declared within this scheme.
map<perm_string,LineInfo*> genvars;
// Generate schemes can contain further generate schemes.
list<PGenerate*> generate_schemes;
// PGenerate*parent;
// This method is called by the elaboration of a module to
// generate scopes. the container is the scope that is to
// contain the generated scope.
bool generate_scope(Design*des, NetScope*container);
// Elaborate signals within any of the generated scopes that
// were made by this generate block within the given container scope.
bool elaborate_sig(Design*des, NetScope*container) const;
bool elaborate(Design*des, NetScope*container) const;
void dump(ostream&out, unsigned indent) const;
private:
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 calculate the
// direct_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
-58
View File
@@ -1,58 +0,0 @@
/*
* Copyright (c) 2008,2010 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* 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 "PScope.h"
PScope::PScope(perm_string n, LexicalScope*parent)
: LexicalScope(parent), name_(n)
{
}
PScope::PScope(perm_string n)
: LexicalScope(0), name_(n)
{
}
PScope::~PScope()
{
}
PWire* LexicalScope::wires_find(perm_string name)
{
map<perm_string,PWire*>::const_iterator cur = wires.find(name);
if (cur == wires.end())
return 0;
else
return (*cur).second;
}
PScopeExtra::PScopeExtra(perm_string n, LexicalScope*parent)
: PScope(n, parent)
{
}
PScopeExtra::PScopeExtra(perm_string n)
: PScope(n)
{
}
PScopeExtra::~PScopeExtra()
{
}
-172
View File
@@ -1,172 +0,0 @@
#ifndef __PScope_H
#define __PScope_H
/*
* Copyright (c) 2008,2010 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* 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 "LineInfo.h"
# include "StringHeap.h"
# include "pform_types.h"
# include "ivl_target.h"
# include <map>
class PEvent;
class PExpr;
class PFunction;
class AProcess;
class PProcess;
class PTask;
class PWire;
class Design;
class NetScope;
/*
* The PScope class is a base representation of an object that
* 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
* hierarchy. That is represented by NetScope objects after elaboration.
*/
class LexicalScope {
public:
explicit LexicalScope(LexicalScope*parent) : parent_(parent) { }
// 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;
// Defined types in the scope.
map<perm_string,data_type_t*>typedefs;
// 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);
// Genvars in the scope. These will only be present in module
// scopes, but are listed here to allow them to be found when
// creating implicit nets.
map<perm_string,LineInfo*> genvars;
// Behaviors (processes) in this scope
list<PProcess*> behaviors;
list<AProcess*> analog_behaviors;
// Enumeration sets.
list<enum_type_t*> enum_sets;
LexicalScope* parent_scope() const { return parent_; }
protected:
void dump_typedefs_(ostream&out, unsigned indent) const;
void dump_parameters_(ostream&out, unsigned indent) const;
void dump_localparams_(ostream&out, unsigned indent) const;
void dump_enumerations_(ostream&out, unsigned indent) const;
void dump_events_(ostream&out, unsigned indent) const;
void dump_wires_(ostream&out, unsigned indent) const;
private:
LexicalScope*parent_;
};
class PScope : public LexicalScope {
public:
// When created, a scope has a name and a parent. The name is
// the name of the definition. For example, if this is a
// module declaration, the name is the name after the "module"
// keyword, and if this is a task scope, the name is the task
// name. The parent is the lexical parent of this scope. Since
// modules do not nest in Verilog, the parent must be nil for
// modules. Scopes for tasks and functions point to their
// containing module.
PScope(perm_string name, LexicalScope*parent);
PScope(perm_string name);
virtual ~PScope();
perm_string pscope_name() const { return name_; }
protected:
bool elaborate_sig_wires_(Design*des, NetScope*scope) const;
bool elaborate_behaviors_(Design*des, NetScope*scope) const;
private:
perm_string name_;
};
/*
* Some scopes can carry definitions. These include Modules and PClass
* scopes. These derive from PScopeExtra so that they hold the maps of
* extra definitions.
*/
class PScopeExtra : public PScope {
public:
PScopeExtra(perm_string, LexicalScope*parent);
PScopeExtra(perm_string);
~PScopeExtra();
/* Task definitions within this module */
map<perm_string,PTask*> tasks;
map<perm_string,PFunction*> funcs;
};
#endif
-34
View File
@@ -1,34 +0,0 @@
/*
* Copyright (c) 2006-2011 Stephen Williams <[email protected]>
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* 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 "PSpec.h"
PSpecPath::PSpecPath(unsigned src_cnt, unsigned dst_cnt, char polarity,
bool full_flag)
: conditional(false), condition(0), edge(0),
src(src_cnt), dst(dst_cnt),
data_source_expression(0)
{
full_flag_ = full_flag;
polarity_ = polarity;
}
PSpecPath::~PSpecPath()
{
}
-87
View File
@@ -1,87 +0,0 @@
#ifndef __PSpec_H
#define __PSpec_H
/*
* Copyright (c) 2006-2011 Stephen Williams <[email protected]>
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* 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 "LineInfo.h"
# include "StringHeap.h"
# include <vector>
class PExpr;
/*
* The PSpecPath is the parse of a specify path, which is in its most
* general form <path> = <delays>. The <delays> are collected into the
* "delays" vector in all cases, and the variety is in the other
* members.
*
* All paths also have a list of source names in the src vector, and a
* list of destination names in the dst vector. These pairs are the
* actual paths.
*
* If the path is a simple path, then:
* condition == nil
* edge == 0
* data_source_expression == nil
*
* If the path is conditional, then conditional == true and condition
* is the condition expression. If the condition expression is nil,
* then this is an ifnone conditional path.
*
* If data_source_expression != nil, then the path is edge sensitive
* and the edge might not be 0.
*
* The full flag is used to verify that only vectors of the same size
* are used in a parallel connection. Icarus always creates a full
* connection between the source and destination. The polarity is for
* informational (display) purposes only. The polarity is either '+',
* '-' or 0.
*/
class PSpecPath : public LineInfo {
public:
PSpecPath(unsigned src_cnt, unsigned dst_cnt, char polarity,
bool full_flag);
~PSpecPath();
void elaborate(class Design*des, class NetScope*scope) const;
void dump(std::ostream&out, unsigned ind) const;
public:
// Condition expression, if present.
bool conditional;
class PExpr* condition;
// Edge specification (-1==negedge, 0 = no edge, 1==posedge)
int edge;
// Is this a full connection.
bool full_flag_;
// What is the polarity of the connection.
char polarity_;
// Ordered set of source nodes of a path
std::vector<perm_string> src;
// Ordered set of destination nodes of a path
std::vector<perm_string> dst;
// Data source expression
class PExpr* data_source_expression;
std::vector<class PExpr*>delays;
};
#endif
+15 -16
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2008,2010 Stephen Williams ([email protected])
* Copyright (c) 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,29 +16,28 @@
* 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"
#if !defined(WINNT)
#ident "$Id: PTask.cc,v 1.2 1999/07/24 02:11:19 steve Exp $"
#endif
# include "PTask.h"
PTask::PTask(perm_string name, LexicalScope*parent, bool is_auto__)
: PScope(name, parent), ports_(0), statement_(0)
PTask::PTask(svector<PWire*>*p, Statement*s)
: ports_(p), statement_(s)
{
is_auto_ = is_auto__;
}
PTask::~PTask()
{
}
void PTask::set_ports(svector<PWire*>*p)
{
assert(ports_ == 0);
ports_ = p;
}
/*
* $Log: PTask.cc,v $
* 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.
*
*/
void PTask::set_statement(Statement*s)
{
assert(statement_ == 0);
statement_ = s;
}
+39 -63
View File
@@ -1,7 +1,7 @@
#ifndef __PTask_H
#define __PTask_H
/*
* Copyright (c) 1999-2008,2010,2012 Stephen Williams ([email protected])
* Copyright (c) 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
@@ -18,71 +18,34 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: PTask.h,v 1.6 1999/09/30 21:28:34 steve Exp $"
#endif
# include "LineInfo.h"
# include "PScope.h"
# include "svector.h"
# include "StringHeap.h"
# include <string>
# include <vector>
# include <list>
class Design;
class NetScope;
class PWire;
class Statement;
class PExpr;
enum PTaskFuncEnum {
PTF_NONE,
PTF_REG,
PTF_REG_S,
PTF_INTEGER,
PTF_REAL,
PTF_REALTIME,
PTF_TIME,
PTF_ATOM2,
PTF_ATOM2_S,
PTF_STRING,
PTF_VOID
};
struct PTaskFuncArg {
PTaskFuncEnum type;
std::list<pform_range_t>*range;
};
/*
* The PTask holds the parsed definitions of a task.
*/
class PTask : public PScope, public LineInfo {
class PTask : public LineInfo {
public:
explicit PTask(perm_string name, LexicalScope*parent, bool is_auto);
explicit PTask(svector<PWire*>*p, Statement*s);
~PTask();
void set_ports(svector<PWire *>*p);
void set_statement(Statement *s);
// Tasks introduce scope, to need to be handled during the
// scope elaboration pass. The scope passed is my scope,
// created by the containing scope. I fill it in with stuff if
// I need to.
void elaborate_scope(Design*des, NetScope*scope) const;
// Bind the ports to the regs that are the ports.
void elaborate_sig(Design*des, NetScope*scope) const;
// Elaborate the statement to finish off the task definition.
void elaborate(Design*des, NetScope*scope) const;
bool is_auto() const { return is_auto_; };
void elaborate_1(Design*des, const string&path) const;
void elaborate_2(Design*des, const string&path) const;
void dump(ostream&, unsigned) const;
private:
svector<PWire*>*ports_;
Statement*statement_;
bool is_auto_;
private: // Not implemented
PTask(const PTask&);
@@ -93,36 +56,49 @@ class PTask : public PScope, public LineInfo {
* The function is similar to a task (in this context) but there is a
* single output port and a set of input ports. The output port is the
* function return value.
*
* The output value is not elaborated until elaborate_sig.
*/
class PFunction : public PScope, public LineInfo {
class PFunction : public LineInfo {
public:
explicit PFunction(perm_string name, LexicalScope*parent, bool is_auto);
explicit PFunction(svector<PWire *>*p, Statement *s);
~PFunction();
void set_ports(svector<PWire *>*p);
void set_statement(Statement *s);
void set_return(PTaskFuncArg t);
void set_output(PWire*);
void elaborate_scope(Design*des, NetScope*scope) const;
/* elaborate the ports and return value. */
void elaborate_sig(Design *des, NetScope*) const;
/* Elaborate the behavioral statement. */
void elaborate(Design *des, NetScope*) const;
bool is_auto() const { return is_auto_; };
/* Functions are elaborated in 2 passes. */
void elaborate_1(Design *des, const string &path) const;
void elaborate_2(Design *des, const string &path) const;
void dump(ostream&, unsigned) const;
private:
PTaskFuncArg return_type_;
PWire*out_;
svector<PWire *> *ports_;
Statement *statement_;
bool is_auto_;
};
/*
* $Log: PTask.h,v $
* Revision 1.6 1999/09/30 21:28:34 steve
* Handle mutual reference of tasks by elaborating
* task definitions in two passes, like functions.
*
* Revision 1.5 1999/09/01 20:46:19 steve
* Handle recursive functions and arbitrary function
* references to other functions, properly pass
* function parameters and save function results.
*
* Revision 1.4 1999/08/25 22:22:41 steve
* elaborate some aspects of functions.
*
* Revision 1.3 1999/07/31 19:14:47 steve
* Add functions up to elaboration (Ed Carter)
*
* 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.
*
*/
#endif
-37
View File
@@ -1,37 +0,0 @@
/*
* Copyright (c) 2003-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
* 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 "PUdp.h"
PUdp::PUdp(perm_string n, unsigned nports)
: ports(nports), sequential(false), initial(verinum::Vx), name_(n)
{
}
unsigned PUdp::find_port(const char*name)
{
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
if (ports[idx] == name)
return idx;
}
return ports.count();
}
+34 -13
View File
@@ -1,7 +1,7 @@
#ifndef __PUdp_H
#define __PUdp_H
/*
* Copyright (c) 1998-2011 Stephen Williams ([email protected])
* Copyright (c) 1998 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,20 +18,25 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: PUdp.h,v 1.3 1999/06/15 03:44:53 steve Exp $"
#endif
# include <map>
# include "LineInfo.h"
# include "StringHeap.h"
# include "svector.h"
# include <string>
# include "verinum.h"
class PExpr;
svector<string>::svector<string>(unsigned size)
: nitems_(size), items_(new string[size])
{
}
/*
* This class represents a parsed UDP. This is a much simpler object
* than a module or macromodule.
* then a module or macromodule.
*
* - all ports are scalar,
* - all ports are scaler,
* - pin 0 (the first port) is always output,
* and the remaining pins are input.
*
@@ -46,16 +51,15 @@ class PExpr;
* the current output.
*
* If the UDP is sequential, the "initial" member is taken to be the
* initial value assigned in the source, or 'x' if none is given.
* intial value assigned in the source, or 'x' if none is given.
*/
class PUdp : public LineInfo {
class PUdp {
public:
explicit PUdp(perm_string n, unsigned nports);
explicit PUdp(const string&n, unsigned nports)
: ports(nports), sequential(false), initial(verinum::Vx), name_(n) { }
svector<string>ports;
unsigned find_port(const char*name);
bool sequential;
svector<string>tinput;
@@ -64,16 +68,33 @@ class PUdp : public LineInfo {
verinum::V initial;
map<string,PExpr*> attributes;
map<string,string> attributes;
void dump(ostream&out) const;
perm_string name_;
private:
const string name_;
private: // Not implemented
PUdp(const PUdp&);
PUdp& operator= (const PUdp&);
};
/*
* $Log: PUdp.h,v $
* 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
+28 -197
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2012 Stephen Williams ([email protected])
* Copyright (c) 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,27 +16,16 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: PWire.cc,v 1.2 1999/09/10 05:02:09 steve Exp $"
#endif
# include "config.h"
# include "PWire.h"
# include "PExpr.h"
# include <cassert>
# include <assert.h>
PWire::PWire(perm_string n,
NetNet::Type t,
NetNet::PortType pt,
ivl_variable_type_t dt)
: name_(n), type_(t), port_type_(pt), data_type_(dt),
signed_(false), isint_(false),
port_set_(false), net_set_(false), is_scalar_(false),
error_cnt_(0), lidx_(0), ridx_(0), enum_type_(0), struct_type_(0),
discipline_(0)
PWire::PWire(const string&n, NetNet::Type t, NetNet::PortType pt)
: name_(n), type_(t), port_type_(pt), lidx_(0), ridx_(0)
{
if (t == NetNet::INTEGER) {
type_ = NetNet::REG;
signed_ = true;
isint_ = true;
}
}
NetNet::Type PWire::get_wire_type() const
@@ -44,11 +33,6 @@ NetNet::Type PWire::get_wire_type() const
return type_;
}
perm_string PWire::basename() const
{
return name_;
}
bool PWire::set_wire_type(NetNet::Type t)
{
assert(t != NetNet::IMPLICIT);
@@ -58,22 +42,12 @@ bool PWire::set_wire_type(NetNet::Type t)
type_ = t;
return true;
case NetNet::IMPLICIT_REG:
if (t == NetNet::REG) {
type_ = t;
return true;
}
if (t == NetNet::INTEGER) {
type_ = NetNet::REG;
isint_ = true;
return true;
}
if (t == NetNet::REG) { type_ = t; return true; }
if (t == NetNet::INTEGER) {type_ = t; return true; }
return false;
case NetNet::REG:
if (t == NetNet::INTEGER) {
isint_ = true;
return true;
}
if (t == NetNet::REG) return true;
if (t == NetNet::INTEGER) {type_ = t; return true; }
return false;
default:
if (type_ != t)
@@ -109,172 +83,29 @@ bool PWire::set_port_type(NetNet::PortType pt)
}
}
bool PWire::set_data_type(ivl_variable_type_t dt)
void PWire::set_range(PExpr*m, PExpr*l)
{
if (data_type_ != IVL_VT_NO_TYPE) {
if (data_type_ != dt)
return false;
else
return true;
}
assert(data_type_ == IVL_VT_NO_TYPE);
data_type_ = dt;
return true;
}
ivl_variable_type_t PWire::get_data_type() const
{
return data_type_;
}
void PWire::set_signed(bool flag)
{
signed_ = flag;
}
bool PWire::get_signed() const
{
return signed_;
}
bool PWire::get_isint() const
{
return isint_;
}
bool PWire::get_scalar() const
{
return is_scalar_;
}
void PWire::set_range_scalar(PWSRType type)
{
is_scalar_ = true;
switch (type) {
case SR_PORT:
if (port_set_) {
cerr << get_fileline() << ": error: Port ``" << name_
<< "'' has already been declared a port." << endl;
error_cnt_ += 1;
} else {
port_set_ = true;
}
return;
case SR_NET:
if (net_set_) {
cerr << get_fileline() << ": error: Net ``" << name_
<< "'' has already been declared." << endl;
error_cnt_ += 1;
} else {
net_set_ = true;
}
return;
case SR_BOTH:
if (port_set_ || net_set_) {
if (port_set_) {
cerr << get_fileline() << ": error: Port ``" << name_
<< "'' has already been declared a port." << endl;
error_cnt_ += 1;
}
if (net_set_) {
cerr << get_fileline() << ": error: Net ``" << name_
<< "'' has already been declared." << endl;
error_cnt_ += 1;
}
} else {
port_set_ = true;
net_set_ = true;
}
return;
}
}
void PWire::set_range(const list<pform_range_t>&rlist, PWSRType type)
{
switch (type) {
case SR_PORT:
if (port_set_) {
cerr << get_fileline() << ": error: Port ``" << name_
<< "'' has already been declared a port." << endl;
error_cnt_ += 1;
} else {
port_ = rlist;
port_set_ = true;
is_scalar_ = false;
}
return;
case SR_NET:
if (net_set_) {
cerr << get_fileline() << ": error: Net ``" << name_
<< "'' has already been declared." << endl;
error_cnt_ += 1;
} else {
net_ = rlist;
net_set_ = true;
is_scalar_ = false;
}
return;
case SR_BOTH:
if (port_set_ || net_set_) {
if (port_set_) {
cerr << get_fileline() << ": error: Port ``" << name_
<< "'' has already been declared a port." << endl;
error_cnt_ += 1;
}
if (net_set_) {
cerr << get_fileline() << ": error: Net ``" << name_
<< "'' has already been declared." << endl;
error_cnt_ += 1;
}
} else {
port_ = rlist;
port_set_ = true;
net_ = rlist;
net_set_ = true;
is_scalar_ = false;
}
return;
}
msb_ = svector<PExpr*>(msb_,m);
lsb_ = svector<PExpr*>(lsb_,l);
}
void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
{
if (lidx_ != 0 || ridx_ != 0) {
cerr << get_fileline() << ": error: Array ``" << name_
<< "'' has already been declared." << endl;
error_cnt_ += 1;
} else {
lidx_ = ldx;
ridx_ = rdx;
}
assert(lidx_ == 0);
assert(ridx_ == 0);
assert((type_ == NetNet::REG) || (type_ == NetNet::INTEGER));
lidx_ = ldx;
ridx_ = rdx;
}
void PWire::set_enumeration(enum_type_t*enum_type)
{
assert(enum_type_ == 0);
assert(struct_type_ == 0);
enum_type_ = enum_type;
}
/*
* $Log: PWire.cc,v $
* Revision 1.2 1999/09/10 05:02:09 steve
* Handle integers at task parameters.
*
* Revision 1.1 1999/06/17 05:34:42 steve
* Clean up interface of the PWire class,
* Properly match wire ranges.
*
*/
void PWire::set_struct_type(struct_type_t*type)
{
assert(enum_type_ == 0);
assert(struct_type_ == 0);
struct_type_ = type;
}
void PWire::set_discipline(ivl_discipline_t d)
{
assert(discipline_ == 0);
discipline_ = d;
}
ivl_discipline_t PWire::get_discipline(void) const
{
return discipline_;
}
+45 -67
View File
@@ -1,7 +1,7 @@
#ifndef __PWire_H
#define __PWire_H
/*
* Copyright (c) 1998-2009,2012 Stephen Williams ([email protected])
* Copyright (c) 1998 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,48 +18,30 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: PWire.h,v 1.6 1999/11/27 19:07:57 steve Exp $"
#endif
# include "netlist.h"
# include "LineInfo.h"
# include <list>
# include <map>
# include "StringHeap.h"
#ifdef HAVE_IOSFWD
# include <iosfwd>
#else
# include <map>
# include "svector.h"
class ostream;
#endif
class PExpr;
class Design;
/*
* The different type of PWire::set_range() calls.
*/
enum PWSRType {SR_PORT, SR_NET, SR_BOTH};
/*
* Wires include nets, registers and ports. A net or register becomes
* a port by declaration, so ports are not separate. The module
* a port by declaration, so ports are not seperate. The module
* identifies a port by keeping it in its port list.
*
* The hname parameter to the constructor is a hierarchical name. It
* is the name of the wire within a module, so does not include the
* current scope or any instances. Modules contain all the wires, so
* from that perspective, sub-scopes within the module are a part of
* the wire name.
*/
class PWire : public LineInfo {
public:
PWire(perm_string name,
NetNet::Type t,
NetNet::PortType pt,
ivl_variable_type_t dt);
PWire(const string&n, NetNet::Type t, NetNet::PortType pt);
// Return a hierarchical name.
perm_string basename() const;
const string&name() const { return name_; }
NetNet::Type get_wire_type() const;
bool set_wire_type(NetNet::Type);
@@ -67,66 +49,62 @@ class PWire : public LineInfo {
NetNet::PortType get_port_type() const;
bool set_port_type(NetNet::PortType);
void set_signed(bool flag);
bool get_signed() const;
bool get_isint() const;
bool get_scalar() const;
bool set_data_type(ivl_variable_type_t dt);
ivl_variable_type_t get_data_type() const;
void set_range_scalar(PWSRType type);
void set_range(const std::list<pform_range_t>&ranges, PWSRType type);
void set_range(PExpr*msb, PExpr*lsb);
void set_memory_idx(PExpr*ldx, PExpr*rdx);
void set_enumeration(enum_type_t*enum_type);
void set_struct_type(struct_type_t*type);
void set_discipline(ivl_discipline_t);
ivl_discipline_t get_discipline(void) const;
map<perm_string,PExpr*> attributes;
map<string,string> attributes;
// Write myself to the specified stream.
void dump(ostream&out, unsigned ind=4) const;
void dump(ostream&out) const;
NetNet* elaborate_sig(Design*, NetScope*scope) const;
void elaborate(Design*, NetScope*scope) const;
private:
perm_string name_;
string name_;
NetNet::Type type_;
NetNet::PortType port_type_;
ivl_variable_type_t data_type_;
bool signed_;
bool isint_; // original type of integer
// These members hold expressions for the bit width of the
// wire. If they do not exist, the wire is 1 bit wide. If they
// do exist, they represent the packed dimensions of the
// bit. The first item in the list is the first range, and so
// on. For example "reg [3:0][7:0] ..." will contains the
// range_t object for [3:0] first and [7:0] last.
std::list<pform_range_t>port_;
bool port_set_;
std::list<pform_range_t>net_;
bool net_set_;
bool is_scalar_;
unsigned error_cnt_;
// wire. If they do not exist, the wire is 1 bit wide.
svector<PExpr*>msb_;
svector<PExpr*>lsb_;
// If this wire is actually a memory, these indices will give
// me the size and address range of the memory.
PExpr*lidx_;
PExpr*ridx_;
enum_type_t*enum_type_;
struct_type_t*struct_type_;
ivl_discipline_t discipline_;
private: // not implemented
PWire(const PWire&);
PWire& operator= (const PWire&);
};
/*
* $Log: PWire.h,v $
* Revision 1.6 1999/11/27 19:07:57 steve
* Support the creation of scopes.
*
* Revision 1.5 1999/06/17 05:34:42 steve
* Clean up interface of the PWire class,
* Properly match wire ranges.
*
* Revision 1.4 1999/06/02 15:38:46 steve
* Line information with nets.
*
* Revision 1.3 1999/04/19 01:59:36 steve
* Add memories to the parse and elaboration phases.
*
* Revision 1.2 1998/11/23 00:20:22 steve
* NetAssign handles lvalues as pin links
* instead of a signal pointer,
* Wire attributes added,
* Ability to parse UDP descriptions added,
* XNF generates EXT records for signals with
* the PAD attribute.
*
* Revision 1.1 1998/11/03 23:28:55 steve
* Introduce verilog to CVS.
*
*/
#endif
-83
View File
@@ -1,83 +0,0 @@
* Getting Started with Icarus Verilog
Icarus Verilog is a Verilog compiler. It is suitable for use as a
simulator, and, to some degree, synthesizer. Icarus Verilog runs under
Linux and a variety of UNIX systems, as well as Windows as a command
line tool, so the instructions are generally applicable to all
environments. Note that this is only a quick start. For more detailed
documentation, see the manual page for the iverilog command.
* Hello, World!
The first thing you want to do as a user is learn how to compile and
execute even the most trivial design. For the purposes of simulation,
we use as our example *the* most trivial simulation:
module main;
initial
begin
$display("Hello, World");
$finish ;
end
endmodule
By a text editor (or copy hello.vl from the Icarus Verilog examples
directory) arrange for this program to be in a text file, "hello.vl".
Next, compile this program with a command like this:
% iverilog -o hello hello.vl
The results of this compile are placed into the file "hello", as the
"-o" flag tells the compiler where to place the compiled result. Next,
execute the compiled program like so:
% vvp hello
Hello, World
And there it is, the program has been executed. So what happened? The
first step, the "iverilog" command, read and interpreted the source
file, then generated a compiled result. The compiled form may be
selected by command line switches, but the default form is the VVP
format, which is actually run by the "vvp" command.
The "iverilog" and "vvp" commands are the only commands that users
use to invoke Icarus Verilog. What the compiler actually does is
controlled by command line switches. In our little example, we asked
the compiler to compile the source program to the default vvp form,
which is in turn executed by the vvp program.
* Windows Install
The easiest way to install under Windows is to get a precompiled
installer for the version you wish to install. Icarus Verilog is
distributed for Windows users as a self-installing .exe. Just execute
the installer and follow the instructions. During the install, take
note of the directory where the program is installed: for example,
C:\iverilog is a good place to install.
Once the binary is installed, you need to add the bin directory to
your execution path. The executables you need are in C:\iverilog\bin,
where the "C:\iverilog" part is actually the root of where you
installed the package. The programs are in the bin subdirectory. Put
this directory in your PATH environment variable, and the above
commands become accessible to you at the command line prompt, or even
in batch files.
* Linux Install
Under Linux, the install is even easier. For RedHat and Mandrake based
systems, there is the appropriate RPM file. Just install the package
with the "rpm -U <file>" command. Debian users should get Icarus
Verilog packages from the main Debian software site.
* Install From Source
In this case, see README.txt and other documentation that comes with
the source.
+185 -303
View File
@@ -1,24 +1,23 @@
THE ICARUS VERILOG COMPILATION SYSTEM
Copyright 2000-2004 Stephen Williams
THE ICARUS VERILOG COMPILATION SYSTEM
September 18, 1999
1.0 What is ICARUS Verilog?
Icarus Verilog is intended to compile ALL of the Verilog HDL as
described in the IEEE-1364 standard. Of course, it's not quite there
yet. It does currently handle a mix of structural and behavioral
constructs. For a view of the current state of Icarus Verilog, see its
home page at <http://www.icarus.com/eda/verilog>.
Icarus Verilog is intended to compile ALL of the Verilog HDL as described
in the IEEE-1364 standard. Of course, it's not quite there yet. It does
currently handle a mix of structural and behavioral constructs. For a
view of the current state of Icarus Verilog, see its home page at
<http://www.icarus.com/eda/verilog>.
IVL is not aimed at being a simulator in the traditional sense, but a
compiler that generates code employed by back-end tools. These back-
end tools currently include a simulator written in C++ called VVM
and an XNF (Xilinx Netlist Format) generator. See "vvm.txt" and
"xnf.txt" for further details on these back-end processors. In the
future, backends are expected for EDIF/LPM, structural Verilog, etc.
Icarus Verilog is not aimed at being a simulator in the traditional
sense, but a compiler that generates code employed by back-end
tools.
For instructions on how to run Icarus Verilog,
see the ``iverilog'' man page.
2.0 Building/Installing Icarus Verilog From Source
2.0 Building/Installing IVL From Source
If you are starting from source, the build process is designed to be
as simple as practical. Someone basically familiar with the target
@@ -26,51 +25,22 @@ system and C/C++ compilation should be able to build the source
distribution with little effort. Some actual programming skills are
not required, but helpful in case of problems.
If you are building for Windows, see the mingw.txt file.
2.1 Compile Time Prerequisites
You need the following software to compile Icarus Verilog from source
on a UNIX-like system:
- GNU Make
The Makefiles use some GNU extensions, so a basic POSIX
The Makefiles use some GNU extensions to, so a basic POSIX
make will not work. Linux systems typically come with a
satisfactory make. BSD based systems (i.e., NetBSD, FreeBSD)
typically have GNU make as the gmake program.
satisfactory make.
- ISO C++ Compiler
The ivl and ivlpp programs are written in C++ and make use
of templates and some of the standard C++ library. egcs and
recent gcc compilers with the associated libstdc++ are known
to work. MSVC++ 5 and 6 are known to definitely *not* work.
The ivl program is written in C++ and makes use of templates
and some of the standard C++ library. egcs compilers with
the associated libstdc++ are known to work.
- bison and flex
- gperf 2.7
The lexical analyzer doesn't recognize keywords directly,
but instead matches symbols and looks them up in a hash
table in order to get the proper lexical code. The gperf
program generates the lookup table.
A version problem with this program is the most common cause
of difficulty. See the Icarus Verilog FAQ.
- readline 4.2
On Linux systems, this usually means the readline-devel
rpm. In any case, it is the development headers of readline
that are needed.
- termcap
The readline library in turn uses termcap.
If you are building from CVS, you will also need software to generate
the configure scripts.
- autoconf 2.53
This generates configure scripts from configure.in. The 2.53
or later versions are known to work, autoconf 2.13 is
reported to *not* work.
- bison
2.2 Compilation
@@ -81,56 +51,16 @@ with the commands:
./configure
make
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:
--prefix=<root>
The default is /usr/local, which causes the tool suite to
be compiled for install in /usr/local/bin,
/usr/local/share/ivl, etc.
I recommend that if you are configuring for precompiled
binaries, use --prefix=/usr. On Solaris systems, it is
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.
2.3 (Optional) Testing
To run a simple test before installation, execute
make check
The commands printed by this run might help you in running Icarus
Verilog on your own Verilog sources before the package is installed
by root.
2.4 Installation
2.3 Installation
Now install the files in an appropriate place. (The makefiles by
default install in /usr/local unless you specify a different prefix
with the --prefix=<path> flag to the configure command.) You may need
to do this as root to gain access to installation directories.
with the --prefix=<path> flag to the configure command.) Do this as
root.
make install
2.5 Uninstallation
The generated Makefiles also include the uninstall target. This should
remove all the files that ``make install'' creates.
3.0 How Icarus Verilog Works
3.0 How IVL Works
This tool includes a parser which reads in Verilog (plus extensions)
and generates an internal netlist. The netlist is passed to various
@@ -149,16 +79,15 @@ only sees a single input file. See ivlpp/ivlpp.txt for details.
3.2 Parse
The Verilog compiler starts by parsing the Verilog source file. The
output of the parse is a list of Module objects in "pform". The pform
The verilog compiler starts by parsing the verilog source file. The
output of the parse in a list of Module objects in PFORM. The pform
(see pform.h) is mostly a direct reflection of the compilation
step. There may be dangling references, and it is not yet clear which
module is the root.
One can see a human readable version of the final pform by using the
``-P <path>'' flag to the ``ivl'' subcommand. This will cause ivl
to dump the pform into the file named <path>. (Note that this is not
normally done, unless debugging the ``ivl'' subcommand.)
One can see a human readable version of the final PFORM by using the
``-P <path>'' flag to the compiler. This will cause ivl to dump the
PFORM into the file named <path>.
3.3 Elaboration
@@ -166,78 +95,116 @@ This phase takes the pform and generates a netlist. The driver selects
(by user request or lucky guess) the root module to elaborate,
resolves references and expands the instantiations to form the design
netlist. (See netlist.txt.) Final semantic checks are performed during
elaboration, and some simple optimizations are performed. The netlist
includes all the behavioral descriptions, as well as gates and wires.
elaboration, and some simple optimizations are performed.
The elaborate() function performs the elaboration.
One can see a human readable version of the final, elaborated and
optimized netlist by using the ``-N <path>'' flag to the compiler. If
elaboration succeeds, the final netlist (i.e., after optimizations but
elaboration succeeds, the final netlist (i.e. after optimizations but
before code generation) will be dumped into the file named <path>.
Elaboration is actually performed in two steps: scopes and parameters
first, followed by the structural and behavioral elaboration.
3.3.1 Scope Elaboration
This pass scans through the pform looking for scopes and parameters. A
tree of NetScope objects is built up and placed in the Design object,
with the root module represented by the root NetScope object. The
elab_scope.cc file contains most of the code for handling this phase.
The tail of the elaborate_scope behavior (after the pform is
traversed) includes a scan of the NetScope tree to locate defparam
assignments that were collected during scope elaboration. This is when
the defparam overrides are applied to the parameters.
3.3.2 Netlist Elaboration
After the scopes and parameters are generated and the NetScope tree
fully formed, the elaboration runs through the pform again, this time
generating the structural and behavioral netlist. Parameters are
elaborated and evaluated by now so all the constants of code
generation are now known locally, so the netlist can be generated by
simply passing through the pform.
3.4 Optimization
This is actually a collection of processing steps that perform
optimizations that do not depend on the target technology. Examples of
some useful transformations are
some useful transformations would be,
- eliminate null effect circuitry
- eliminate null effect circuitry,
- combinational reduction
- constant propagation
- Constant propagation
The actual functions performed are specified on the ivl command line by
the -F flags (see below).
The actual functions performed are specified on the command line by
the -F flags (See below).
3.5 Code Generation
This step takes the design netlist and uses it to drive the code
generator (see target.h). This may require transforming the
generator. (See target.h.) This may require transforming the
design to suit the technology.
The emit() method of the Design class performs this step. It runs
through the design elements, calling target functions as need arises
to generate actual output.
The user selects the target code generator with the -t flag on the
The target code generator to used is given by the -t flag on the
command line.
3.6 ATTRIBUTES
4.0 Running Verilog
NOTE: The $attribute syntax will soon be deprecated in favor of the
Verilog-2001 attribute syntax, which is cleaner and standardized.
The preferred way to invoke the compiler with the verilog(1)
command. This program invokes the preprocessor (ivlpp) and the
compiler (ivl) with the proper command line options to get the job
done in a friendly way. See the verilog(1) man page for usage details.
The parser accepts, as an extension to Verilog, the $attribute module
4.1 Running IVL Directly
The ivl command is the compiler driver, that invokes the parser,
optimization functions and the code generator.
Usage: ivl <options>... file
ivl -h
-F <name>
Use this flag to request an optimization function be applied
to the netlist before it is sent to the target output
stage. Any number of -F options may be given, to specify a
variety of processing steps. The steps will be applied in
order, with the output of one uses as the input to the next.
The function is specified by name. Use the "ivl -h" command to
get a list of configured function names.
-f <assign>
Use this flag to set a parameter value. The format of the
assignment is <key>=<value> where key is any string up to the
first '=', and <value> is the rest of the option. If the '='
is omitted, then the key is assigned the empty string.
The useful keys are defined by the functions and the target in
use. These assignments are specifically useful for passing
target specific information to the target back-end, or
options/parameters to optimization functions, if any are defined.
-N <file>
Dump the elaborated netlist to the named file. The netlist is
the folly elaborated netlist, after all the function modules
are applied and right before the output generator is
called. This is an aid for debugging the compiler, and the
output generator in particular.
-o <file>
Normally, the generated result is sent to standard
output. Use the -o flag to specify an output file for the
generated result.
-P <file>
Write the PForm of the parsed input to the specified file.
The pform is the compiler's understanding of the input after
parsing and before elaboration. This is an aid for debugging
the compiler.
-s <module>
Normally, ivl will elaborate the only module in the source
file. If there are multiple modules, use this option to select
the module to be used as the top-level module.
-t <name>
Select the output format for the compiled result. Use the
"ivl -h" command to get a list of configured targets.
-v
Print version and copyright information for ivl.
ATTRIBUTES
The parser accepts as an extension to Verilog the $attribute module
item. The syntax of the $attribute item is:
$attribute (<identifier>, <key>, <value>);
The $attribute keyword looks like a system task invocation. The
difference here is that the parameters are more restricted than those
difference here is that the parameters are more restricted then those
of a system task. The <identifier> must be an identifier. This will be
the item to get an attribute. The <key> and <value> are strings, not
expressions, that give the key and the value of the attribute to be
@@ -254,32 +221,21 @@ names a primitive earlier in the compilation unit and the statement is
placed in global scope, instead of within a module. The semicolon is
not part of a type attribute.
Currently, type attributes are only supported for UDP types.
Note that attributes are also occasionally used for communication
between processing steps. Processing steps that are aware of others
may place attributes on netlist objects to communicate information to
later steps.
Icarus Verilog also accepts the Verilog 2001 syntax for
attributes. They have the same general meaning as with the $attribute
syntax, but they are attached to objects by position instead of by
name. Also, the key is a Verilog identifier instead of a string.
4.0 Running iverilog
The preferred way to invoke the compiler is with the iverilog(1)
command. This program invokes the preprocessor (ivlpp) and the
compiler (ivl) with the proper command line options to get the job
done in a friendly way. See the iverilog(1) man page for usage details.
4.1 EXAMPLES
Example: Compiling "hello.vl"
------------------------ hello.vl ----------------------------
module main();
initial
initial
begin
$display("Hi there");
$finish ;
@@ -289,189 +245,115 @@ endmodule
--------------------------------------------------------------
Ensure that "iverilog" is on your search path, and the vpi library
Insure that "verilog" is on your search path, and the vpi library
is available.
To compile the program:
For csh -
iverilog hello.vl
setenv PATH /usr/local/bin:$PATH
setenv VPI_MODULE_PATH /usr/local/lib/ivl
verilog hello.vl
(The above presumes that /usr/local/include and /usr/local/lib are
part of the compiler search path, which is usually the case for gcc.)
To run the program:
To run the program
./a.out
./hello
You can use the "-o" switch to name the output command to be generated
by the compiler. See the iverilog(1) man page.
5.0 Unsupported Constructs
Icarus Verilog is in development - as such it still only supports a
(growing) subset of Verilog. Below is a description of some of the
currently unsupported Verilog features. This list is not exhaustive,
and does not account for errors in the compiler. See the Icarus
Verilog web page for the current state of support for Verilog, and in
particular, browse the bug report database for reported unsupported
constructs.
IVL is in development - as such it still only supports a (growing) subset
of verilog. Below is a description of some of the currently unsupported
verilog features. This list is not exhaustive, and does not account
for errors in the compiler. See the Icarus Verilog web page for the
current state of support for Verilog.
- System functions are supported, but the return value is a little
tricky. See SYSTEM FUNCTION TABLE FILES in the iverilog man page.
- Min/Typ/Max expressions: Example: a = (1 : 6 : 14);
- Specify blocks are parsed but ignored in general.
- Memories work, but only in procedural code.
- trireg is not supported. tri0 and tri1 are supported.
reg [1:0] b [2:0], bar;
wire [1:0] foo;
always foo = b[i]; // sorry
always @(i) bar = b[i]; // OK
- tran primitives, i.e. tran, tranif1, tranif0, rtran, rtranif1
and rtranif0 are not supported.
- `timescale directive
- Net delays, of the form "wire #N foo;" do not work. Delays in
every other context do work properly, including the V2001 form
"wire #5 foo = bar;"
- force/release/assign/deassign procedural assignments not
supported.
- Event controls inside non-blocking assignments are not supported.
i.e.: a <= @(posedge clk) b;
- block disable not supported, i.e.:
- Macro arguments are not supported. `define macros are supported,
but they cannot take arguments.
begin : foo
[...]
disable foo; // sorry
[...]
end
5.1 Nonstandard Constructs or Behaviors
- fork/join is not supported in vvm runtime
Icarus Verilog includes some features that are not part of the
IEEE1364 standard, but have well defined meaning, and also sometimes
gives nonstandard (but extended) meanings to some features of the
language that are defined. See the "extensions.txt" documentation for
more details.
- Structural shift operators are in general not supported.
Procedural expressions are OK. Constant expressions are OK.
$is_signed(<expr>)
This system function returns 1 if the expression contained is
signed, or 0 otherwise. This is mostly of use for compiler
regression tests.
assign foo = a << b; // sorry
always @(a or b) foo = a << b; // OK
parameter foo = a << b; // OK
$sizeof(<expr>)
$bits(<expr>)
The $bits system function returns the size in bits of the
expression that is its argument. The result of this
function is undefined if the argument doesn't have a
self-determined size.
- Functions in structural contexts are not supported.
The $sizeof function is deprecated in favor of $bits, which is
the same thing, but included in the SystemVerilog definition.
assign foo = user_function(a,b); // sorry
always @(a or b) foo = user_function(a,b); // OK
$simtime
The $simtime system function returns as a 64bit value the
simulation time, unscaled by the time units of local
scope. This is different from the $time and $stime functions
which return the scaled times. This function is added for
regression testing of the compiler and run time, but can be
used by applications who really want the simulation time.
- multiplicative operators (*, /, %) are not supported.
Note that the simulation time can be confusing if there are
lots of different `timescales within a design. It is not in
general possible to predict what the simulation precision will
turn out to be.
assign foo = a * b; // sorry
always @(a or b) foo = a * b; // sorry
$mti_random()
$mti_dist_uniform
These functions are similar to the IEEE1364 standard $random
functions, but they use the Mersenne Twister (MT19937)
algorithm. This is considered an excellent random number
generator, but does not generate the same sequence as the
standardized $random.
- event data type is not supported.
Builtin system functions
- real data type not supported.
Certain of the system functions have well defined meanings, so
can theoretically be evaluated at compile time, instead of
using runtime VPI code. Doing so means that VPI cannot
override the definitions of functions handled in this
manner. On the other hand, this makes them synthesizable, and
also allows for more aggressive constant propagation. The
functions handled in this manner are:
- system functions are not supported. (User defined functions are
supported, and system tasks are supported.)
$bits
$signed
$sizeof
$unsigned
assign foo = $some_function(a,b); // sorry
always @(a or b) foo = $some_function(a,b); // sorry
Implementations of these system functions in VPI modules will
be ignored.
- non-constant delay expressions, i.e.:
Preprocessing Library Modules
reg [7:0] del;
always #(reg) $display($time,,"del = %d", del); // sorry
Icarus Verilog does preprocess modules that are loaded from
libraries via the -y mechanism. However, the only macros
defined during compilation of that file are those that it
defines itself (or includes) or that are defined on the
command line or command file.
- drive strengths are parsed, bug ignored.
Specifically, macros defined in the non-library source files
are not remembered when the library module is loaded. This is
intentional. If it were otherwise, then compilation results
might vary depending on the order that libraries are loaded,
and that is too unpredictable.
Specify blocks are parsed but ignored in general.
It is said that some commercial compilers do allow macro
definitions to span library modules. That's just plain weird.
Width in %t Time Formats
Standard Verilog does not allow width fields in the %t formats
of display strings. For example, this is illegal:
$display("Time is %0t", %time);
Standard Verilog instead relies on the $timeformat to
completely specify the format.
Icarus Verilog allows the programmer to specify the field
width. The "%t" format in Icarus Verilog works exactly as it
does in standard Verilog. However, if the programmer chooses
to specify a minimum width (i.e., "%5t"), then for that display
Icarus Verilog will override the $timeformat minimum width and
use the explicit minimum width.
vpiScope iterator on vpiScope objects.
In the VPI, the normal way to iterate over vpiScope objects
contained within a vpiScope object, is the vpiInternalScope
iterator. Icarus Verilog adds support for the vpiScope
iterator of a vpiScope object, that iterates over *everything*
the is contained in the current scope. This is useful in cases
where one wants to iterate over all the objects in a scope
without iterating over all the contained types explicitly.
time 0 race resolution.
Combinational logic is routinely modeled using always
blocks. However, this can lead to race conditions if the
inputs to the combinational block are initialized in initial
statements. Icarus Verilog slightly modifies time 0 scheduling
by arranging for always statements with ANYEDGE sensitivity
lists to be scheduled before any other threads. This causes
combinational always blocks to be triggered when the values in
the sensitivity list are initialized by initial threads.
Nets with Types
Icarus Verilog support an extension syntax that allows nets
and regs to be explicitly typed. The currently supported types
are logic, bool and real. This implies that "logic" and "bool"
are new keywords. Typical syntax is:
wire real foo = 1.0;
reg logic bar, bat;
... and so forth. The syntax can be turned off by using the
-g2 flag to iverilog, and turned on explicitly with the -g2x
flag to iverilog.
6.0 CREDITS
Except where otherwise noted, Icarus Verilog, ivl and ivlpp are
Copyright Stephen Williams. The proper notices are in the head of each
file. However, I have early on received aid in the form of fixes,
Verilog guidance, and especially testing from many people. Testers in
particular include a larger community of people interested in a GPL
Verilog for Linux.
Except where otherwise noted, ivl and ivlpp are Copyright Stephen
Williams. The proper notices are in the head of each file. However,
I have received aid in the form of fixes, Verilog guidance, and
especially testing from many people, including (in alphabetical order):
Eric Aardoom <[email protected]>
Ed Carter <[email protected]>
Larry Doolittle <[email protected]>
Guy Hutchison <[email protected]>
Ales Hvezda <[email protected]>
James Lee <[email protected]>
Peter Monta <[email protected]>
Daniel H. Nelsen <[email protected]>
Stefan Petersen <[email protected]>
Jason Schonberg <[email protected]>
Stuart Sutherland <[email protected]>
Stephen Tell <[email protected]>
Stefan Theide <[email protected]>
Steve Wilson <[email protected]>
and others. Testers in particular include a larger community of people
interested in a GPL Verilog for Linux. Special thanks to Steve Wilson
for collecting and organizing the test suite code for all those testers.
+109 -202
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2008,2010 Stephen Williams ([email protected])
* Copyright (c) 1998 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,8 +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
*/
# include "config.h"
#if !defined(WINNT)
#ident "$Id: Statement.cc,v 1.16 1999/09/29 18:36:02 steve Exp $"
#endif
# include "Statement.h"
# include "PExpr.h"
@@ -26,22 +27,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;
if (de) delay_.set_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;
}
PAssign_::~PAssign_()
@@ -50,28 +49,18 @@ PAssign_::~PAssign_()
delete rval_;
}
PAssign::PAssign(PExpr*lval__, PExpr*ex)
: PAssign_(lval__, ex, false), op_(0)
PAssign::PAssign(PExpr*lval, PExpr*ex)
: PAssign_(lval, ex)
{
}
PAssign::PAssign(PExpr*lval__, char op, PExpr*ex)
: PAssign_(lval__, ex, false), op_(op)
PAssign::PAssign(PExpr*lval, PExpr*d, PExpr*ex)
: PAssign_(lval, d, ex)
{
}
PAssign::PAssign(PExpr*lval__, PExpr*d, PExpr*ex)
: PAssign_(lval__, d, ex), op_(0)
{
}
PAssign::PAssign(PExpr*lval__, PExpr*cnt, PEventStatement*d, PExpr*ex)
: PAssign_(lval__, cnt, d, ex), op_(0)
{
}
PAssign::PAssign(PExpr*lval__, PExpr*ex, bool is_constant)
: PAssign_(lval__, ex, is_constant), op_(0)
PAssign::PAssign(PExpr*lval, PEventStatement*d, PExpr*ex)
: PAssign_(lval, d, ex)
{
}
@@ -79,18 +68,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)
{
}
@@ -98,57 +82,30 @@ PAssignNB::~PAssignNB()
{
}
PBlock::PBlock(perm_string n, LexicalScope*parent, BL_TYPE t)
: PScope(n, parent), bl_type_(t)
PBlock::PBlock(const string&n, BL_TYPE t, const svector<Statement*>&st)
: name_(n), bl_type_(t), list_(st)
{
}
PBlock::PBlock(BL_TYPE t, const svector<Statement*>&st)
: bl_type_(t), list_(st)
{
}
PBlock::PBlock(BL_TYPE t)
: PScope(perm_string()), bl_type_(t)
: bl_type_(t)
{
}
PBlock::~PBlock()
{
for (unsigned idx = 0 ; idx < list_.size() ; idx += 1)
for (unsigned idx = 0 ; idx < list_.count() ; idx += 1)
delete list_[idx];
}
void PBlock::set_statement(const vector<Statement*>&st)
PCallTask::PCallTask(const string&n, const svector<PExpr*>&p)
: name_(n), parms_(p)
{
list_ = st;
}
PCallTask::PCallTask(const pform_name_t&n, const list<PExpr*>&p)
: path_(n), parms_(p.size())
{
list<PExpr*>::const_iterator cur = p.begin();
for (size_t idx = 0 ; idx < parms_.size() ; idx += 1) {
parms_[idx] = *cur;
++cur;
}
assert(cur == p.end());
}
PCallTask::PCallTask(perm_string n, const list<PExpr*>&p)
: parms_(p.size())
{
list<PExpr*>::const_iterator cur = p.begin();
for (size_t idx = 0 ; idx < parms_.size() ; idx += 1) {
parms_[idx] = *cur;
++cur;
}
assert(cur == p.end());
path_.push_back(name_component_t(n));
}
PCallTask::~PCallTask()
{
}
const pform_name_t& PCallTask::path() const
{
return path_;
}
PCase::PCase(NetCase::TYPE t, PExpr*ex, svector<PCase::Item*>*l)
@@ -165,22 +122,6 @@ PCase::~PCase()
delete[]items_;
}
PCAssign::PCAssign(PExpr*l, PExpr*r)
: lval_(l), expr_(r)
{
}
PCAssign::~PCAssign()
{
delete lval_;
delete expr_;
}
PCondit::PCondit(PExpr*ex, Statement*i, Statement*e)
: expr_(ex), if_(i), else_(e)
{
}
PCondit::~PCondit()
{
delete expr_;
@@ -188,83 +129,6 @@ PCondit::~PCondit()
delete else_;
}
PDeassign::PDeassign(PExpr*l)
: lval_(l)
{
}
PDeassign::~PDeassign()
{
delete lval_;
}
PDelayStatement::PDelayStatement(PExpr*d, Statement*st)
: delay_(d), statement_(st)
{
}
PDelayStatement::~PDelayStatement()
{
}
PDisable::PDisable(const pform_name_t&sc)
: scope_(sc)
{
}
PDisable::~PDisable()
{
}
PEventStatement::PEventStatement(const svector<PEEvent*>&ee)
: expr_(ee), statement_(0)
{
assert(expr_.count() > 0);
}
PEventStatement::PEventStatement(PEEvent*ee)
: expr_(1), statement_(0)
{
expr_[0] = ee;
}
PEventStatement::PEventStatement(void)
: statement_(0)
{
}
PEventStatement::~PEventStatement()
{
// delete the events and the statement?
}
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)
{
}
PForce::~PForce()
{
delete lval_;
delete expr_;
}
PForever::PForever(Statement*s)
: statement_(s)
{
@@ -275,31 +139,11 @@ PForever::~PForever()
delete statement_;
}
PForStatement::PForStatement(PExpr*n1, PExpr*e1, PExpr*cond,
Statement*step, Statement*st)
: name1_(n1), expr1_(e1), cond_(cond), step_(step), statement_(st)
{
}
PForStatement::~PForStatement()
{
}
PProcess::~PProcess()
{
delete statement_;
}
PRelease::PRelease(PExpr*l)
: lval_(l)
{
}
PRelease::~PRelease()
{
delete lval_;
}
PRepeat::PRepeat(PExpr*e, Statement*s)
: expr_(e), statement_(s)
{
@@ -311,22 +155,85 @@ PRepeat::~PRepeat()
delete statement_;
}
PTrigger::PTrigger(const pform_name_t&e)
: event_(e)
{
}
PTrigger::~PTrigger()
{
}
PWhile::PWhile(PExpr*e1, Statement*st)
: cond_(e1), statement_(st)
{
}
PWhile::~PWhile()
{
delete cond_;
delete statement_;
}
/*
* $Log: Statement.cc,v $
* Revision 1.16 1999/09/29 18:36:02 steve
* Full case support
*
* Revision 1.15 1999/09/22 02:00:48 steve
* assignment with blocking event delay.
*
* Revision 1.14 1999/09/04 19:11:46 steve
* Add support for delayed non-blocking assignments.
*
* Revision 1.13 1999/09/02 01:59:27 steve
* Parse non-blocking assignment delays.
*
* Revision 1.12 1999/07/12 00:59:36 steve
* procedural blocking assignment delays.
*
* Revision 1.11 1999/06/24 04:24:18 steve
* Handle expression widths for EEE and NEE operators,
* add named blocks and scope handling,
* add registers declared in named blocks.
*
* Revision 1.10 1999/06/19 21:06:16 steve
* Elaborate and supprort to vvm the forever
* and repeat statements.
*
* Revision 1.9 1999/06/15 05:38:39 steve
* Support case expression lists.
*
* Revision 1.8 1999/06/13 23:51:16 steve
* l-value part select for procedural assignments.
*
* Revision 1.7 1999/06/06 20:45:38 steve
* Add parse and elaboration of non-blocking assignments,
* Replace list<PCase::Item*> with an svector version,
* Add integer support.
*
* Revision 1.6 1999/05/10 00:16:58 steve
* Parse and elaborate the concatenate operator
* in structural contexts, Replace vector<PExpr*>
* and list<PExpr*> with svector<PExpr*>, evaluate
* constant expressions with parameters, handle
* memories as lvalues.
*
* Parse task declarations, integer types.
*
* Revision 1.5 1999/02/03 04:20:11 steve
* Parse and elaborate the Verilog CASE statement.
*
* Revision 1.4 1999/01/25 05:45:56 steve
* Add the LineInfo class to carry the source file
* location of things. PGate, Statement and PProcess.
*
* elaborate handles module parameter mismatches,
* missing or incorrect lvalues for procedural
* assignment, and errors are propogated to the
* top of the elaboration call tree.
*
* Attach line numbers to processes, gates and
* assignment statements.
*
* Revision 1.3 1998/11/11 03:13:04 steve
* Handle while loops.
*
* Revision 1.2 1998/11/07 17:05:05 steve
* Handle procedural conditional, and some
* of the conditional expressions.
*
* Elaborate signals and identifiers differently,
* allowing the netlist to hold signal information.
*
* Revision 1.1 1998/11/03 23:28:55 steve
* Introduce verilog to CVS.
*
*/
+172 -213
View File
@@ -1,7 +1,7 @@
#ifndef __Statement_H
#define __Statement_H
/*
* Copyright (c) 1998-2008 Stephen Williams ([email protected])
* Copyright (c) 1998 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,53 +18,42 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: Statement.h,v 1.20 1999/09/29 18:36:02 steve Exp $"
#endif
# include <string>
# include <vector>
# include <list>
# include "ivl_target.h"
# include "svector.h"
# include "StringHeap.h"
# include "PDelays.h"
# include "PExpr.h"
# include "PScope.h"
# include "HName.h"
# include "LineInfo.h"
class PExpr;
class Statement;
class PEventStatement;
class Design;
class NetAssign_;
class NetCAssign;
class NetDeassign;
class NetForce;
class NetScope;
/*
* The PProcess is the root of a behavioral process. Each process gets
* one of these, which contains its type (initial, always, or final)
* and a pointer to the single statement that is the process. A module
* may have several concurrent processes.
* one of these, which contains its type (initial or always) and a
* pointer to the single statement that is the process. A module may
* have several concurrent processes.
*/
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;
virtual void dump(ostream&out, unsigned ind) const;
private:
ivl_process_type_t type_;
Type type_;
Statement*statement_;
};
@@ -80,11 +69,7 @@ class Statement : public LineInfo {
virtual ~Statement() =0;
virtual void dump(ostream&out, unsigned ind) 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;
map<perm_string,PExpr*> attributes;
virtual NetProc* elaborate(Design*des, const string&path) const;
};
/*
@@ -94,49 +79,41 @@ 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;
NetNet*elaborate_lval(Design*, const string&path,
unsigned&lsb, unsigned&msb,
NetExpr*&mux) const;
PExpr* delay_;
PDelays delay_;
PEventStatement*event_;
PExpr* count_;
private:
PExpr* lval_;
PExpr* rval_;
bool is_constant_;
};
class PAssign : public PAssign_ {
public:
// lval - assignment l-value
// ex - assignment r-value
// op - compressed assignment operator (i.e. '+', '-', ...)
// de - delayed assignment delay expression
explicit PAssign(PExpr*lval, PExpr*ex);
explicit PAssign(PExpr*lval, char op, 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;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual NetProc* elaborate(Design*des, const string&path) const;
private:
NetProc* elaborate_compressed_(Design*des, NetScope*scope) const;
char op_;
NetProc*assign_to_memory_(class NetMemory*, PExpr*,
Design*des, const string&path) const;
};
class PAssignNB : public PAssign_ {
@@ -144,15 +121,14 @@ 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;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual NetProc* elaborate(Design*des, const string&path) const;
private:
NetProc*assign_to_memory_(class NetMemory*, PExpr*,
Design*des, NetScope*scope) const;
Design*des, const string&path) const;
};
/*
@@ -162,65 +138,72 @@ class PAssignNB : public PAssign_ {
* statements before constructing this object, so it knows a priori
* what is contained.
*/
class PBlock : public PScope, public Statement {
class PBlock : public Statement {
public:
enum BL_TYPE { BL_SEQ, BL_PAR };
// If the block has a name, it is a scope and also has a parent.
explicit PBlock(perm_string n, LexicalScope*parent, BL_TYPE t);
// If it doesn't have a name, it's not a scope
explicit PBlock(const string&n, BL_TYPE t, const svector<Statement*>&st);
explicit PBlock(BL_TYPE t, const svector<Statement*>&st);
explicit PBlock(BL_TYPE t);
~PBlock();
BL_TYPE bl_type() const { return bl_type_; }
void set_statement(const std::vector<Statement*>&st);
//unsigned size() const { return list_.count(); }
//const Statement*stat(unsigned idx) const { return list_[idx]; }
virtual void dump(ostream&out, unsigned ind) 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;
virtual NetProc* elaborate(Design*des, const string&path) const;
private:
string name_;
const BL_TYPE bl_type_;
std::vector<Statement*>list_;
svector<Statement*>list_;
};
class PCallTask : public Statement {
public:
explicit PCallTask(const pform_name_t&n, const list<PExpr*>&parms);
explicit PCallTask(perm_string n, const list<PExpr*>&parms);
~PCallTask();
explicit PCallTask(const string&n, const svector<PExpr*>&parms);
const pform_name_t& path() const;
string name() const { return name_; }
unsigned nparms() const { return parms_.count(); }
PExpr*&parm(unsigned idx)
{ assert(idx < parms_.count());
return parms_[idx];
}
PExpr* parm(unsigned idx) const
{ assert(idx < parms_.count());
return parms_[idx];
}
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual NetProc* elaborate(Design*des, const string&path) const;
private:
NetProc* elaborate_sys(Design*des, NetScope*scope) const;
NetProc* elaborate_usr(Design*des, NetScope*scope) const;
NetProc* elaborate_sys(Design*des, const string&path) const;
NetProc* elaborate_usr(Design*des, const string&path) const;
pform_name_t path_;
vector<PExpr*> parms_;
const string name_;
svector<PExpr*> parms_;
};
class PCase : public Statement {
public:
struct Item {
list<PExpr*>expr;
svector<PExpr*>expr;
Statement*stat;
};
PCase(NetCase::TYPE, PExpr*ex, svector<Item*>*);
~PCase();
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;
virtual NetProc* elaborate(Design*des, const string&path) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
@@ -234,29 +217,14 @@ class PCase : public Statement {
PCase& operator= (const PCase&);
};
class PCAssign : public Statement {
public:
explicit PCAssign(PExpr*l, PExpr*r);
~PCAssign();
virtual NetCAssign* elaborate(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
PExpr*lval_;
PExpr*expr_;
};
class PCondit : public Statement {
public:
PCondit(PExpr*ex, Statement*i, Statement*e);
PCondit(PExpr*ex, Statement*i, Statement*e)
: expr_(ex), if_(i), else_(e) { }
~PCondit();
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;
virtual NetProc* elaborate(Design*des, const string&path) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
@@ -269,118 +237,50 @@ class PCondit : public Statement {
PCondit& operator= (const PCondit&);
};
class PDeassign : public Statement {
public:
explicit PDeassign(PExpr*l);
~PDeassign();
virtual NetDeassign* elaborate(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
PExpr*lval_;
};
class PDelayStatement : public Statement {
public:
PDelayStatement(PExpr*d, Statement*st);
~PDelayStatement();
PDelayStatement(PExpr*d, Statement*st)
: delay_(d), statement_(st) { }
virtual void dump(ostream&out, unsigned ind) 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;
virtual NetProc* elaborate(Design*des, const string&path) const;
private:
PExpr*delay_;
Statement*statement_;
};
/*
* This represents the parsing of a disable <scope> statement.
*/
class PDisable : public Statement {
public:
explicit PDisable(const pform_name_t&sc);
~PDisable();
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
private:
pform_name_t scope_;
};
/*
* The event statement represents the event delay in behavioral
* code. It comes from such things as:
*
* @name <statement>;
* @(expr) <statement>;
* @* <statement>;
*/
class PEventStatement : public Statement {
public:
explicit PEventStatement(const svector<PEEvent*>&ee);
explicit PEventStatement(PEEvent*ee);
// Make an @* statement.
explicit PEventStatement(void);
PEventStatement(const svector<PEEvent*>&ee)
: expr_(ee), statement_(0) { }
~PEventStatement();
PEventStatement(PEEvent*ee)
: expr_(1), statement_(0) { expr_[0] = ee; }
void set_statement(Statement*st);
void set_statement(Statement*st) { 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);
virtual NetProc* elaborate(Design*des, const string&path) const;
// 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;
NetProc* elaborate_wait(Design*des, NetScope*scope, NetProc*st) const;
NetProc* elaborate_st(Design*des, const string&path, NetProc*st) const;
private:
svector<PEEvent*>expr_;
Statement*statement_;
};
ostream& operator << (ostream&o, const PEventStatement&obj);
class PForce : public Statement {
public:
explicit PForce(PExpr*l, PExpr*r);
~PForce();
virtual NetForce* elaborate(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
PExpr*lval_;
PExpr*expr_;
};
class PForever : public Statement {
public:
explicit PForever(Statement*s);
~PForever();
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;
virtual NetProc* elaborate(Design*des, const string&path) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
@@ -391,12 +291,12 @@ class PForStatement : public Statement {
public:
PForStatement(PExpr*n1, PExpr*e1, PExpr*cond,
Statement*step, Statement*body);
~PForStatement();
PExpr*n2, PExpr*e2, Statement*st)
: name1_(n1), expr1_(e1), cond_(cond), name2_(n2), expr2_(e2),
statement_(st)
{ }
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;
virtual NetProc* elaborate(Design*des, const string&path) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
@@ -405,7 +305,8 @@ class PForStatement : public Statement {
PExpr*cond_;
Statement*step_;
PExpr* name2_;
PExpr* expr2_;
Statement*statement_;
};
@@ -414,7 +315,6 @@ class PNoop : public Statement {
public:
PNoop() { }
~PNoop() { }
};
class PRepeat : public Statement {
@@ -422,9 +322,7 @@ class PRepeat : public Statement {
explicit PRepeat(PExpr*expr, Statement*s);
~PRepeat();
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;
virtual NetProc* elaborate(Design*des, const string&path) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
@@ -432,45 +330,14 @@ class PRepeat : public Statement {
Statement*statement_;
};
class PRelease : public Statement {
public:
explicit PRelease(PExpr*l);
~PRelease();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
PExpr*lval_;
};
/*
* The PTrigger statement sends a trigger to a named event. Take the
* name here.
*/
class PTrigger : public Statement {
public:
explicit PTrigger(const pform_name_t&ev);
~PTrigger();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
pform_name_t event_;
};
class PWhile : public Statement {
public:
PWhile(PExpr*e1, Statement*st);
PWhile(PExpr*e1, Statement*st)
: cond_(e1), statement_(st) { }
~PWhile();
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;
virtual NetProc* elaborate(Design*des, const string&path) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
@@ -478,4 +345,96 @@ class PWhile : public Statement {
Statement*statement_;
};
/*
* $Log: Statement.h,v $
* Revision 1.20 1999/09/29 18:36:02 steve
* Full case support
*
* Revision 1.19 1999/09/22 02:00:48 steve
* assignment with blocking event delay.
*
* Revision 1.18 1999/09/15 01:55:06 steve
* Elaborate non-blocking assignment to memories.
*
* Revision 1.17 1999/09/04 19:11:46 steve
* Add support for delayed non-blocking assignments.
*
* Revision 1.16 1999/09/02 01:59:27 steve
* Parse non-blocking assignment delays.
*
* Revision 1.15 1999/07/12 00:59:36 steve
* procedural blocking assignment delays.
*
* Revision 1.14 1999/07/03 02:12:51 steve
* Elaborate user defined tasks.
*
* Revision 1.13 1999/06/24 04:24:18 steve
* Handle expression widths for EEE and NEE operators,
* add named blocks and scope handling,
* add registers declared in named blocks.
*
* Revision 1.12 1999/06/19 21:06:16 steve
* Elaborate and supprort to vvm the forever
* and repeat statements.
*
* Revision 1.11 1999/06/15 05:38:39 steve
* Support case expression lists.
*
* Revision 1.10 1999/06/13 23:51:16 steve
* l-value part select for procedural assignments.
*
* Revision 1.9 1999/06/06 20:45:38 steve
* Add parse and elaboration of non-blocking assignments,
* Replace list<PCase::Item*> with an svector version,
* Add integer support.
*
* Revision 1.8 1999/05/10 00:16:58 steve
* Parse and elaborate the concatenate operator
* in structural contexts, Replace vector<PExpr*>
* and list<PExpr*> with svector<PExpr*>, evaluate
* constant expressions with parameters, handle
* memories as lvalues.
*
* Parse task declarations, integer types.
*
* Revision 1.7 1999/04/29 02:16:26 steve
* Parse OR of event expressions.
*
* Revision 1.6 1999/02/03 04:20:11 steve
* Parse and elaborate the Verilog CASE statement.
*
* Revision 1.5 1999/01/25 05:45:56 steve
* Add the LineInfo class to carry the source file
* location of things. PGate, Statement and PProcess.
*
* elaborate handles module parameter mismatches,
* missing or incorrect lvalues for procedural
* assignment, and errors are propogated to the
* top of the elaboration call tree.
*
* Attach line numbers to processes, gates and
* assignment statements.
*
* Revision 1.4 1998/11/11 03:13:04 steve
* Handle while loops.
*
* Revision 1.3 1998/11/09 18:55:33 steve
* Add procedural while loops,
* Parse procedural for loops,
* Add procedural wait statements,
* Add constant nodes,
* Add XNOR logic gate,
* Make vvm output look a bit prettier.
*
* Revision 1.2 1998/11/07 17:05:05 steve
* Handle procedural conditional, and some
* of the conditional expressions.
*
* Elaborate signals and identifiers differently,
* allowing the netlist to hold signal information.
*
* Revision 1.1 1998/11/03 23:28:56 steve
* Introduce verilog to CVS.
*
*/
#endif
-88
View File
@@ -1,88 +0,0 @@
#ifndef PLI_TYPES
#define PLI_TYPES
/*
* Copyright (c) 2003 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
*/
# undef HAVE_INTTYPES_H
#ifdef HAVE_INTTYPES_H
/*
* If the host environment has the stdint.h header file,
* then use that to size our PLI types.
*/
#ifndef __STDC_FORMAT_MACROS
# define __STDC_FORMAT_MACROS
#endif
# include <inttypes.h>
typedef uint64_t PLI_UINT64;
typedef int64_t PLI_INT64;
typedef uint32_t PLI_UINT32;
typedef int32_t PLI_INT32;
typedef signed short PLI_INT16;
typedef unsigned short PLI_UINT16;
typedef char PLI_BYTE8;
typedef unsigned char PLI_UBYTE8;
# define PLI_UINT64_FMT PRIu64
#else
/*
* If we do not have the c99 stdint.h header file, then use
* configure detection to guess the pli types ourselves.
*/
# define SIZEOF_UNSIGNED_LONG_LONG 8
# define SIZEOF_UNSIGNED_LONG 8
# define SIZEOF_UNSIGNED 4
#if SIZEOF_UNSIGNED >= 8
typedef unsigned PLI_UINT64;
typedef int PLI_INT64;
# define PLI_UINT64_FMT "u"
#else
# if SIZEOF_UNSIGNED_LONG >= 8
typedef unsigned long PLI_UINT64;
typedef long PLI_INT64;
# define PLI_UINT64_FMT "lu"
# else
# if SIZEOF_UNSIGNED_LONG_LONG > SIZEOF_UNSIGNED_LONG
typedef unsigned long long PLI_UINT64;
typedef long long PLI_INT64;
# define PLI_UINT64_FMT "llu"
# else
typedef unsigned long PLI_UINT64;
typedef long PLI_INT64;
# define PLI_UINT64_FMT "lu"
# endif
# endif
#endif
typedef signed int PLI_INT32;
typedef unsigned int PLI_UINT32;
typedef signed short PLI_INT16;
typedef unsigned short PLI_UINT16;
typedef char PLI_BYTE8;
typedef unsigned char PLI_UBYTE8;
#endif
#endif
-273
View File
@@ -1,273 +0,0 @@
#ifndef __acc_user_H
#define __acc_user_H
/*
* 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
* 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
*/
/*
* This header file contains the definitions and declarations needed
* by an Icarus Verilog user using acc_ routines.
*
* NOTE: Icarus Verilog does not support acc_ routines. This is just a
* stub. The functions that are implemented here are actually
* implemented using VPI routines.
*/
#ifdef __cplusplus
# define EXTERN_C_START extern "C" {
# define EXTERN_C_END }
#else
# define EXTERN_C_START
# define EXTERN_C_END
# define bool int
#endif
EXTERN_C_START
# include "_pli_types.h"
/*
* This is a declaration of the "handle" type that is compatible with
* the vpiHandle from vpi_user.h. The libveriuser library implements
* the acc handle type as a vpiHandle, to prevent useless indirection.
*/
typedef struct __vpiHandle *handle;
/* OBJECT TYPES */
#define accModule 20
#define accScope 21
#define accNet 25
#define accReg 30
#define accIntegerParam 200
#define accRealParam 202
#define accStringParam 204
#define accParameter 220
#define accTopModule 224
#define accModuleInstance 226
#define accWire 260
#define accNamedEvent 280
#define accIntegerVar 281
#define accRealVar 282
#define accTimeVar 283
#define accIntVar accIntegerVar
#define accScalar 300
#define accVector 302
#define accUnknown 412
#define accConstant 600
/* type VALUES FOR t_setval_delay STRUCTURE */
#define accNoDelay 0
#define accInertialDelay 1
#define accTransportDelay 2
#define accPureTransportDelay 3
#define accForceFlag 4
#define accReleaseFlag 5
/* type VALUES FOR t_setval_value STRUCTURE */
#define accBinStrVal 1
#define accOctStrVal 2
#define accDecStrVal 3
#define accHexStrVal 4
#define accScalarVal 5
#define accIntVal 6
#define accRealVal 7
#define accStringVal 8
#define accVectorVal 9
/* Scalar values */
#define acc0 0
#define acc1 1
#define accX 2
#define accZ 3
/* type VALUES FOR t_acc_time STRUCTURE */
#define accTime 1
#define accSimTime 2
#define accRealTime 3
/* reason codes */
#define logic_value_change 1
#define strength_value_change 2
#define real_value_change 3
#define vector_value_change 4
#define event_value_change 5
#define integer_value_change 6
#define time_value_change 7
#define sregister_value_change 8
#define vregister_value_change 9
#define realtime_value_change 10
/* VCL strength values */
#define vclSupply 7
#define vclStrong 6
#define vclPull 5
#define vclLarge 4
#define vclWeak 3
#define vclMedium 2
#define vclSmall 1
#define vclHighZ 0
/* Constants used by acc_vcl_add */
#define vcl_verilog_logic 2
#define VCL_VERILOG_LOGIC vcl_verilog_logic
#define vcl_verilog_strength 3
#define VCL_VERILOG_STRENGTH vcl_verilog_strength
typedef struct t_acc_time {
int type;
int low, high;
double real;
} s_acc_time, *p_acc_time;
typedef struct t_setval_delay {
s_acc_time time;
int model;
} s_setval_delay, *p_setval_delay;
typedef struct t_acc_vecval {
int aval;
int bval;
} s_acc_vecval, *p_acc_vecval;
typedef struct t_setval_value {
int format;
union {
char*str;
int scalar;
int integer;
double real;
p_acc_vecval vector;
} value;
} s_setval_value, *p_setval_value, s_acc_value, *p_acc_value;
typedef struct t_strengths {
PLI_UBYTE8 logic_value;
PLI_UBYTE8 strength1;
PLI_UBYTE8 strength2;
} s_strengths, *p_strengths;
typedef struct t_vc_record {
PLI_INT32 vc_reason;
PLI_INT32 vc_hightime;
PLI_INT32 vc_lowtime;
void* user_data;
union {
PLI_UBYTE8 logic_value;
double real_value;
handle vector_handle;
s_strengths strengths_s;
} out_value;
} s_vc_record, *p_vc_record;
typedef struct t_location {
PLI_INT32 line_no;
const char*filename;
} s_location, *p_location;
extern int acc_error_flag;
extern int acc_initialize(void);
extern void acc_close(void);
/*
* This is the acc_configure command, and the config_param
* codes that are accepted.
*/
extern int acc_configure(PLI_INT32 config_param, const char*value);
#define accEnableArgs 6
#define accDevelopmentVersion 11
extern int acc_fetch_argc(void);
extern char**acc_fetch_argv(void);
extern PLI_INT32 acc_fetch_direction(handle obj);
/* XXXX FIXME: Values returned by acc_fetch_direction */
# define accInout 2
extern char* acc_fetch_fullname(handle obj);
extern int acc_fetch_location(p_location loc, handle obj);
extern char* acc_fetch_name(handle obj);
extern char* acc_fetch_defname(handle obj);
extern double acc_fetch_paramval(handle obj);
extern double acc_fetch_tfarg(PLI_INT32);
extern double acc_fetch_itfarg(PLI_INT32, handle);
extern PLI_INT32 acc_fetch_tfarg_int(PLI_INT32);
extern PLI_INT32 acc_fetch_itfarg_int(PLI_INT32, handle);
extern char* acc_fetch_tfarg_str(PLI_INT32);
extern char* acc_fetch_itfarg_str(PLI_INT32, handle);
typedef struct t_timescale_info {
PLI_INT16 unit;
PLI_INT16 precision;
} s_timescale_info, *p_timescale_info;
extern void acc_fetch_timescale_info(handle obj, p_timescale_info info);
extern PLI_INT32 acc_fetch_size(handle obj);
extern PLI_INT32 acc_fetch_type(handle obj);
extern PLI_INT32 acc_fetch_fulltype(handle obj);
extern PLI_INT32 acc_fetch_range(handle object, int *msb, int *lsb);
extern const char* acc_fetch_type_str(PLI_INT32 type);
extern char* acc_fetch_value(handle obj, const char*fmt, s_acc_value*value);
extern handle acc_handle_by_name(const char*name, handle scope);
extern handle acc_handle_hiconn(handle port_ref_handle);
extern handle acc_handle_object(const char*name);
extern handle acc_handle_parent(handle obj);
extern handle acc_handle_scope(handle obj);
extern handle acc_handle_simulated_net(handle net);
extern handle acc_handle_tfarg(int n);
extern handle acc_handle_tfinst(void);
extern PLI_INT32 acc_compare_handles(handle, handle);
extern handle acc_next(PLI_INT32 *, handle, handle);
extern handle acc_next_bit(handle ref, handle bit);
extern handle acc_next_port(handle ref, handle bit);
extern handle acc_next_scope(handle, handle);
extern handle acc_next_topmod(handle prev_topmod);
extern int acc_object_in_typelist(handle object, PLI_INT32*typelist);
extern int acc_object_of_type(handle object, PLI_INT32 type);
extern char*acc_product_version(void);
extern char*acc_set_scope(handle ref, ...);
extern int acc_set_value(handle obj, p_setval_value value,
p_setval_delay delay);
extern void acc_vcl_add(handle obj, PLI_INT32(*consumer)(p_vc_record),
void*data, PLI_INT32 vcl_flag);
extern void acc_vcl_delete(handle obj, PLI_INT32(*consumer)(p_vc_record),
void*data, PLI_INT32 vcl_flag);
extern char* acc_version(void);
EXTERN_C_END
#endif
Vendored
-256
View File
@@ -1,256 +0,0 @@
# 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],[AC_HELP_STRING([--enable-suffix],
[Use/set the installation command suffix])],
[true],[enable_suffix=no])
if test X$enable_suffix = Xyes; then
install_suffix='-0.10'
elif test X$enable_suffix = Xno; then
install_suffix=''
else
install_suffix="$enable_suffix"
fi
AC_SUBST(install_suffix)
])# AX_ENABLE_SUFFIX
# _AX_C_UNDERSCORES_MATCH_IFELSE(PATTERN, ACTION-IF-MATCH, ACTION-IF-NOMATCH)
# ------------------------------
# Sub-macro for AX_C_UNDERSCORES_LEADING and AX_C_UNDERSCORES_TRAILING.
# Unwarranted assumptions:
# - the object file produced by AC_COMPILE_IFELSE is called "conftest.$ac_objext"
# - the nm(1) utility is available, and its name is "nm".
AC_DEFUN([_AX_C_UNDERSCORES_MATCH_IF],
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([void underscore(void){}])],
[AS_IF([nm conftest.$ac_objext|grep $1 >/dev/null 2>/dev/null],[$2],[$3])],
[AC_MSG_ERROR([underscore test crashed])]
)])
# AX_C_UNDERSCORES_LEADING
# ---------------------------------
# Check if symbol names in object files produced by C compiler have
# leading underscores. Define NEED_LU if so.
AC_DEFUN([AX_C_UNDERSCORES_LEADING],
[AC_CACHE_CHECK([for leading underscores], ax_cv_c_underscores_leading,
[_AX_C_UNDERSCORES_MATCH_IF([_underscore],
[AS_VAR_SET(ax_cv_c_underscores_leading, yes)],
[AS_VAR_SET(ax_cv_c_underscores_leading, no)])])
if test $ax_cv_c_underscores_leading = yes -a "$CYGWIN" != "yes" -a "$MINGW32" != "yes"; then
AC_DEFINE([NEED_LU], [1], [Symbol names in object files produced by C compiler have leading underscores.])
fi
])# AX_C_UNDERSCORES_LEADING
# AX_C_UNDERSCORES_TRAILING
# ---------------------------------
# Check if symbol names in object files produced by C compiler have
# trailing underscores. Define NEED_TU if so.
AC_DEFUN([AX_C_UNDERSCORES_TRAILING],
[AC_CACHE_CHECK([for trailing underscores], ax_cv_c_underscores_trailing,
[_AX_C_UNDERSCORES_MATCH_IF([underscore_],
[AS_VAR_SET(ax_cv_c_underscores_trailing, yes)],
[AS_VAR_SET(ax_cv_c_underscores_trailing, no)])])
if test $ax_cv_c_underscores_trailing = yes; then
AC_DEFINE([NEED_TU], [1], [Symbol names in object files produced by C compiler have trailing underscores.])
fi
])# AX_C_UNDERSCORES_TRAILING
# AX_WIN32
# --------
# Combined check for several flavors of Microsoft Windows so
# their "issues" can be dealt with
AC_DEFUN([AX_WIN32],
[AC_MSG_CHECKING([for Microsoft Windows])
AC_REQUIRE([AC_CANONICAL_HOST]) []dnl
case $host_os in
*cygwin*) MINGW32=no; WIN32=yes;;
*mingw*) MINGW32=yes; WIN32=yes;;
*) MINGW32=no; WIN32=no;;
esac
AC_SUBST(MINGW32)
AC_SUBST(WIN32)
AC_MSG_RESULT($WIN32)
if test $WIN32 = yes; then
AC_MSG_CHECKING([for MinGW])
AC_MSG_RESULT($MINGW32)
fi
])# AX_WIN32
# AX_LD_EXTRALIBS
# ---------------
# mingw needs to link with libiberty.a, but cygwin alone can't tolerate it
AC_DEFUN([AX_LD_EXTRALIBS],
[AC_MSG_CHECKING([for extra libs needed])
EXTRALIBS=
case "${host}" in
*-*-cygwin* )
if test "$MINGW32" = "yes"; then
EXTRALIBS="-liberty"
fi
;;
esac
AC_SUBST(EXTRALIBS)
AC_MSG_RESULT($EXTRALIBS)
])# AX_LD_EXTRALIBS
# AX_LD_SHAREDLIB_OPTS
# --------------------
# linker options when building a shared library
AC_DEFUN([AX_LD_SHAREDLIB_OPTS],
[AC_MSG_CHECKING([for shared library link flag])
shared=-shared
case "${host}" in
*-*-cygwin*)
shared="-shared -Wl,--enable-auto-image-base"
;;
*-*-mingw*)
shared="-shared -Wl,--enable-auto-image-base"
;;
*-*-hpux*)
shared="-b"
;;
*-*-darwin1.[0123])
shared="-bundle -undefined suppress"
;;
*-*-darwin*)
shared="-bundle -undefined suppress -flat_namespace"
;;
*-*-solaris*)
if test ${using_sunpro_c} = 1
then
shared="-G"
fi
;;
esac
AC_SUBST(shared)
AC_MSG_RESULT($shared)
])# AX_LD_SHAREDLIB_OPTS
# AX_C_PICFLAG
# ------------
# The -fPIC flag is used to tell the compiler to make position
# independent code. It is needed when making shared objects.
AC_DEFUN([AX_C_PICFLAG],
[AC_MSG_CHECKING([for flag to make position independent code])
PICFLAG=-fPIC
case "${host}" in
*-*-cygwin*)
PICFLAG=
;;
*-*-mingw*)
PICFLAG=
;;
*-*-hpux*)
PICFLAG=+z
;;
*-*-solaris*)
if test ${using_sunpro_c} = 1
then
PICFLAG=-G
fi
;;
esac
AC_SUBST(PICFLAG)
AC_MSG_RESULT($PICFLAG)
])# AX_C_PICFLAG
# AX_LD_RDYNAMIC
# --------------
# The -rdynamic flag is used by iverilog when compiling the target,
# to know how to export symbols of the main program to loadable modules
# that are brought in by -ldl
AC_DEFUN([AX_LD_RDYNAMIC],
[AC_MSG_CHECKING([for -rdynamic compiler flag])
rdynamic=-rdynamic
case "${host}" in
*-*-netbsd*)
rdynamic="-Wl,--export-dynamic"
;;
*-*-openbsd*)
rdynamic="-Wl,--export-dynamic"
;;
*-*-solaris*)
rdynamic=""
;;
*-*-cygwin*)
rdynamic=""
;;
*-*-mingw*)
rdynamic=""
;;
*-*-hpux*)
rdynamic="-E"
;;
*-*-darwin*)
rdynamic="-Wl,-all_load"
strip_dynamic="-SX"
;;
esac
AC_SUBST(rdynamic)
AC_MSG_RESULT($rdynamic)
AC_SUBST(strip_dynamic)
# since we didn't tell them we're "checking", no good place to tell the answer
# AC_MSG_RESULT($strip_dynamic)
])# AX_LD_RDYNAMIC
# AX_CPP_PRECOMP
# --------------
AC_DEFUN([AX_CPP_PRECOMP],
[# Darwin requires -no-cpp-precomp
case "${host}" in
*-*-darwin*)
CPPFLAGS="-no-cpp-precomp $CPPFLAGS"
CFLAGS="-no-cpp-precomp $CFLAGS"
;;
esac
])# AX_CPP_PRECOMP
# AX_C99_STRTOD
# -------------
AC_DEFUN([AX_C99_STRTOD],
[# On MinGW we need to jump through hoops to get a C99 compliant strtod().
case "${host}" in
*-*-mingw*)
LDFLAGS+=" -Wl,--undefined=___strtod,--wrap,strtod,--defsym,___wrap_strtod=___strtod"
;;
esac
])# AX_C99_STRTOD
# When config.status generates a header, we must update the stamp-h file.
# This file resides in the same directory as the config header
# that is generated. The stamp file name are based on the header name.
# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
# loop where config.status creates the headers, so we can generate
# our stamp files there.
AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
[
_config_header=$1
_stamp_name=stamp-`expr //$_config_header : '.*/\([[^./]]*\)\.[[^./]]*$'`-h
echo "timestamp for $_config_header" > `AS_DIRNAME(["$_config_header"])`/[]$_stamp_name
]) #_AC_AM_CONFIG_HEADER_HOOK
-91
View File
@@ -1,91 +0,0 @@
/*
* Copyright (c) 2002-2010 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* 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 "functor.h"
# include "netlist.h"
# include <cassert>
bool NetAssign::is_asynchronous()
{
return true;
}
bool NetCondit::is_asynchronous()
{
return false;
}
/*
* NetEvWait statements come from statements of the form @(...) in the
* Verilog source. These event waits are considered asynchronous if
* all of the events in the list are ANYEDGE, and all the inputs to
* the statement are included in the sensitivity list. If any of the
* events are posedge or negedge, the statement is synchronous
* (i.e. an edge-triggered flip-flop) and if any of the inputs are
* unaccounted for in the sensitivity list then the statement is a
* latch.
*/
bool NetEvWait::is_asynchronous()
{
/* The "sense" set contains the set of Nexa that are in the
sensitivity list. We also require that the events are all
level sensitive, but the nex_async_ method takes care of
that test. */
NexusSet*sense = new NexusSet;
for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) {
NexusSet*tmp = event(idx)->nex_async_();
if (tmp == 0) {
delete sense;
return false;
}
sense->add(*tmp);
delete tmp;
}
NexusSet*inputs = statement_->nex_input();
if (! sense->contains(*inputs)) {
delete sense;
delete inputs;
return false;
}
delete sense;
delete inputs;
/* If it passes all the other tests, then this statement is
asynchronous. */
return true;
}
bool NetProc::is_asynchronous()
{
return false;
}
bool NetProcTop::is_asynchronous() const
{
if (type_ == IVL_PR_INITIAL)
return false;
return statement_->is_asynchronous();
}
-85
View File
@@ -1,85 +0,0 @@
ATTRIBUTE NAMING CONVENTIONS
Attributes that are specific to Icarus Verilog, and are intended to be
of use to programmers, start with the prefix "ivl_".
Attributes with the "_ivl_" prefix are set aside for internal
use. They may be generated internally by the compiler. They need not
be documented here.
ATTRIBUTES TO CONTROL SYNTHESIS
The following is a summary of Verilog attributes that Icarus Verilog
understands within Verilog source files to control synthesis
behavior. This section documents generic synthesis attributes. For
target specific attributes, see target specific documentation.
These attributes only effect the behavior of the synthesizer. For
example, the ivl_combinational will not generate an error message
if the Verilog is being compiled for simulation. (It may generate a
warning.)
* Attributes for "always" and "initial" statements
(* ivl_combinational *)
This attribute tells the compiler that the statement models
combinational logic. If the compiler finds that it cannot make
combinational logic out of a marked always statement, it will
report an error.
This attribute can be used to prevent accidentally inferring
latches or flip-flops where the user intended combinational
logic.
(* ivl_synthesis_on *)
This attribute tells the compiler that the marked always statement
is synthesizable. The compiler will attempt to synthesize the
code in the marked "always" statement. If it cannot in any way
synthesize it, then it will report an error.
(* ivl_synthesis_off *)
If this value is attached to an "always" statement, then the
compiler will *not* synthesize the "always" statement. This can be
used, for example, to mark embedded test bench code.
* Attributes for modules
(* ivl_synthesis_cell *)
If this value is attached to a module during synthesis, that
module will be considered a target architecture primitive, and
its interior will not be synthesized further. The module can
therefore hold a model for simulation purposes.
* Attributes for signals (wire/reg/integer/tri/etc.)
(* PAD = "<pad assignment list>" *)
If this attribute is attached to a signal that happens to be a
root module port, then targets that support it will use the string
value as a list of pin assignments for the port/signal. The format
is a comma separated list of location tokens, with the format of
the token itself defined by the back-end tools in use.
* Other Attributes
[ none defined yet ]
MISC
(* _ivl_schedule_push *)
If this attribute is attached to a thread object (always or
initial statement) then the vvp code generator will generate code
that causes the scheduler to push this thread at compile time. The
compiler may internally add this attribute to always statements if
it detects that it is combinational. This helps resolve time-0
races.
-13
View File
@@ -1,13 +0,0 @@
#!/bin/sh
#
# This shell script exists to run autoconf on source distributions
# that are pulled from CVS. The configure scripts are not included
# in CVS, and there are several configure.in files, so it is easiest
# to just run this script to autoconf wherever needed.
#
echo "Autoconf in root..."
autoconf -f
echo "Precompiling lexor_keyword.gperf"
gperf -o -i 7 -C -k 1-4,6,9,\$ -L ANSI-C -H keyword_hash -N check_identifier -t ./lexor_keyword.gperf > lexor_keyword.cc
-96
View File
@@ -1,96 +0,0 @@
#
# This source code is free software; you can redistribute it
# and/or modify it in source code form under the terms of the GNU
# Library General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc.,
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
SHELL = /bin/sh
suffix = @install_suffix@
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
VPATH = $(srcdir)
bindir = @bindir@
libdir = @libdir@
includedir = $(prefix)/include
vpidir = @libdir@/ivl$(suffix)
CC = @CC@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
ifeq (@srcdir@,.)
INCLUDE_PATH = -I. -I..
else
INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/..
endif
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
LDFLAGS = @LDFLAGS@
O = cadpli.o
all: dep cadpli.vpl $(ALL32)
check: all
clean:
rm -rf *.o dep cadpli.vpl
distclean: clean
rm -f Makefile config.log
cppcheck: $(O:.o=.c)
cppcheck --enable=all -f $(INCLUDE_PATH) $^
Makefile: $(srcdir)/Makefile.in ../config.status
cd ..; ./config.status --file=cadpli/$@
dep:
mkdir dep
%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) @DEPENDENCY_FLAG@ -c $<
mv $*.d dep
SYSTEM_VPI_LDFLAGS = -L../vvp -lvpi
ifeq (@MINGW32@,yes)
SYSTEM_VPI_LDFLAGS += @EXTRALIBS@
endif
cadpli.vpl: $O ../vvp/libvpi.a ../libveriuser/libveriuser.o
$(CC) @shared@ $(LDFLAGS) -o $@ $O ../libveriuser/libveriuser.o $(SYSTEM_VPI_LDFLAGS)
install: all installdirs $(vpidir)/cadpli.vpl
$(vpidir)/cadpli.vpl: ./cadpli.vpl
$(INSTALL_PROGRAM) ./cadpli.vpl "$(DESTDIR)$(vpidir)/cadpli.vpl"
installdirs: $(srcdir)/../mkinstalldirs
$(srcdir)/../mkinstalldirs "$(DESTDIR)$(vpidir)"
uninstall: $(UNINSTALL32)
rm -f "$(DESTDIR)$(vpidir)/cadpli.vpl"
uninstall32:
-include $(patsubst %.o, dep/%.d, $O)
-85
View File
@@ -1,85 +0,0 @@
/*
* Copyright (c) 2003-2010 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* 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 <vpi_user.h>
# include <veriuser.h>
# include <stdlib.h>
# include <string.h>
# include <assert.h>
# include "config.h"
# include "ivl_dlfcn.h"
# include "ivl_alloc.h"
typedef void* (*funcvp)(void);
static void thunker_register(void)
{
struct t_vpi_vlog_info vlog_info;
void*mod;
void*boot;
struct t_tfcell*tf;
int idx;
vpi_get_vlog_info(&vlog_info);
for (idx = 0 ; idx < vlog_info.argc ; idx += 1) {
char*module, *cp, *bp;
if (strncmp("-cadpli=", vlog_info.argv[idx], 8) != 0)
continue;
cp = vlog_info.argv[idx] + 8;
assert(cp);
bp = strchr(cp, ':');
assert(bp);
module = malloc(bp-cp+1);
strncpy(module, cp, bp-cp);
module[bp-cp] = 0;
mod = ivl_dlopen(module);
if (mod == 0) {
vpi_printf("%s link: %s\n", vlog_info.argv[idx], dlerror());
free(module);
continue;
}
bp += 1;
boot = ivl_dlsym(mod, bp);
if (boot == 0) {
vpi_printf("%s: Symbol %s not found.\n",
vlog_info.argv[idx], bp);
free(module);
continue;
}
free(module);
assert(boot);
tf = (*((funcvp)boot))();
assert(tf);
veriusertfs_register_table(tf);
}
}
void (*vlog_startup_routines[])() = {
thunker_register,
0
};
-35
View File
@@ -1,35 +0,0 @@
CADENCE PLI1 MODULES
Copyright 2003 Stephen Williams
With the cadpli module, Icarus Verilog is able to load PLI1
applications that were compiled and linked to be dynamic loaded by
Verilog-XL or NC-Verilog. This allows Icarus Verilog users to run
third-party modules that were compiled to interface with XL or
NC. Obviously, this only works on the operating system that the PLI
application was compiled to run on. For example, a Linux module can
only be loaded and run under Linux.
Icarus Verilog uses an interface module, the "cadpli" module, to
connect the worlds. This module is installed with Icarus Verilog, and
is invoked by the usual -m flag to iverilog or vvp. This module in
turn scans the extended arguments, looking for +cadpli= arguments. The
latter specify the share object and bootstrap function for running the
module. For example, to run the module product.so, that has the
bootstrap function "my_boot":
vvp -mcadpli a.out -cadpli=./product.so:my_boot
The "-mcadpli" argument causes vvp to load the cadpli.vpl library
module. This activates the -cadpli= argument interpreter. The
-cadpli=<module>:<boot_func> argument, then, causes vvp, through the
cadpli module, to load the loadable PLI application, invoke the
my_boot function to get a veriusertfs table, and scan that table to
register the system tasks and functions exported by that object. The
format of the -cadpli= extended argument is essentially the same as
the +loadpli1= argument to Verilog-XL.
The integration from this point is seamless. The PLI application
hardly knows that it is being invoked by Icarus Verilog instead of
Verilog-XL, so operates as it would otherwise.
-94
View File
@@ -1,94 +0,0 @@
#ifndef __ivl_dlfcn_H
#define __ivl_dlfcn_H
/*
* Copyright (c) 2001 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
*/
#if defined(__MINGW32__)
# include <windows.h>
# include <stdio.h>
typedef void * ivl_dll_t;
#elif defined(HAVE_DLFCN_H)
# include <dlfcn.h>
typedef void* ivl_dll_t;
#elif defined(HAVE_DL_H)
# include <dl.h>
typedef shl_t ivl_dll_t;
#endif
#if defined(__MINGW32__)
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)
{ return (void *)GetProcAddress((HINSTANCE)dll,nm);}
static __inline__ void ivl_dlclose(ivl_dll_t dll)
{ (void)FreeLibrary((HINSTANCE)dll);}
static __inline__ const char *dlerror(void)
{
static char msg[256];
unsigned long err = GetLastError();
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &msg,
sizeof(msg) - 1,
NULL
);
return msg;
}
#elif defined(HAVE_DLFCN_H)
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)
{
void*sym = dlsym(dll, nm);
/* Not found? try without the leading _ */
if (sym == 0 && nm[0] == '_')
sym = dlsym(dll, nm+1);
return sym;
}
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)
{ return shl_load(name, BIND_IMMEDIATE, 0); }
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)
{ shl_unload(dll); }
static __inline__ const char*dlerror(void)
{ return strerror( errno ); }
#endif
#endif
-4
View File
@@ -1,4 +0,0 @@
functor:cprop
functor:nodangle
-t:dll
flag:DLL=tgt-vvp/vvp.tgt
+12 -224
View File
@@ -1,7 +1,7 @@
#ifndef __compiler_H
#define __compiler_H
/*
* Copyright (c) 1999-2011 Stephen Williams ([email protected])
* Copyright (c) 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
@@ -18,237 +18,25 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include <list>
# include <map>
# include "netlist.h"
# include "StringHeap.h"
#if !defined(WINNT)
#ident "$Id: compiler.h,v 1.1 1999/06/06 20:42:48 steve Exp $"
#endif
/*
* This defines constants and defaults for the compiler in general.
*/
/*
* The integer_width is the width of integer variables. This is also
* the minimum width of unsized integers when they are found in
* self-determined contexts.
*/
extern unsigned integer_width;
/*
* This is the maximum number of recursive module loops allowed within
* a generate block.
*/
extern unsigned recursive_mod_limit;
/* The TIME_WIDTH is the width of time variables. */
#ifndef TIME_WIDTH
# define TIME_WIDTH 64
/* The INTEGER_WIDTH is the default width of integer variables, and
the presumed width of unsigned literal numbers. */
#ifndef INTEGER_WIDTH
# define INTEGER_WIDTH 32
#endif
/*
* When doing dynamic linking, we need a uniform way to identify the
* symbol. Some compilers put leading _, some trailing _. The
* configure script figures out which is the local convention and
* defines NEED_LU and NEED_TU as required.
* $Log: compiler.h,v $
* Revision 1.1 1999/06/06 20:42:48 steve
* Make compiler width a compile time constant.
*
*/
#ifdef NEED_LU
#define LU "_"
#else
#define LU ""
#endif
#ifdef NEED_TU
#define TU "_"
#else
#define TU ""
#endif
/*
* These are flags to enable various sorts of warnings. By default all
* the warnings are off, the -W<list> parameter arranges for each to be
* enabled.
*/
/* Implicit definitions of wires. */
extern bool warn_implicit;
/* inherit timescales across files. */
extern bool warn_timescale;
/* Warn about legal but questionable module port bindings. */
extern bool warn_portbinding;
/* Warn about constant out of bound selects. */
extern bool warn_ob_select;
/* Warn about structures that may have infinite loops. */
extern bool warn_inf_loop;
/* Warn about always @* statements where a part or word select causes
sensitivity to an entire vector or array. */
extern bool warn_sens_entire_vec;
extern bool warn_sens_entire_arr;
/* Warn about level-appropriate anochronisms. */
extern bool warn_anachronisms;
/* This is true if verbose output is requested. */
extern bool verbose_flag;
extern bool debug_scopes;
extern bool debug_eval_tree;
extern bool debug_elaborate;
extern bool debug_synth2;
extern bool debug_optimizer;
/* Possibly temporary flag to control virtualization of pin arrays */
extern bool disable_virtual_pins;
/* Limit to size of devirtualized arrays */
extern unsigned long array_size_limit;
/* Path to a directory useful for finding subcomponents. */
extern const char*basedir;
/* This is an ordered list of library suffixes to search. */
extern list<const char*>library_suff;
extern int build_library_index(const char*path, bool key_case_sensitive);
/* This is the generation of Verilog that the compiler is asked to
support. Then there are also more detailed controls for more
specific language features. */
enum generation_t {
GN_VER1995 = 1,
GN_VER2001_NOCONFIG = 2,
GN_VER2001 = 3,
GN_VER2005 = 4,
GN_VER2005_SV = 5,
GN_VER2009 = 6,
GN_DEFAULT = 4
};
extern generation_t generation_flag;
/* If this flag is true, enable extended types support. */
extern bool gn_cadence_types_flag;
/* If this flag is true, enable miscellaneous extensions. */
extern bool gn_icarus_misc_flag;
/* If this flag is true, then elaborate specify blocks. If this flag
is false, then skip elaboration of specify behavior. */
extern bool gn_specify_blocks_flag;
/* If this flag is true, then support/elaborate Verilog-AMS. */
extern bool gn_verilog_ams_flag;
/* If this flag is false a warning is printed when the port declaration
is scalar and the net/register definition is vectored. */
extern bool gn_io_range_error_flag;
/* If this flag is true, then force re-evaluation of user functions
in a continuous assignment when any part of the expression is
re-evaluated. */
extern bool gn_strict_ca_eval_flag;
/* If this flag is true, then force strict conformance to the IEEE
standard expression width rules. */
extern bool gn_strict_expr_width_flag;
/* If variables can be converted to uwires by a continuous assignment
(assuming no procedural assign, then return true. This will be true
for SystemVerilog */
static inline bool gn_var_can_be_uwire(void)
{
if (generation_flag == GN_VER2005_SV ||
generation_flag == GN_VER2009)
return true;
return false;
}
static inline bool gn_system_verilog(void)
{
if (generation_flag == GN_VER2005_SV ||
generation_flag == GN_VER2009)
return true;
return false;
}
/* The bits of these GN_KEYWORDS_* constants define non-intersecting
sets of keywords. The compiler enables groups of keywords by setting
lexor_keyword_mask with the OR of the bits for the keywords to be
enabled. */
enum { GN_KEYWORDS_1364_1995 = 0x0001,
GN_KEYWORDS_1364_2001 = 0x0002,
GN_KEYWORDS_1364_2001_CONFIG = 0x0004,
GN_KEYWORDS_1364_2005 = 0x0008,
GN_KEYWORDS_VAMS_2_3 = 0x0010,
GN_KEYWORDS_1800_2005 = 0x0020,
GN_KEYWORDS_1800_2009 = 0x0040,
GN_KEYWORDS_ICARUS = 0x8000
};
extern int lexor_keyword_mask;
/* This is the string to use to invoke the preprocessor. */
extern char*ivlpp_string;
extern map<perm_string,unsigned> missing_modules;
/* Files that are library files are in this map. The lexor compares
file names as it processes `line directives, and if the file name
matches an entry in this table, it will turn on the
library_active_flag so that modules know that they are in a
library. */
extern map<perm_string,bool> library_file_map;
/*
* the lex_strings are perm_strings made up of tokens from the source
* file. Identifiers are so likely to be used many times that it makes
* much sense to use a StringHeapLex to hold them.
*/
extern StringHeapLex lex_strings;
/*
* The ivl_target.h API in a variety of places keeps strings of
* bits. Manage these as perm_string in a StringHeap.
*/
extern StringHeapLex bits_strings;
/*
* The filename_strings are perm_strings for file names. They are put
* into their own StringHeapLex because these paths are used a *lot*
* and this makes them more sure to hash together.
*/
extern StringHeapLex filename_strings;
/*
* system task/function listings.
*/
/*
* This table describes all the return values of various system
* functions. This table is used to elaborate expressions that are
* system function calls.
*/
struct sfunc_return_type {
const char* name;
ivl_variable_type_t type;
unsigned wid;
int signed_flag;
};
extern const struct sfunc_return_type* lookup_sys_func(const char*name);
extern int load_sys_func_table(const char*path);
extern void cleanup_sys_func_table();
/*
* In system Verilog it is allowed with a warning to call a function
* as a task. You can even cast the return value away and have no
* warning message.
*/
extern ivl_sfunc_as_task_t def_sfunc_as_task;
#endif
+460 -1109
View File
File diff suppressed because it is too large Load Diff
-63
View File
@@ -1,63 +0,0 @@
#ifndef __config_H /* -*- c++ -*- */
#define __config_H
/*
* Copyright (c) 2001-2010 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* 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
*/
#if defined(__cplusplus)
# if !defined(__GNUC__)
using namespace std;
# elif (__GNUC__ == 3)
using namespace std;
# endif
#endif
# undef NEED_LU
# undef NEED_TU
# undef WLU
# undef WTU
# undef HAVE_TIMES
# undef HAVE_IOSFWD
# undef HAVE_GETOPT_H
# undef HAVE_INTTYPES_H
# undef HAVE_LIBIBERTY_H
# undef HAVE_DLFCN_H
# undef HAVE_DL_H
# undef HAVE_FCHMOD
# undef HAVE_LIBREADLINE
# undef HAVE_LIBZ
# undef HAVE_LIBBZ2
# undef HAVE_LROUND
# undef HAVE_SYS_WAIT_H
# undef WORDS_BIGENDIAN
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
/* These two are needed by the lxt and lxt2 files (copied from GTKWave). */
# undef HAVE_ALLOCA_H
# undef HAVE_FSEEKO
/*
* Define this if you want to compile vvp with memory freeing and
* special valgrind hooks for the memory pools.
*/
# undef CHECK_WITH_VALGRIND
#endif /* __config_H */
Vendored
+216 -724
View File
File diff suppressed because it is too large Load Diff
+2 -298
View File
@@ -1,307 +1,11 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT(netlist.h)
AC_CONFIG_HEADER(config.h)
AC_CONFIG_HEADER(_pli_types.h)
AC_CONFIG_HEADER(vhdlpp/vhdlpp_config.h)
AC_CONFIG_HEADER(vvp/config.h)
AC_CONFIG_HEADER(vpi/vpi_config.h)
AC_CONFIG_HEADER(libveriuser/config.h)
AC_CONFIG_HEADER(tgt-vvp/vvp_config.h)
AC_CONFIG_HEADER(tgt-vhdl/vhdl_config.h)
AC_CONFIG_HEADER(tgt-pcb/pcb_config.h)
AC_CANONICAL_HOST
dnl Checks for programs.
AC_PROG_CC
# AC_PROG_CC_C99 is only available in autoconf version 2.60 and later.
# If you must use an older version then comment out the following two
# lines, but be warned that there could be issues with finding the
# nan(), etc. functions. It is really best to upgrade to a supported
# version of autoconf.
AC_PREREQ([2.60])
AC_PROG_CC_C99
AC_PROG_CXX
AC_PROG_RANLIB
AC_CHECK_TOOL(LD, ld, false)
AC_CHECK_TOOL(AR, ar, false)
AC_CHECK_TOOL(DLLTOOL, dlltool, false)
AC_CHECK_TOOL(STRIP, strip, true)
AC_CHECK_TOOL(WINDRES,windres,false)
AC_CHECK_PROGS(XGPERF,gperf,none)
AC_CHECK_PROGS(MAN,man,none)
AC_CHECK_PROGS(PS2PDF,ps2pdf,none)
AC_CHECK_PROGS(GIT,git,none)
if test "$XGPERF" = "none"
then
echo ""
echo "*** Warning: No suitable gperf found. ***"
echo " The gperf package is essential for building ivl from"
echo " CVS sources, or modifying the parse engine of ivl itself."
echo " You can get away without it when simply building from"
echo " snapshots or major releases."
echo ""
fi
AC_CHECK_PROGS(LEX,flex,none)
if test "$LEX" = "none"
then
echo "*** Error: No suitable flex found. ***"
echo " Please install the 'flex' package."
exit 1
fi
AC_CHECK_PROGS(YACC,bison,none)
if test "$YACC" = "none"
then
echo "*** Error: No suitable bison found. ***"
echo " Please install the 'bison' package."
exit 1
fi
AC_EXEEXT
AC_SUBST(EXEEXT)
# Combined check for Microsoft-related bogosities; sets WIN32 if found
AX_WIN32
# Check to see if we are using the Sun compiler. If so then configure
# some of the flags to match the Sun compiler syntax. This is also used
# in the aclocal.m4 file to configure the flags used to build and link
# dynamic libraries
AC_CHECK_DECL(__SUNPRO_C, using_sunpro_c=1, using_sunpro_c=0)
if test ${using_sunpro_c} = 1
then
AC_SUBST(DEPENDENCY_FLAG, [-xMMD])
AC_SUBST(WARNING_FLAGS, [""])
AC_SUBST(WARNING_FLAGS_CXX, [""])
else
# Check to see if -Wextra is supported.
iverilog_temp_cflags="$CFLAGS"
CFLAGS="-Wextra $CFLAGS"
AC_MSG_CHECKING(if gcc supports -Wextra)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
[[iverilog_wextra_flag="-Wextra";] AC_MSG_RESULT(yes)],
[[iverilog_wextra_flag="-W";] AC_MSG_RESULT(no)])
CFLAGS="$iverilog_temp_cflags"
AC_SUBST(DEPENDENCY_FLAG, [-MD])
AC_SUBST(WARNING_FLAGS, ["-Wall -Wshadow"])
AC_SUBST(WARNING_FLAGS_CXX, ["$iverilog_wextra_flag"])
fi
AC_LANG(C++)
# Check that we are using either the GNU compilers or the Sun compilers
# but not a mixture of the two (not currently supported).
AC_CHECK_DECL(__SUNPRO_CC, using_sunpro_cc=1, using_sunpro_cc=0)
if test ${using_sunpro_c} = 1
then
if test ${using_sunpro_cc} = 0
then
echo "*** Error: No support for mixing GNU and Sun compilers. ***"
echo " Using Sun C compiler and GNU C++ compiler.."
exit 1
fi
else
if test ${using_sunpro_cc} = 1
then
echo "*** Error: No support for mixing GNU and Sun compilers. ***"
echo " Using GNU C compiler and Sun C++ compiler.."
exit 1
fi
fi
AC_CHECK_HEADERS(getopt.h inttypes.h libiberty.h iosfwd sys/wait.h)
AC_CHECK_SIZEOF(unsigned long long)
AC_CHECK_SIZEOF(unsigned long)
AC_CHECK_SIZEOF(unsigned)
# vvp uses these...
AC_CHECK_LIB(termcap, tputs)
AC_CHECK_LIB(readline, readline)
AC_CHECK_LIB(history, add_history)
AC_CHECK_HEADERS(readline/readline.h readline/history.h sys/resource.h)
case "${host}" in *linux*) AC_DEFINE([LINUX], [1], [Host operating system is Linux.]) ;; esac
# vpi uses these
AC_CHECK_LIB(pthread, pthread_create)
AC_CHECK_LIB(z, gzwrite)
AC_CHECK_LIB(z, gzwrite, HAVE_LIBZ=yes, HAVE_LIBZ=no)
AC_SUBST(HAVE_LIBZ)
if test "$WIN32" = "yes"; then
AC_CHECK_LIB(bz2, main)
AC_CHECK_LIB(bz2, main, HAVE_LIBBZ2=yes, HAVE_LIBBZ2=no)
else
AC_CHECK_LIB(bz2, BZ2_bzdopen)
AC_CHECK_LIB(bz2, BZ2_bzdopen, HAVE_LIBBZ2=yes, HAVE_LIBBZ2=no)
fi
AC_SUBST(HAVE_LIBBZ2)
# The lxt/lxt2 files from GTKWave use these...
AC_FUNC_ALLOCA
AC_FUNC_FSEEKO
# valgrind checks
AC_ARG_WITH([valgrind], [AC_HELP_STRING([--with-valgrind],
[Add valgrind hooks])],
[], [check_valgrind=yes])
AS_IF([test "x$check_valgrind" = xyes],
[AC_MSG_NOTICE([Not using valgrind hooks])],
[AC_CHECK_HEADER([valgrind/memcheck.h],
[AC_DEFINE([CHECK_WITH_VALGRIND], [1],
[Define to one to use the valgrind hooks])],
[AC_MSG_ERROR([Could not find <valgrind/memcheck.h>])])])
AC_MSG_CHECKING(for sys/times)
AC_TRY_LINK(
#include <unistd.h>
#include <sys/times.h>
,{clock_t a = times(0)/sysconf(_SC_CLK_TCK);},
do_times=yes
AC_DEFINE([HAVE_TIMES], [1], [The times system call is available in the host operating system.]),
do_times=no
)
AC_MSG_RESULT($do_times)
# --
# Look for a dl library to use. First look for the standard dlopen
# functions, and failing that look for the HP specific shl_load function.
AC_CHECK_HEADERS(dlfcn.h dl.h, break)
DLLIB=''
AC_CHECK_LIB(dl,dlopen,[DLLIB=-ldl])
if test -z "$DLLIB" ; then
AC_CHECK_LIB(dld,shl_load,[DLLIB=-ldld])
fi
AC_SUBST(DLLIB)
AC_CHECK_HEADERS(getopt.h)
AC_PROG_INSTALL
AC_LANG(C)
AC_C_BIGENDIAN
# $host
AX_ENABLE_SUFFIX
AX_LD_EXTRALIBS
# Compiler option for position independent code, needed when making shared objects.
# CFLAGS inherited by cadpli/Makefile?
AX_C_PICFLAG
# may modify CPPFLAGS and CFLAGS
AX_CPP_PRECOMP
# may modify LDFLAGS
AX_C99_STRTOD
# Processor specific compile flags
case "${host}" in
alpha*-*-linux*)
CPPFLAGS="-mieee $CPPFLAGS"
CFLAGS="-mieee $CFLAGS"
;;
esac
# Do some more operating system specific setup. We put the file64_support
# define in a substitution instead of simply a define because there
# are source files (namely lxt support files) that don't include any
# config.h header file.
file64_support=''
case "${host}" in
*-*-linux*)
AC_DEFINE([_LARGEFILE_SOURCE], [1], [Indicates LFS (i.e. the ability to create files larger than 2 GiB on 32-bit operating systems).])
file64_support='-D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64'
;;
esac
AC_SUBST(file64_support)
# Check that these functions exist. They are mostly C99
# functions that older compilers may not yet support.
AC_CHECK_FUNCS(fopen64)
# The following math functions may be defined in the math library so look
# in the default libraries first and then look in -lm for them. On some
# systems we may need to use the compiler in C99 mode to get a definition.
# We requested C99 mode earlier with AC_PROG_CC_C99.
AC_SEARCH_LIBS([lround], [m], [AC_DEFINE([HAVE_LROUND], [1])])
AC_SEARCH_LIBS([llround], [m], [AC_DEFINE([HAVE_LLROUND], [1])])
AC_SEARCH_LIBS([nan], [m], [AC_DEFINE([HAVE_NAN], [1])])
AC_SEARCH_LIBS([fmin], [m], [AC_DEFINE([HAVE_FMIN], [1])])
AC_SEARCH_LIBS([fmax], [m], [AC_DEFINE([HAVE_FMAX], [1])])
# Check to see if an unsigned long and uint64_t are the same from
# a compiler perspective. We can not just check that they are the
# same size since unsigned long and unsigned long long are not the
# same from an overloading perspective even though they could be
# the same size on some 64 bit machines. The result from this test
# is only used if inttypes.h is available, so if the test fails for
# that reason we don't care.
AC_LANG(C++)
AC_MSG_CHECKING(if uint64_t and unsigned long are identical)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include "inttypes.h"
static bool check(unsigned long val)
{
return val != 0;
}
static bool check(uint64_t val)
{
return val != 0;
}]], [[unsigned long ulval = 1;
bool result = check(ulval);
uint64_t uival = 1;
result &= check(uival);
return !result;]])],
[AC_MSG_RESULT(no)],
[AC_DEFINE([UINT64_T_AND_ULONG_SAME], [1]) AC_MSG_RESULT(yes)])
# Linker option used when compiling the target
AX_LD_RDYNAMIC
# linker options when building a shared library
AX_LD_SHAREDLIB_OPTS
#######################
## test for underscores. The vpi module loader needs to know this
## in order to know the name of the start symbol for the .vpi module.
#######################
AX_C_UNDERSCORES_LEADING
AX_C_UNDERSCORES_TRAILING
#######################
## end of test for underscores
#######################
#######################
# Sanity check the configured results
#######################
AC_MSG_CHECKING(for sanity of prefix)
if test `echo "$prefix" | wc -w` != 1
then
AC_MSG_ERROR(cannot configure white space in prefix: $prefix)
fi
AC_MSG_RESULT(ok)
AC_MSG_CHECKING(for sanity of exec_prefix)
if test `echo "$exec_prefix" | wc -w` != 1
then
AC_MSG_ERROR(cannot configure white space in exec_prefix: $exec_prefix)
fi
AC_MSG_RESULT(ok)
AC_MSG_CHECKING(for sanity of libdir)
if test `echo "$libdir" | wc -w` != 1
then
AC_MSG_ERROR(cannot configure white space in libdir: $libdir)
fi
AC_MSG_RESULT(ok)
# XXX disable tgt-fpga for the moment
AC_OUTPUT(Makefile ivlpp/Makefile vhdlpp/Makefile vvp/Makefile vpi/Makefile driver/Makefile driver-vpi/Makefile cadpli/Makefile libveriuser/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-vvp/Makefile tgt-vhdl/Makefile tgt-fpga/Makefile tgt-verilog/Makefile tgt-pal/Makefile tgt-vlog95/Makefile tgt-pcb/Makefile)
AC_OUTPUT(Makefile vpi/Makefile ivlpp/Makefile vvm/Makefile)
-43
View File
@@ -1,43 +0,0 @@
// Mathematical and physical constants
`ifdef CONSTANTS_VAMS
`else
`define CONSTANTS_VAMS 1
// M_ is a mathematical constant
`define M_E 2.7182818284590452354
`define M_LOG2E 1.4426950408889634074
`define M_LOG10E 0.43429448190325182765
`define M_LN2 0.69314718055994530942
`define M_LN10 2.30258509299404568402
`define M_PI 3.14159265358979323846
`define M_TWO_PI 6.28318530717958647693
`define M_PI_2 1.57079632679489661923
`define M_PI_4 0.78539816339744830962
`define M_1_PI 0.31830988618379067154
`define M_2_PI 0.63661977236758134308
`define M_2_SQRTPI 1.12837916709551257390
`define M_SQRT2 1.41421356237309504880
`define M_SQRT1_2 0.70710678118654752440
/*
* Do we need these? For now they are not available.
*
// The following constants have been taken from http://physics.nist.gov
// P_ is a physical constant
// charge of electron in coulombs
`define P_Q 1.602176462e-19
// speed of light in vacuum in meters/sec
`define P_C 2.99792458e8
// Boltzmann's constant in joules/kelvin
`define P_K 1.3806503e-23
// Planck's constant in joules*sec
`define P_H 6.62606876e-34
// permittivity of vacuum in farads/meter
`define P_EPS0 8.854187817e-12
// permeability of vacuum in henrys/meter
`define P_U0 (4.0e-7 * `M_PI)
// zero celsius in kelvin
`define P_CELSIUS0 273.15
*/
`endif
-3
View File
@@ -1,3 +0,0 @@
// These are correct and are used to find the base (zero) pin.
thisSubtraction:netlist.h:4169
thisSubtraction:netlist.h:4178
+150 -220
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2010 Stephen Williams ([email protected])
* Copyright (c) 1998 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,258 +16,188 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: cprop.cc,v 1.2 1998/12/02 04:37:13 steve Exp $"
#endif
# include "config.h"
# include <cstdlib>
# include "netlist.h"
# include "netmisc.h"
# include "functor.h"
# include "compiler.h"
# include "ivl_assert.h"
# include <vector>
# include <assert.h>
/*
* The cprop function below invokes constant propagation where
* The cprop function below invokes constant propogation where
* possible. The elaboration generates NetConst objects. I can remove
* these and replace the gates connected to it with simpler ones. I
* may even be able to replace nets with a new constant.
*/
struct cprop_functor : public functor_t {
unsigned count;
virtual void signal(Design*des, NetNet*obj);
virtual void lpm_add_sub(Design*des, NetAddSub*obj);
virtual void lpm_compare(Design*des, NetCompare*obj);
virtual void lpm_compare_eq_(Design*des, NetCompare*obj);
virtual void lpm_ff(Design*des, NetFF*obj);
virtual void lpm_logic(Design*des, NetLogic*obj);
virtual void lpm_mux(Design*des, NetMux*obj);
};
void cprop_functor::signal(Design*, NetNet*)
static bool is_a_const_node(const NetNode*obj)
{
return dynamic_cast<const NetConst*>(obj);
}
void cprop_functor::lpm_add_sub(Design*, NetAddSub*)
static bool const_into_xnor(Design*des, NetConst*obj,
NetLogic*log, unsigned pin)
{
assert(pin > 0);
/* if this is the last input pin of the XNOR device, then
the device is simply buffering the constant value. */
if (log->pin_count() == 2) {
cerr << "cprop: delete gate " << log->name() <<
" and propogate " << obj->value() << "." << endl;
assert(pin == 1);
connect(log->pin(0), log->pin(1));
delete log;
return true;
}
/* If this is a constant 0, then replace the gate with one
1-pin smaller. Skip this pin. */
if (obj->value() == verinum::V0) {
cerr << "cprop: disconnect pin " << pin << " from gate "
<< log->name() << "." << endl;
NetLogic*tmp = new NetLogic(log->name(),
log->pin_count()-1,
NetLogic::XNOR);
connect(log->pin(0), tmp->pin(0));
unsigned idx, jdx;
for (idx = 1, jdx = 1 ; idx < log->pin_count() ; idx += 1) {
if (idx == pin) continue;
connect(log->pin(idx), tmp->pin(jdx));
jdx += 1;
}
delete log;
des->add_node(tmp);
return true;
}
/* If this is a constant 1, then replace the gate with an XOR
that is 1-pin smaller. Removing the constant 1 causes the
sense of the output to change. */
if (obj->value() == verinum::V1) {
cerr << "cprop: disconnect pin " << pin << " from gate "
<< log->name() << "." << endl;
NetLogic*tmp = new NetLogic(log->name(),
log->pin_count()-1,
NetLogic::XOR);
connect(log->pin(0), tmp->pin(0));
unsigned idx, jdx;
for (idx = 1, jdx = 1 ; idx < log->pin_count() ; idx += 1) {
if (idx == pin) continue;
connect(log->pin(idx), tmp->pin(jdx));
jdx += 1;
}
delete log;
des->add_node(tmp);
return true;
}
/* If this is a constant X or Z, then the gate is certain to
generate an X. Replace the gate with a constant X. This may
cause other signals all over to become dangling. */
if ((obj->value() == verinum::Vx) || (obj->value() == verinum::Vz)) {
cerr << "cprop: replace gate " << log->name() << " with "
"a constant X." << endl;
NetConst*tmp = new NetConst(log->name(), verinum::Vx);
connect(log->pin(0), tmp->pin(0));
delete log;
des->add_node(tmp);
return true;
}
return false;
}
void cprop_functor::lpm_compare(Design*des, NetCompare*obj)
static void look_for_core_logic(Design*des, NetConst*obj)
{
if (obj->pin_AEB().is_linked()) {
assert( ! obj->pin_AGB().is_linked() );
assert( ! obj->pin_AGEB().is_linked() );
assert( ! obj->pin_ALB().is_linked() );
assert( ! obj->pin_ALEB().is_linked() );
assert( ! obj->pin_AGB().is_linked() );
assert( ! obj->pin_ANEB().is_linked() );
lpm_compare_eq_(des, obj);
return;
NetObj*cur = obj;
unsigned pin = 0;
for (obj->pin(0).next_link(cur, pin)
; cur != obj
; cur->pin(pin).next_link(cur, pin)) {
NetLogic*log = dynamic_cast<NetLogic*>(cur);
if (log == 0)
continue;
bool flag = false;
switch (log->type()) {
case NetLogic::XNOR:
flag = const_into_xnor(des, obj, log, pin);
break;
default:
break;
}
/* If the optimization test tells me that a link was
deleted, restart the scan. */
if (flag) obj->pin(0).next_link(cur, pin);
}
}
void cprop_functor::lpm_compare_eq_(Design*, NetCompare*)
{
}
void cprop_functor::lpm_ff(Design*, NetFF*obj)
{
// Look for and count unlinked FF outputs. Note that if the
// Data and Q pins are connected together, they can be removed
// from the circuit, since it doesn't do anything.
if (connected(obj->pin_Data(), obj->pin_Q())
&& (! obj->pin_Sclr().is_linked())
&& (! obj->pin_Sset().is_linked())
&& (! obj->pin_Aclr().is_linked())
&& (! obj->pin_Aset().is_linked())) {
obj->pin_Data().unlink();
obj->pin_Q().unlink();
delete obj;
}
}
void cprop_functor::lpm_logic(Design*, NetLogic*)
{
}
/*
* 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
* input used to enable the output.
*/
void cprop_functor::lpm_mux(Design*des, NetMux*obj)
{
if (obj->size() != 2)
return;
if (obj->sel_width() != 1)
return;
Nexus*sel_nex = obj->pin_Sel().nexus();
/* If the select input is constant, then replace with a BUFZ */
// If the select is not constant, there is nothing we can do.
if (! sel_nex->drivers_constant())
return;
// If the select input is assigned or forced, then again there
// is nothing we can do here.
if (sel_nex->assign_lval())
return;
// If the constant select is 'bz or 'bx, then give up.
verinum::V sel_val = sel_nex->driven_value();
if (sel_val == verinum::Vz || sel_val == verinum::Vx)
return;
// The Select input must be a defined constant value, so we
// can replace the device with a BUFZ.
NetBUFZ*tmp = new NetBUFZ(obj->scope(), obj->name(), obj->width(), true);
tmp->set_line(*obj);
if (debug_optimizer)
cerr << obj->get_fileline() << ": debug: "
<< "Replace binary MUX with constant select=" << sel_val
<< " with a BUFZ to the selected input." << endl;
tmp->rise_time(obj->rise_time());
tmp->fall_time(obj->fall_time());
tmp->decay_time(obj->decay_time());
connect(tmp->pin(0), obj->pin_Result());
if (sel_val == verinum::V1)
connect(tmp->pin(1), obj->pin_Data(1));
else
connect(tmp->pin(1), obj->pin_Data(0));
delete obj;
des->add_node(tmp);
count += 1;
}
/*
* This functor looks to see if the constant is connected to nothing
* This function looks to see if the constant is connected to nothing
* but signals. If that is the case, delete the dangling constant and
* the now useless signals. This functor is applied after the regular
* functor to clean up dangling constants that might be left behind.
* the now useless signals.
*/
struct cprop_dc_functor : public functor_t {
virtual void lpm_const(Design*des, NetConst*obj);
};
struct nexus_info_s {
Nexus*nex;
unsigned inp;
unsigned out;
};
void cprop_dc_functor::lpm_const(Design*, NetConst*obj)
static void dangling_const(Design*des, NetConst*obj)
{
// 'bz constant values drive high impedance to whatever is
// connected to it. In other words, it is a noop. But that is
// only true if *all* the bits of the vectors.
{ unsigned tmp = 0;
ivl_assert(*obj, obj->pin_count()==1);
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
if (obj->value(idx) == verinum::Vz) {
tmp += 1;
}
}
// If there are any links that take input, abort this
// operation.
if (count_inputs(obj->pin(0)) > 0)
return;
if (tmp == obj->width()) {
delete obj;
return;
}
}
std::vector<nexus_info_s> nexus_info (obj->pin_count());
for (unsigned idx = 0 ; idx < obj->pin_count() ; idx += 1) {
nexus_info[idx].nex = obj->pin(idx).nexus();
unsigned inputs = 0, outputs = 0;
nexus_info[idx].nex -> count_io(inputs, outputs);
nexus_info[idx].inp = inputs;
nexus_info[idx].out = outputs;
}
// If there are any links that take input, the constant is
// used structurally somewhere.
for (unsigned idx = 0 ; idx < obj->pin_count() ; idx += 1)
if (nexus_info[idx].inp > 0)
return;
// Look for signals that have NetESignal nodes attached to
// them. If I find any, then this constant is used by a
// behavioral expression somewhere.
for (unsigned idx = 0 ; idx < obj->pin_count() ; idx += 1) {
for (Link*clnk = nexus_info[idx].nex->first_nlink()
; clnk ; clnk = clnk->next_nlink()) {
NetPins*cur;
unsigned pin;
clnk->cur_link(cur, pin);
NetNet*tmp = dynamic_cast<NetNet*>(cur);
if (tmp == 0)
continue;
assert(tmp->scope());
// If the net is a signal name from the source,
// then users will probably want to see it in the
// waveform dump, so unhooking the constant will
// make it look wrong.
if (! tmp->local_flag())
return;
// If the net has an eref, then there is an
// expression somewhere that reads this signal. So
// the constant does get read.
if (tmp->peek_eref() > 0)
return;
// If the net is a port of the root module, then
// the constant may be driving something outside
// the design, so do not eliminate it.
if ((tmp->port_type() != NetNet::NOT_A_PORT)
&& (tmp->scope()->parent() == 0))
return;
// If there are no other drivers, delete all the signals that
// are also dangling.
if (count_outputs(obj->pin(0)) == 1) {
NetObj*cur;
unsigned pin;
obj->pin(0).next_link(cur, pin);
while (cur != obj) {
cerr << "cprop: delete dangling signal " << cur->name() <<
"." << endl;
delete cur;
obj->pin(0).next_link(cur, pin);
}
}
// Done. Found no reason to keep this object, so delete it.
// Done. Delete me.
delete obj;
}
void cprop(Design*des)
{
// Continually propagate constants until a scan finds nothing
// to do.
cprop_functor prop;
do {
prop.count = 0;
des->functor(&prop);
if (verbose_flag) {
cout << " ... Iteration detected "
<< prop.count << " optimizations." << endl << flush;
}
} while (prop.count > 0);
if (verbose_flag) {
cout << " ... Look for dangling constants" << endl << flush;
des->clear_node_marks();
while (NetNode*obj = des->find_node(&is_a_const_node)) {
NetConst*cur = dynamic_cast<NetConst*>(obj);
look_for_core_logic(des, cur);
cur->set_mark();
dangling_const(des, cur);
}
cprop_dc_functor dc;
des->functor(&dc);
if (verbose_flag) {
cout << " ... done" << endl << flush;
}
}
/*
* $Log: cprop.cc,v $
* Revision 1.2 1998/12/02 04:37:13 steve
* Add the nobufz function to eliminate bufz objects,
* Object links are marked with direction,
* constant propagation is more careful will wide links,
* Signal folding is aware of attributes, and
* the XNF target can dump UDP objects based on LCA
* attributes.
*
* Revision 1.1 1998/11/13 06:23:17 steve
* Introduce netlist optimizations with the
* cprop function to do constant propogation.
*
*/
-35
View File
@@ -1,35 +0,0 @@
This file describes the build procedure under cygwin32 (Windows 95/98/NT/2K)
----------------------------------------------------------------------------
Note: Icarus Verilog also compiles to native Windows binaries if you
use the instructions in the mingw.txt file. Some people prefer cygwin
binaries, and these instructions apply.
To build using cygwin:
Prerequisites:
o Latest net release (1.1.4) of cygwin (sources.redhat.com/cygwin)
Procedure:
o Get the source code - see the main Icarus Verilog page for how to
do this
o cd to the verilog directory
o autoconf.sh
o ./configure
o make
o make install
That's all that's needed.
To build your own extensions - just include vpi_user.h and link with
a command like this:
$(CC) -shared -o <dllname> <objects> -Wl,--enable-auto-image-base -L../vvm -lvvm -lvpip
- Venkat Iyer <[email protected]>
+588 -1089
View File
File diff suppressed because it is too large Load Diff
-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.
-39
View File
@@ -1,39 +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 "discipline.h"
ivl_nature_s::ivl_nature_s(perm_string name__, perm_string access__)
: name_(name__), access_(access__)
{
}
ivl_nature_s::~ivl_nature_s()
{
}
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__)
{
}
ivl_discipline_s::~ivl_discipline_s()
{
}
-77
View File
@@ -1,77 +0,0 @@
#ifndef __discipline_H
#define __discipline_H
/*
* Copyright (c) 2008-2010 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* 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
*/
/*
* The discipline types include the discipline, nature and other
* related types for managing declared and used disciplines in a
* Verilog-AMS program.
*/
# include "StringHeap.h"
# include <iostream>
# include <map>
# include "ivl_target.h"
# include "LineInfo.h"
extern std::ostream& operator << (std::ostream&, ivl_dis_domain_t);
class ivl_nature_s : public LineInfo {
public:
explicit ivl_nature_s(perm_string name, perm_string access);
~ivl_nature_s();
perm_string name() const { return name_; }
// Identifier for the access function for this nature
perm_string access() const { return access_; }
private:
perm_string name_;
perm_string access_;
};
class ivl_discipline_s : 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();
perm_string name() const { return name_; }
ivl_dis_domain_t domain() const { return domain_; }
ivl_nature_t potential() const { return potential_; }
ivl_nature_t flow() const { return flow_; }
private:
perm_string name_;
ivl_dis_domain_t domain_;
ivl_nature_t potential_;
ivl_nature_t flow_;
private: // not implemented
ivl_discipline_s(const ivl_discipline_s&);
ivl_discipline_s& operator = (const ivl_discipline_s&);
};
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;
#endif
-72
View File
@@ -1,72 +0,0 @@
// Standard definitions for Verilog-AMS
`ifdef DISCIPLINES_VAMS
`else
`define DISCIPLINES_VAMS 1
discipline \logic ;
domain discrete;
enddiscipline
discipline ddiscrete;
domain discrete;
enddiscipline
nature Current;
units = "A";
access = I;
idt_nature = Charge;
`ifdef CURRENT_ABSTOL
abstol = `CURRENT_ABSTOL
`else
abstol = 1e-12;
`endif
endnature
nature Charge;
units = "coul";
access = Q;
ddt_nature = Current;
`ifdef CHARGE_ABSTOL
abstol = `CHARGE_ABSTOL;
`else
abstol = 1e-14;
`endif
endnature
nature Voltage;
units = "V";
access = V;
idt_nature = Flux;
`ifdef VOLTAGE_ABSTOL
abstol = `VOLTAGE_ABSTOL;
`else
abstol = 1e-6;
`endif
endnature
nature Flux;
units = "Wb";
access = Phi;
ddt_nature = Voltage;
`ifdef FLUX_ABSTOL
abstol = `flux_ABSTOL;
`else
abstol = 1e-9;
`endif
endnature
discipline electrical;
potential Voltage;
flow Current;
enddiscipline
discipline voltage;
potential Voltage;
enddiscipline
discipline current;
flow Current;
enddiscipline
`endif // !`ifdef DISCIPLINES_VAMS
-68
View File
@@ -1,68 +0,0 @@
/*
* Copyright (c) 2001-2009 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
*/
/*
* This is a simple program to make a dosified copy of the
* original. That is, it converts unix style line ends to DOS
* style. This is useful for installing text files.
*
* The exact substitution is to replace \n with \r\n. If the line
* already ends with \r\n then it is not changed to \r\r\n.
*/
# include <stdio.h>
int main(int argc, char*argv[])
{
FILE*ifile;
FILE*ofile;
int ch, pr;
if (argc != 3) {
fprintf(stderr, "Usage: %s <input> <output>\n", argv[0]);
return 1;
}
ifile = fopen(argv[1], "rb");
if (ifile == 0) {
fprintf(stderr, "Unable to open %s for input.\n", argv[1]);
return 2;
}
ofile = fopen(argv[2], "wb");
if (ofile == 0) {
fprintf(stderr, "Unable to open %s for output.\n", argv[2]);
fclose(ifile);
return 2;
}
pr = 0;
while ((ch = fgetc(ifile)) != EOF) {
if ((ch == '\n') && (pr != '\r'))
fputc('\r', ofile);
fputc(ch, ofile);
pr = ch;
}
fclose(ifile);
fclose(ofile);
return 0;
}
-104
View File
@@ -1,104 +0,0 @@
#
# This source code is free software; you can redistribute it
# and/or modify it in source code form under the terms of the GNU
# Library General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc.,
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
SHELL = /bin/sh
suffix = @install_suffix@
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
datarootdir = @datarootdir@
VPATH = $(srcdir)
suffix = @install_suffix@
bindir = $(exec_prefix)/bin
libdir = $(exec_prefix)/lib
includedir = $(prefix)/include
mandir = @mandir@
dllib=@DLLIB@
CC = @CC@
WINDRES = @WINDRES@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
ifeq (@srcdir@,.)
INCLUDE_PATH = -I. -I..
else
INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/..
endif
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
LDFLAGS = @LDFLAGS@
O = main.o res.o
all: iverilog-vpi@EXEEXT@
check: all
clean:
rm -f *.o config.h iverilog-vpi@EXEEXT@ res.rc
distclean: clean
rm -f Makefile config.log
cppcheck: main.c
cppcheck --enable=all -f $(INCLUDE_PATH) $^
Makefile: $(srcdir)/Makefile.in ../config.status
cd ..; ./config.status --file=driver-vpi/$@
iverilog-vpi@EXEEXT@: $O
$(CC) $(LDFLAGS) $O -o iverilog-vpi@EXEEXT@ @EXTRALIBS@
main.o: $(srcdir)/main.c config.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c $(srcdir)/main.c
config.h: $(srcdir)/config.h.in Makefile
sed -e 's;@IVLCC@;@CC@;' -e 's;@IVLCXX@;@CXX@;' \
-e 's;@SUFFIX@;$(suffix);g' \
-e 's;@IVLCFLAGS@;$(CFLAGS);' \
-e 's;@SHARED@;@shared@;' $< > $@
# Windows specific...
res.rc: $(srcdir)/res.rc.in ../version.exe
sed -e 's;@PRODUCTVERSION@;'`../version.exe '%M,%m,%n,0'`';' \
$(srcdir)/res.rc.in > $@
res.o: res.rc
$(WINDRES) -i res.rc -o res.o
#
install: all installdirs $(bindir)/iverilog-vpi$(suffix)@EXEEXT@
$(bindir)/iverilog-vpi$(suffix)@EXEEXT@: ./iverilog-vpi@EXEEXT@
$(INSTALL_PROGRAM) ./iverilog-vpi@EXEEXT@ "$(bindir)/iverilog-vpi$(suffix)@EXEEXT@"
installdirs: $(srcdir)/../mkinstalldirs
$(srcdir)/../mkinstalldirs "$(bindir)"
uninstall:
rm -f $(bindir)/iverilog-vpi$(suffix)@EXEEXT@
-9
View File
@@ -1,9 +0,0 @@
/* For now do not put the Icarus Verilog include or library paths here.
* They are generated from a registry entry the user must set (-ivl=).
* This may change in the future once I have thought about it more. */
#define IVERILOG_VPI_CC "@IVLCC@"
#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@"
-657
View File
@@ -1,657 +0,0 @@
/*
* Copyright (c) 2002 Gus Baldauf ([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
*/
/*
* iverilog-vpi.c
*
* this program provides the functionality of iverilog-vpi.sh under Win32
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <windows.h>
static void setup_ivl_environment();
static void assign(char **ptr, char *str);
/* The compile options: compiler, flags, etc. are in here */
#include "config.h"
/* pointers to global strings */
static struct global_strings {
char *pCCSRC; /* list of C source files (*.c) */
char *pCXSRC; /* list of C++ source files (*.cc, *.cpp) */
char *pOBJ; /* list of object files */
char *pLIB; /* list of library files */
char *pINCS; /* list of include directories */
char *pDEFS; /* list of definitions */
char *pOUT; /* output file name (.vpi extension), if 0 length then no source files specified */
char *pMINGW; /* path to MinGW directory */
char *pIVL; /* path to IVL directory */
char *pCFLAGS; /* CFLAGS option */
char *pLDLIBS; /* LDLIBS option */
char *pNewPath; /* new PATH environment variable setting */
char *pLD; /* what to use for a linker */
} gstr;
static void deInitDynString(char *str)
{
free(str);
}
/* when finished, free allocated memory and return error code */
static void myExit(int exitVal)
{
deInitDynString(gstr.pCCSRC);
deInitDynString(gstr.pCXSRC);
deInitDynString(gstr.pOBJ);
deInitDynString(gstr.pLIB);
deInitDynString(gstr.pINCS);
deInitDynString(gstr.pDEFS);
deInitDynString(gstr.pOUT);
deInitDynString(gstr.pMINGW);
deInitDynString(gstr.pIVL);
deInitDynString(gstr.pCFLAGS);
deInitDynString(gstr.pLDLIBS);
deInitDynString(gstr.pNewPath);
free(gstr.pLD);
exit(exitVal);
}
/* display usage summary and exit */
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");
myExit(1);
}
static void initDynString(char **str)
{
*str = (char *) malloc(1);
if (!*str) {
fprintf(stderr,"error: out of memory\n");
myExit(4);
}
*str[0] = 0;
}
/* initialize dynamic memory buffers */
static void init()
{
initDynString(&gstr.pCCSRC);
initDynString(&gstr.pCXSRC);
initDynString(&gstr.pOBJ);
initDynString(&gstr.pLIB);
initDynString(&gstr.pINCS);
initDynString(&gstr.pDEFS);
initDynString(&gstr.pOUT);
initDynString(&gstr.pMINGW);
initDynString(&gstr.pIVL);
initDynString(&gstr.pCFLAGS);
initDynString(&gstr.pLDLIBS);
initDynString(&gstr.pNewPath);
/* By default use the C compiler to link the programs. */
assign(&gstr.pLD, IVERILOG_VPI_CC);
}
/* return true if "str" is terminated with with "end", case insensitive */
static int endsIn (char *end, char *str)
{
char *ext;
if (strlen(end) >= strlen(str))
return 0;
ext = str + (strlen(str) - strlen(end));
return stricmp(end,ext) ? 0 : 1;
}
/* return true if "str" begins with "prefix", case insensitive */
static int startsWith (char *prefix, char *str)
{
if (strlen(prefix) >= strlen(str))
return 0;
return strnicmp(prefix,str,strlen(prefix)) ? 0 : 1;
}
/* append "app" to "ptr", allocating memory as needed */
/* if count is zero, then copy all characters of "app" */
static void appendn (char **ptr, char *app, int count)
{
char *nptr = (char *) realloc(*ptr, strlen(*ptr) +
(count?count:strlen(app)) + 1);
if (nptr == NULL) {
fprintf(stderr,"error: out of memory\n");
free(*ptr);
myExit(4);
}
*ptr = nptr;
if (count)
strncat(*ptr,app,count);
else
strcat(*ptr,app);
}
/* append "app" to "ptr", allocating memory as needed */
static void append (char **ptr, char *app)
{
appendn(ptr,app,0);
}
/* if the string does not end with a backslash, add one */
static void appendBackSlash(char **str)
{
if ((*str)[strlen(*str)-1] != '\\')
append(str,"\\");
}
/* copy count characters of "str" to "ptr", allocating memory as needed */
/* if count is zero, then copy all characters of "str" */
static void assignn (char **ptr, char *str, int count)
{
char *nptr = (char *) realloc(*ptr, (count?count:strlen(str)) + 1);
if (nptr == NULL) {
fprintf(stderr,"error: out of memory\n");
free(*ptr);
myExit(4);
}
*ptr = nptr;
if (count) {
strncpy(*ptr,str,count);
(*ptr)[count] = 0;
}
else
strcpy(*ptr,str);
}
/* copy count characters of "str" to "ptr", allocating memory as needed */
static void assign (char **ptr, char *str)
{
assignn(ptr,str,0);
}
/* get a copy of a Icarus Verilog registry string key */
static int GetRegistryKey(char *key, char **value)
{
long lrv;
HKEY hkKey;
char *regKeyBuffer;
DWORD regKeyType, regKeySize;
lrv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\Icarus Verilog",0,KEY_QUERY_VALUE,&hkKey);
if (lrv != ERROR_SUCCESS)
return 0;
lrv = RegQueryValueEx(hkKey,key,NULL,&regKeyType,NULL,&regKeySize);
if ((lrv != ERROR_SUCCESS) || (regKeyType != REG_SZ) || (!regKeySize)) {
lrv = RegCloseKey(hkKey);
return 0;
}
regKeyBuffer = (char *) malloc(regKeySize+1);
if (!regKeyBuffer) {
lrv = RegCloseKey(hkKey);
fprintf(stderr,"error: out of memory\n");
myExit(4);
}
regKeyBuffer[regKeySize] = 0; /* makes sure there is a trailing NULL */
/* This needs an unsigned char *, but for MinGW the char is signed. */
lrv = RegQueryValueEx(hkKey, key, NULL, &regKeyType,
(unsigned char *) regKeyBuffer, &regKeySize);
if ((lrv != ERROR_SUCCESS) || (regKeyType != REG_SZ) || (!regKeySize)) {
lrv = RegCloseKey(hkKey);
free(regKeyBuffer);
return 0;
}
RegCloseKey(hkKey);
assign(value,regKeyBuffer);
free(regKeyBuffer);
return 1;
}
/* store a copy of a Icarus Verilog registry string key */
static void SetRegistryKey(char *key, char *value)
{
HKEY hkKey;
DWORD res;
if (RegCreateKeyEx(
HKEY_LOCAL_MACHINE,
"Software\\Icarus Verilog",
0,
"",
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,NULL,
&hkKey,
&res) != ERROR_SUCCESS)
return;
/* This needs an unsigned char *, but for MinGW the char is signed. */
RegSetValueEx(hkKey, key, 0, REG_SZ, (unsigned char *) value,
strlen(value)+1);
RegCloseKey(hkKey);
printf("info: storing %s in Windows' registry entry\n",value);
printf(" HKEY_LOCAL_MACHINE\\Software\\Icarus Verilog\\%s\n",key);
}
/* parse the command line, assign results to global variable strings */
static int parse(int argc, char *argv[])
{
int idx, srcFileCnt=0;
char dot_c_ext[] = ".c";
char dot_cc_ext[] = ".cc";
char dot_cpp_ext[] = ".cpp";
char dot_o_ext[] = ".o";
char name_option[] = "--name=";
char lib_option[] = "-l";
char inc_option[] = "-I";
char mingw_option[] = "-mingw=";
char ivl_option[] = "-ivl=";
char def_option[] = "-D";
if (argc == 1) return 0;
for (idx=1; idx<argc; ++idx) {
/* Check for C source files (*.c) */
if (endsIn(dot_c_ext, argv[idx])) {
++srcFileCnt;
append(&gstr.pCCSRC, argv[idx]);
append(&gstr.pCCSRC, " ");
if (!*gstr.pOUT)
assignn(&gstr.pOUT, argv[idx],
strlen(argv[idx])-strlen(dot_c_ext));
}
/* Check for C++ source files (*.cc) */
else if (endsIn(dot_cc_ext, argv[idx])) {
/* We need to link with the C++ compiler. */
assign(&gstr.pLD, IVERILOG_VPI_CXX);
++srcFileCnt;
append(&gstr.pCXSRC, argv[idx]);
append(&gstr.pCXSRC, " ");
if (!*gstr.pOUT)
assignn(&gstr.pOUT, argv[idx],
strlen(argv[idx])-strlen(dot_cc_ext));
}
/* Check for C++ source files (*.cpp) */
else if (endsIn(dot_cpp_ext, argv[idx])) {
/* We need to link with the C++ compiler. */
assign(&gstr.pLD, IVERILOG_VPI_CXX);
++srcFileCnt;
append(&gstr.pCXSRC, argv[idx]);
append(&gstr.pCXSRC, " ");
if (!*gstr.pOUT)
assignn(&gstr.pOUT, argv[idx],
strlen(argv[idx])-strlen(dot_cpp_ext));
}
/* Check for compiled object files */
else if (endsIn(dot_o_ext, argv[idx])) {
++srcFileCnt;
append(&gstr.pOBJ," ");
append(&gstr.pOBJ, argv[idx]);
if (!*gstr.pOUT)
assignn(&gstr.pOUT, argv[idx],
strlen(argv[idx])-strlen(dot_o_ext));
}
/* Check for the -mingw option */
else if (startsWith(mingw_option, argv[idx]))
assignn(&gstr.pMINGW, argv[idx]+sizeof(mingw_option)-1,
strlen(argv[idx])-(sizeof(mingw_option)-1));
/* Check for the -ivl option */
else if (startsWith(ivl_option, argv[idx]))
assignn(&gstr.pIVL, argv[idx]+sizeof(ivl_option)-1,
strlen(argv[idx])-(sizeof(ivl_option)-1));
/* Check for the --name option */
else if (startsWith(name_option, argv[idx])) {
assignn(&gstr.pOUT, argv[idx]+sizeof(name_option)-1,
strlen(argv[idx])-(sizeof(name_option)-1));
}
/* Check for the -l option */
else if (startsWith(lib_option, argv[idx])) {
append(&gstr.pLIB, " ");
append(&gstr.pLIB, argv[idx]);
}
/* Check for the -I option */
else if (startsWith(inc_option, argv[idx])) {
append(&gstr.pINCS, " ");
append(&gstr.pINCS, argv[idx]);
}
/* Check for the -D option */
else if (startsWith(def_option, argv[idx])) {
append(&gstr.pDEFS, " ");
append(&gstr.pDEFS, argv[idx]);
}
/* Check for the --cflags option */
else if (stricmp("--cflags", argv[idx]) == 0) {
setup_ivl_environment();
printf("%s\n", gstr.pCFLAGS);
myExit(0);
}
/* Check for the --ldflags option */
else if (stricmp("--ldflags", argv[idx]) == 0) {
printf("%s\n", IVERILOG_VPI_LDFLAGS);
myExit(0);
}
/* Check for the --ldlibs option */
else if (stricmp("--ldlibs", argv[idx]) == 0) {
setup_ivl_environment();
printf("%s\n", gstr.pLDLIBS);
myExit(0);
}
/* 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);
myExit(0);
}
/* This is different than iverilog-vpi.sh, we don't
* ignore unknown arguments */
else return 0;
}
/* In case there is a --name without source/object files */
if (0 == srcFileCnt) assign(&gstr.pOUT,"");
/* Normally it's an error if there are no source or object files */
/* Unless we are setting the IVL or MinGW registry entries */
if (!*gstr.pOUT) {
if (!*gstr.pMINGW && !*gstr.pIVL) return 0;
} else
/* We have a valid result file so add the .vpi extension */
append(&gstr.pOUT, ".vpi");
return 1;
}
/* do minimal check that the MinGW root directory looks valid */
static void checkMingwDir(char *root)
{
int irv;
struct _stat stat_buf;
char *path, *comp, *cp;
initDynString(&path);
assign(&path,gstr.pMINGW);
appendBackSlash(&path);
append(&path,"bin\\");
/* Get just the compiler name (the first word) */
comp = strdup(IVERILOG_VPI_CC);
cp = strchr(comp, ' ');
if (cp != NULL) *cp = '\0';
append(&path, comp);
append(&path,".exe");
free(comp);
irv = _stat(path,&stat_buf);
deInitDynString(path);
if (irv) {
fprintf(stderr,"error: %s does not appear to be the valid root directory\n",root);
fprintf(stderr," of MinGW. Use the -mingw option of iverilog-vpi.exe to\n");
fprintf(stderr," point to the MinGW root directory. For a Windows command\n");
fprintf(stderr," shell the option would be something like -mingw=c:\\mingw\n");
fprintf(stderr," For a Cygwin shell the option would be something like\n");
fprintf(stderr," -mingw=c:\\\\mingw\n");
myExit(5);
}
}
/* do minimal check that the Icarus Verilog root directory looks valid */
static void checkIvlDir(char *root)
{
int irv;
struct _stat stat_buf;
char *path;
initDynString(&path);
assign(&path,gstr.pIVL);
appendBackSlash(&path);
append(&path,"bin\\vvp" IVERILOG_SUFFIX ".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," 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");
fprintf(stderr," -ivl=c:\\\\iverilog\n");
myExit(6);
}
}
/* see if we can find mingw root */
#define IVL_REGKEY_MINGW "MingwDir"
static void setup_mingw_environment()
{
char *pOldPATH = getenv("PATH"); /* get current path */
if (*gstr.pMINGW) {
checkMingwDir(gstr.pMINGW);
SetRegistryKey(IVL_REGKEY_MINGW,gstr.pMINGW);
} else if (!GetRegistryKey(IVL_REGKEY_MINGW,&gstr.pMINGW)) {
fprintf(stderr,"error: can not locate the MinGW root directory, use the -mingw option of\n");
fprintf(stderr," iverilog-vpi.exe to point to the MinGW root directory. For\n");
fprintf(stderr," a Windows command shell the option would be something like\n");
fprintf(stderr," -mingw=c:\\mingw For a Cygwin shell the option would be\n");
fprintf(stderr," something like -mingw=c:\\\\mingw\n");
myExit(5);
}
/* Create new path with MinGW in it */
assign(&gstr.pNewPath,"PATH=");
append(&gstr.pNewPath,gstr.pMINGW);
appendBackSlash(&gstr.pNewPath);
append(&gstr.pNewPath, "\\");
append(&gstr.pNewPath,"bin;");
append(&gstr.pNewPath,pOldPATH);
/* Place new path in environment */
_putenv(gstr.pNewPath);
}
/* see if we can find iverilog root */
#define IVL_REGKEY_IVL "InstallDir"
static void setup_ivl_environment()
{
if (*gstr.pIVL) {
checkIvlDir(gstr.pIVL);
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," 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");
myExit(6);
}
/* Build up the CFLAGS option string */
assign(&gstr.pCFLAGS,IVERILOG_VPI_CFLAGS " -I\"");
append(&gstr.pCFLAGS,gstr.pIVL);
appendBackSlash(&gstr.pCFLAGS);
append(&gstr.pCFLAGS,"\\include\\\\iverilog\"" IVERILOG_SUFFIX);
/* 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);
}
/* compile source modules */
static void compile(char *pSource, char **pObject, int *compile_errors, char *compiler)
{
char *ptr1 = pSource;
char *ptr2 = strchr(ptr1, ' ');
char *buf=0, *src=0, *obj=0;
while (ptr2) {
int len = ptr2 - ptr1;
char *ostart;
int olen;
assignn(&src, ptr1, len);
/* Build the object file name */
ostart = strrchr(ptr1, '/');
if (ostart == NULL) ostart = ptr1;
else ostart += 1;
olen = strrchr(ptr1, '.') - ostart;
assignn(&obj, ostart, olen);
append(&obj, ".o");
/* Build the compile line */
assign(&buf, compiler);
append(&buf, " -c -o ");
append(&buf, obj);
append(&buf, " ");
append(&buf, gstr.pDEFS);
append(&buf, " ");
append(&buf, gstr.pCFLAGS);
append(&buf, " ");
append(&buf, gstr.pINCS);
append(&buf, " ");
append(&buf, src);
append (pObject, " ");
append (pObject, obj);
printf("Compiling %s...\n", src);
if (system(buf)) ++*compile_errors;
/* advance to next token */
ptr1 = ptr2 + 1;
ptr2 = strchr(ptr1, ' ');
}
free(buf);
free(src);
free(obj);
}
/* using the global strings, compile and link */
static void compile_and_link()
{
char *buf=0;
int iRet, compile_errors = 0;
/* To make the output match iverilog-vpi.sh do not print out the
* root directories */
// printf("MinGW root directory: %s.\n", gstr.pMINGW);
checkMingwDir(gstr.pMINGW);
// printf("Icarus Verilog root directory: %s.\n", gstr.pIVL);
checkIvlDir(gstr.pIVL);
/* compile the C source files (*.c) */
compile(gstr.pCCSRC, &gstr.pOBJ, &compile_errors, IVERILOG_VPI_CC );
/* compile the C++ source files (*.cc, *.cpp) */
compile(gstr.pCXSRC, &gstr.pOBJ, &compile_errors, IVERILOG_VPI_CXX);
if (compile_errors) {
fprintf(stderr,"iverilog-vpi: %d file(s) failed to compile.\n",
compile_errors);
myExit(2);
}
/* link */
assign(&buf, gstr.pLD);
append(&buf, " -o ");
append(&buf, gstr.pOUT);
append(&buf, " ");
append(&buf, IVERILOG_VPI_LDFLAGS);
append(&buf, " ");
append(&buf, gstr.pOBJ);
append(&buf, " ");
append(&buf, gstr.pLIB);
append(&buf, " ");
append(&buf, gstr.pLDLIBS);
printf("Making %s from %s...\n", gstr.pOUT,gstr.pOBJ);
iRet = system(buf);
free(buf);
if (iRet) myExit(3);
}
/* program execution starts here */
int main(int argc, char *argv[])
{
init();
if (!parse(argc,argv)) usage();
setup_mingw_environment();
setup_ivl_environment();
/* are there any source or object files specified */
if (*gstr.pOUT) compile_and_link();
myExit(0);
return 0; // eliminate warnings.
}
-38
View File
@@ -1,38 +0,0 @@
// LANGUAGE ENGLISH
LANGUAGE 9, 4
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
1 VERSIONINFO
FILEVERSION 2002,11,13,0
PRODUCTVERSION @PRODUCTVERSION@
FILEFLAGSMASK 0x3fL
FILEFLAGS 0x2L
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Icarus Verilog\0"
VALUE "FileDescription", "Icarus Verilog VPI Tool\0"
VALUE "FileVersion", "2002, 11, 13, 0\0"
VALUE "InternalName", "iverilog-vpi\0"
VALUE "LegalCopyright", "Copyright 2002 Gus Baldauf\0"
VALUE "OriginalFilename", "iverilog-vpi.exe\0"
VALUE "ProductName", "Icarus Verilog\0"
VALUE "ProductVersion", "@PRODUCTVERSION@\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
-145
View File
@@ -1,145 +0,0 @@
#
# This source code is free software; you can redistribute it
# and/or modify it in source code form under the terms of the GNU
# Library General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc.,
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
SHELL = /bin/sh
suffix = @install_suffix@
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
datarootdir = @datarootdir@
VPATH = $(srcdir)
bindir = $(exec_prefix)/bin
libdir = $(exec_prefix)/lib
includedir = $(prefix)/include
mandir = @mandir@
dllib=@DLLIB@
CC = @CC@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
LEX = @LEX@
YACC = @YACC@
MAN = @MAN@
PS2PDF = @PS2PDF@
ifeq (@srcdir@,.)
INCLUDE_PATH = -I. -I..
else
INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/..
endif
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
LDFLAGS = @LDFLAGS@
O = main.o substit.o cflexor.o cfparse.o
all: dep iverilog@EXEEXT@ iverilog.man
check: all
clean:
rm -f *.o cflexor.c cfparse.c cfparse.h cfparse.output
rm -f iverilog@EXEEXT@ iverilog.man iverilog.pdf iverilog.ps
rm -rf dep
distclean: clean
rm -f Makefile config.log
cppcheck: $(O:.o=.c)
cppcheck --enable=all -f $(INCLUDE_PATH) $^
Makefile: $(srcdir)/Makefile.in ../config.status
cd ..; ./config.status --file=driver/$@
dep:
mkdir dep
iverilog@EXEEXT@: $O
$(CC) $(LDFLAGS) $O -o iverilog@EXEEXT@ @EXTRALIBS@
cflexor.c: $(srcdir)/cflexor.lex
$(LEX) -s -t $< > $@
# Build this in two steps to avoid parallel build issues (see pr3462585)
cfparse.c: $(srcdir)/cfparse.y
$(YACC) --verbose -t -p cf -d -o $@ $<
cfparse.h: cfparse.c
%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o
mv $*.d dep
main.o: main.c globals.h $(srcdir)/../version_base.h ../version_tag.h Makefile
$(CC) $(CPPFLAGS) $(CFLAGS) @DEPENDENCY_FLAG@ -c -DIVL_ROOT='"@libdir@/ivl$(suffix)"' -DIVL_SUFFIX='"$(suffix)"' -DIVL_INC='"@includedir@"' -DIVL_LIB='"@libdir@"' -DDLLIB='"@DLLIB@"' $(srcdir)/main.c
mv $*.d dep
cflexor.o: cflexor.c cfparse.h
iverilog.man: $(srcdir)/iverilog.man.in ../version.exe
../version.exe `head -1 $(srcdir)/iverilog.man.in`'\n' > $@
tail -n +2 $(srcdir)/iverilog.man.in >> $@
iverilog.ps: iverilog.man
$(MAN) -t ./iverilog.man > iverilog.ps
iverilog.pdf: iverilog.ps
$(PS2PDF) iverilog.ps iverilog.pdf
ifeq (@MINGW32@,yes)
ifeq ($(MAN),none)
INSTALL_DOC = $(mandir)/man1/iverilog$(suffix).1
else
ifeq ($(PS2PDF),none)
INSTALL_DOC = $(mandir)/man1/iverilog$(suffix).1
else
INSTALL_DOC = $(prefix)/iverilog$(suffix).pdf $(mandir)/man1/iverilog$(suffix).1
all: iverilog.pdf
endif
endif
INSTALL_DOCDIR = $(mandir)/man1
else
INSTALL_DOC = $(mandir)/man1/iverilog$(suffix).1
INSTALL_DOCDIR = $(mandir)/man1
endif
install: all installdirs $(bindir)/iverilog$(suffix)@EXEEXT@ $(INSTALL_DOC)
$(bindir)/iverilog$(suffix)@EXEEXT@: ./iverilog@EXEEXT@
$(INSTALL_PROGRAM) ./iverilog@EXEEXT@ "$(DESTDIR)$(bindir)/iverilog$(suffix)@EXEEXT@"
$(mandir)/man1/iverilog$(suffix).1: iverilog.man
$(INSTALL_DATA) iverilog.man "$(DESTDIR)$(mandir)/man1/iverilog$(suffix).1"
$(prefix)/iverilog$(suffix).pdf: iverilog.pdf
$(INSTALL_DATA) iverilog.pdf "$(DESTDIR)$(prefix)/iverilog$(suffix).pdf"
installdirs: $(srcdir)/../mkinstalldirs
$(srcdir)/../mkinstalldirs "$(DESTDIR)$(bindir)" "$(DESTDIR)$(INSTALL_DOCDIR)"
uninstall:
rm -f "$(DESTDIR)$(bindir)/iverilog$(suffix)@EXEEXT@"
rm -f "$(DESTDIR)$(mandir)/man1/iverilog$(suffix).1" "$(DESTDIR)$(prefix)/iverilog$(suffix).pdf"
-include $(patsubst %.o, dep/%.d, $O)
-257
View File
@@ -1,257 +0,0 @@
%option prefix="cf"
%option nounput
%option noinput
%{
/*
* Copyright (c) 2001-2009 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 "cfparse.h"
# include "cfparse_misc.h"
# include "globals.h"
# include <string.h>
static int comment_enter;
static char* trim_trailing_white(char*txt, int trim);
/*
* Mostly copied from the flex manual. Do not make this arbitrary
* depth without checking for looping files.
*/
#define MAX_CMDFILE_DEPTH 15
typedef struct t_cmdfile {
char *cmdfile;
YY_BUFFER_STATE buffer;
} s_cmdfile;
s_cmdfile cmdfile_stack[MAX_CMDFILE_DEPTH];
int cmdfile_stack_ptr = 0;
%}
%x CCOMMENT
%x LCOMMENT
%x PLUS_ARGS
%x FILE_NAME
%%
/* Accept C++ style comments. */
"//".* { comment_enter = YY_START; BEGIN(LCOMMENT); }
<LCOMMENT>. { yymore(); }
<LCOMMENT>\n { cflloc.first_line += 1; BEGIN(comment_enter); }
/* Accept C style comments. */
"/*" { comment_enter = YY_START; BEGIN(CCOMMENT); }
<CCOMMENT>. { yymore(); }
<CCOMMENT>\n { cflloc.first_line += 1; yymore(); }
<CCOMMENT>"*/" { BEGIN(comment_enter); }
/* Accept shell type comments. */
^"#".* { ; }
/* Skip white space. */
[ \t\f\r] { ; }
/* Skip line ends, but also count the line. */
\n { cflloc.first_line += 1; }
"+define+" { BEGIN(PLUS_ARGS); return TOK_DEFINE; }
"+incdir+" { BEGIN(PLUS_ARGS); return TOK_INCDIR; }
"+integer-width+" { BEGIN(PLUS_ARGS); return TOK_INTEGER_WIDTH; }
"+libdir+" { BEGIN(PLUS_ARGS); return TOK_LIBDIR; }
"+libdir-nocase+" { BEGIN(PLUS_ARGS); return TOK_LIBDIR_NOCASE; }
"+libext+" { BEGIN(PLUS_ARGS); return TOK_LIBEXT; }
"+parameter+" { BEGIN(PLUS_ARGS); return TOK_PARAMETER; }
"+timescale+" { BEGIN(PLUS_ARGS); return TOK_TIMESCALE; }
"+vhdl-work+" { BEGIN(PLUS_ARGS); return TOK_VHDL_WORK; }
"+vhdl-libdir+" { BEGIN(PLUS_ARGS); return TOK_VHDL_LIBDIR; }
/* If it is not any known plus-flag, return the generic form. */
"+"[^\n \t\b\f\r+]* {
cflval.text = strdup(yytext);
BEGIN(PLUS_ARGS);
return TOK_PLUSWORD; }
/* Once in PLUS_ARGS mode, words are delimited by +
characters. White space and line end terminate PLUS_ARGS mode,
but + terminates only the word. */
<PLUS_ARGS>[^\n \t\b\f\r+]* {
cflval.text = strdup(yytext);
return TOK_PLUSARG; }
/* Within plusargs, this is a delimiter. */
<PLUS_ARGS>"+" { }
/* White space end plus_args mode. */
<PLUS_ARGS>[ \t\b\f\r] { BEGIN(0); }
<PLUS_ARGS>\n {
cflloc.first_line += 1;
BEGIN(0); }
/* Notice the -a flag. */
"-a" { return TOK_Da; }
/* Notice the -c or -f flag. */
"-c" { return TOK_Dc; }
"-f" { return TOK_Dc; }
/* Notice the -v flag. */
"-v" { return TOK_Dv; }
/* Notice the -y flag. */
"-y" { return TOK_Dy; }
/* This rule matches paths and strings that may be file names. This
is a little bit tricky, as we don't want to mistake a comment for
a string word. */
"/"[\r\n] { /* Special case of file name "/" */
cflval.text = trim_trailing_white(yytext, 0);
return TOK_STRING; }
"/"[^\*\/] { /* A file name that starts with "/". */
yymore();
BEGIN(FILE_NAME); }
[^/\n \t\b\r+-][^/\n\r]* { /* A file name that starts with other than "/" */
yymore();
BEGIN(FILE_NAME); }
<FILE_NAME>"//" {
/* Found a trailing comment. Returning the terminated name. */
cflval.text = trim_trailing_white(yytext, 2);
BEGIN(LCOMMENT);
return TOK_STRING; }
<FILE_NAME>"/"?[^/\n\r]* {
yymore();
/* not a comment... continuing */; }
<FILE_NAME>[\n\r] {
/* No trailing comment. Return the file name. */
cflval.text = trim_trailing_white(yytext, 0);
BEGIN(0);
return TOK_STRING; }
/* Fallback match. */
. { return yytext[0]; }
/* At the end of file switch back to the previous buffer. */
<<EOF>> {
if (--cmdfile_stack_ptr < 0) {
free(current_file);
yyterminate();
} else {
yy_delete_buffer(YY_CURRENT_BUFFER);
yy_switch_to_buffer(cmdfile_stack[cmdfile_stack_ptr].buffer);
free(current_file);
current_file = cmdfile_stack[cmdfile_stack_ptr].cmdfile;
} }
%%
static char* trim_trailing_white(char*text, int trim)
{
char*cp = text + strlen(text);
while (cp > text && trim > 0) {
trim -= 1;
cp -= 1;
*cp = 0;
}
while (cp > text && strchr("\n\r\t\b", cp[-1]))
cp -= 1;
cp[0] = 0;
return strdup(text);
}
int yywrap()
{
return 1;
}
void switch_to_command_file(const char *file)
{
char path[4096];
char *cp;
if (cmdfile_stack_ptr >= MAX_CMDFILE_DEPTH) {
fprintf(stderr, "Error: command files nested too deeply (%d) "
"at %s:%d.\n", MAX_CMDFILE_DEPTH, current_file,
cflloc.first_line);
exit(1);
}
cmdfile_stack[cmdfile_stack_ptr].buffer = YY_CURRENT_BUFFER;
cmdfile_stack[cmdfile_stack_ptr].cmdfile = current_file;
cmdfile_stack_ptr += 1;
/*
* If this is a relative file then add the current path to the
* file name.
*/
if (file[0] != '/') {
strcpy(path, current_file);
cp = strrchr(path, '/');
if (cp == 0) strcpy(path, file); /* A base file. */
else {
*(cp+1) = '\0';
strcat(path, file);
}
} else strcpy(path, file); /* An absolute path. */
yyin = fopen(path, "r");
if (yyin == NULL) {
fprintf(stderr, "Error: unable to read nested command file (%s) "
"at %s:%d.\n", path, current_file, cflloc.first_line);
exit(1);
}
current_file = strdup(path);
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
cflloc.first_line = 1;
}
void cfreset(FILE*fd, const char*path)
{
yyin = fd;
yyrestart(fd);
current_file = strdup(path);
cflloc.first_line = 1;
}
/*
* 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
}
-266
View File
@@ -1,266 +0,0 @@
%{
/*
* Copyright (c) 2001-2011 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* 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 "globals.h"
# include "cfparse_misc.h"
# include <ctype.h>
# include <stdlib.h>
# include <stdio.h>
# include <string.h>
# include "ivl_alloc.h"
/*
* This flag is set to 0, 1 or 2 if file names are to be translated to
* uppercase(1) or lowercase(2).
*/
static int setcase_filename_flag = 0;
static void translate_file_name(char*text)
{
switch (setcase_filename_flag) {
case 0:
break;
case 1:
while (*text) {
*text = toupper((int)*text);
text += 1;
}
break;
case 2:
while (*text) {
*text = tolower((int)*text);
text += 1;
}
break;
}
}
%}
%union {
char*text;
};
%token TOK_Da TOK_Dc TOK_Dv TOK_Dy
%token TOK_DEFINE TOK_INCDIR TOK_INTEGER_WIDTH TOK_LIBDIR TOK_LIBDIR_NOCASE
%token TOK_LIBEXT TOK_PARAMETER TOK_TIMESCALE TOK_VHDL_WORK TOK_VHDL_LIBDIR
%token <text> TOK_PLUSARG TOK_PLUSWORD TOK_STRING
%%
start
:
| item_list
;
item_list
: item_list item
| item
;
item
/* Absent any other matching, a token string is taken to be the name
of a source file. Add the file to the file list. */
: TOK_STRING
{ char*tmp = substitutions($1);
translate_file_name(tmp);
process_file_name(tmp, 0);
free($1);
free(tmp);
}
/* The -a flag is completely ignored. */
| TOK_Da { }
/* Match a -c <cmdfile> or -f <cmdfile> */
| TOK_Dc TOK_STRING
{ char*tmp = substitutions($2);
translate_file_name(tmp);
switch_to_command_file(tmp);
free($2);
free(tmp);
}
/* The -v <libfile> flag is ignored, and the <libfile> is processed
as an ordinary source file. */
| TOK_Dv TOK_STRING
{ char*tmp = substitutions($2);
translate_file_name(tmp);
process_file_name(tmp, 1);
free($2);
free(tmp);
}
/* This rule matches "-y <path>" sequences. This does the same thing
as -y on the command line, so add the path to the library
directory list. */
| TOK_Dy TOK_STRING
{ char*tmp = substitutions($2);
process_library_switch(tmp);
free($2);
free(tmp);
}
| TOK_LIBDIR TOK_PLUSARG
{ char*tmp = substitutions($2);
process_library_switch(tmp);
free($2);
free(tmp);
}
| TOK_LIBDIR_NOCASE TOK_PLUSARG
{ char*tmp = substitutions($2);
process_library_nocase_switch(tmp);
free($2);
free(tmp);
}
| TOK_PARAMETER TOK_PLUSARG
{ char*tmp = substitutions($2);
process_parameter(tmp);
free($2);
free(tmp);
}
/* The +timescale token is used to set the default timescale for
the simulator. */
| TOK_TIMESCALE TOK_PLUSARG
{ char*tmp = substitutions($2);
process_timescale(tmp);
free($2);
free(tmp);
}
| TOK_DEFINE TOK_PLUSARG
{ process_define($2);
free($2);
}
| TOK_VHDL_WORK TOK_PLUSARG
{ char*tmp = substitutions($2);
vhdlpp_work = tmp;
free($2);
}
| TOK_VHDL_LIBDIR TOK_PLUSARG
{ char*tmp = substitutions($2);
vhdlpp_libdir = realloc(vhdlpp_libdir, (vhdlpp_libdir_cnt+1)*sizeof(char*));
vhdlpp_libdir[vhdlpp_libdir_cnt] = tmp;
vhdlpp_libdir_cnt += 1;
free($2);
}
/* The +incdir token introduces a list of +<path> arguments that are
the include directories to search. */
| TOK_INCDIR inc_args
/* The +libext token introduces a list of +<ext> arguments that
become individual -Y flags to ivl. */
| TOK_LIBEXT libext_args
/* These are various misc flags that are supported. */
| TOK_INTEGER_WIDTH TOK_PLUSARG
{ char*tmp = substitutions($2);
free($2);
integer_width = strtoul(tmp,0,10);
free(tmp);
}
/* The +<word> tokens that are not otherwise matched, are
ignored. The skip_args rule arranges for all the argument words
to be consumed. */
| TOK_PLUSWORD skip_args
{ fprintf(stderr, "%s:%u: Ignoring %s\n",
@1.text, @1.first_line, $1);
free($1);
}
| TOK_PLUSWORD
{ if (strcmp($1, "+toupper-filenames") == 0) {
setcase_filename_flag = 1;
} else if (strcmp($1, "+tolower-filenames") == 0) {
setcase_filename_flag = 2;
} else {
fprintf(stderr, "%s:%u: Ignoring %s\n",
@1.text, @1.first_line, $1);
}
free($1);
}
| error
{ fprintf(stderr, "Error: unable to parse line %d in "
"%s.\n", cflloc.first_line, current_file);
return 1;
}
;
/* inc_args are +incdir+ arguments in order. */
inc_args
: inc_args inc_arg
| inc_arg
;
inc_arg : TOK_PLUSARG
{ char*tmp = substitutions($1);
process_include_dir(tmp);
free($1);
free(tmp);
}
;
/* inc_args are +incdir+ arguments in order. */
libext_args
: libext_args libext_arg
| libext_arg
;
libext_arg : TOK_PLUSARG
{ process_library2_switch($1);
free($1);
}
;
/* skip_args are arguments to a +word flag that is not otherwise
parsed. This rule matches them and releases the strings, so that
they can be safely ignored. */
skip_args
: skip_args skip_arg
| skip_arg
;
skip_arg : TOK_PLUSARG
{ free($1);
}
;
%%
int yyerror(const char*msg)
{
return 0;
}
-44
View File
@@ -1,44 +0,0 @@
#ifndef __cfparse_misc_H
#define __cfparse_misc_H
/*
* Copyright (c) 2001-2009 Picture Elements, Inc.
* 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
*/
/*
* The vlltype supports the passing of detailed source file location
* information between the lexical analyzer and the parser. Defining
* YYLTYPE compels the lexor to use this type and not something other.
*/
struct cfltype {
unsigned first_line;
unsigned first_column;
unsigned last_line;
unsigned last_column;
const char*text;
};
# define YYLTYPE struct cfltype
int cflex(void);
int cferror(const char *);
int cfparse(void);
void switch_to_command_file(const char *);
void destroy_lexor();
char *current_file;
#endif
-54
View File
@@ -1,54 +0,0 @@
#ifndef __globals_H
#define __globals_H
/*
* Copyright (c) 2000-2009 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 <stddef.h>
/* This is the integer-width argument that will be passed to ivl. */
extern unsigned integer_width;
extern const char*vhdlpp_work;
extern const char**vhdlpp_libdir;
extern unsigned vhdlpp_libdir_cnt;
/* Perform variable substitutions on the string. */
extern char* substitutions(const char*str);
/* Add the name to the list of source files. */
extern void process_file_name(const char*name, int lib_flag);
/* Add the name to the list of library directories. */
extern void process_library_switch(const char*name);
extern void process_library_nocase_switch(const char*name);
extern void process_library2_switch(const char*name);
/* Add a new include file search directory */
extern void process_include_dir(const char*name);
/* Add a new -D define. */
extern void process_define(const char*name);
/* Add a new parameter definition */
extern void process_parameter(const char*name);
/* Set the default timescale for the simulator. */
extern void process_timescale(const char*ts_string);
#endif
-518
View File
@@ -1,518 +0,0 @@
.TH iverilog 1 "February 27th, 2011" "" "Version %M.%m.%n %E"
.SH NAME
iverilog - Icarus Verilog compiler
.SH SYNOPSIS
.B iverilog
[\-ESVv] [\-Bpath] [\-ccmdfile|\-fcmdfile] [\-Dmacro[=defn]]
[\-Pparameter=value] [\-pflag=value]
[\-dname] [\-g1995|\-g2001|\-g2005|\-g2005-sv|\-g2009|\-g<feature>]
[\-Iincludedir] [\-mmodule] [\-M[mode=]file] [\-Nfile] [\-ooutputfilename]
[\-stopmodule] [\-ttype] [\-Tmin/typ/max] [\-Wclass] [\-ypath] sourcefile
.SH DESCRIPTION
.PP
\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
types are added as code generators are implemented.
.SH OPTIONS
\fIiverilog\fP accepts the following options:
.TP 8
.B -B\fIbase\fP
The \fIiverilog\fP program uses external programs and configuration
files to preprocess and compile the Verilog source. Normally, the path
used to locate these tools is built into the \fIiverilog\fP
program. However, the \fB\-B\fP switch allows the user to select a
different set of programs. The path given is used to locate
\fIivlpp\fP, \fIivl\fP, code generators and the VPI modules.
.TP 8
.B -c\fIfile\fP -f\fIfile\fP
These flags specifies an input file that contains a list of Verilog
source files. This is similar to the \fIcommand file\fP of other
Verilog simulators, in that it is a file that contains the file names
instead of taking them on the command line. See \fBCommand Files\fP below.
.TP 8
.B -D\fImacro\fP
Defines macro \fImacro\fP with the string `1' as its definition. This
form is normally only used to trigger ifdef conditionals in the
Verilog source.
.TP 8
.B -D\fImacro=defn\fP
Defines macro \fImacro\fP as \fIdefn\fP.
.TP 8
.B -P\fIparameter=value\fP
Override (i.e. defparam) a parameter in a root module. This allows the
user to override at compile time (defparam) a parameter in a root
module instance. For example, \fB\-Pmain.foo=2\fP overrides the
parameter foo in the root instance main with the value 2.
.TP 8
.B -d\fIname\fP
Activate a class of compiler debugging messages. The \fB\-d\fP switch may
be used as often as necessary to activate all the desired messages.
Supported names are scopes, eval_tree, elaborate, and synth2;
any other names are ignored.
.TP 8
.B -E
Preprocess the Verilog source, but do not compile it. The output file
is the Verilog input, but with file inclusions and macro references
expanded and removed. This is useful, for example, to preprocess
Verilog source for use by other compilers.
.TP 8
.B -g1995\fI|\fP-g2001\fI|\fP-g2001-noconfig\fI|\fP-g2005\fI|\fP-g2005-sv\fI|\fP-g2009
Select the Verilog language \fIgeneration\fP to support in the compiler.
This selects between \fIIEEE1364\-1995\fP, \fIIEEE1364\-2001\fP,
\fIIEEE1364\-2005\fP, \fIIEEE1800\-2005\fP, or \fIIEEE1800\-2009\fP.
Icarus Verilog currently defaults to the \fIIEEE1364\-2005\fP generation
of the language. This flag is used to restrict the language to a set of
keywords/features, this allows simulation of older Verilog code that may
use newer keywords and for compatibility with other tools. Much of the
\fIIEEE1800\fP generations functionality is not currently supported.
The \fIIEEE1800\fP generations do parse all the keywords, so they can
be used to verify that \fIIEEE1364\fP compliant Verilog code does not
use any of the new \fIIEEE1800\fP keywords.
.TP 8
.B -gverilog-ams\fI|\fP-gno-verilog-ams
Enable or disable (default) support for Verilog\-AMS.
Very little Verilog\-AMS specific functionality is currently supported.
.TP 8
.B -gspecify\fI|\fP-gno-specify
Enable or disable (default) specify block support. When enabled,
specify block code is elaborated. When disabled, specify blocks are
parsed but ignored. Specify blocks are commonly not needed for RTL
simulation, and in fact can hurt performance of the
simulation. However, disabling specify blocks reduces accuracy of
full-timing simulations.
.TP 8
.B -gstd-include\fI|\fP-gno-std-include
Enable (default) or disable the search of a standard installation
include directory after all other explicit include directories. This
standard include directory is a convenient place to install standard
header files that a Verilog program may include.
.TP 8
.B -grelative-include\fI|\fP-gno-relative-include
Enable or disable (default) adding the local files directory to
the beginning of the include file search path. This allows files
to be included relative to the current file not the more common
files are only found in the working directory or in the specified
include file search path.
.TP 8
.B -gxtypes\fI|\fP-gno-xtypes
Enable (default) or disable support for extended types. Enabling
extended types allows for new types that are supported by Icarus
Verilog as extensions beyond the baseline Verilog. It may be necessary
to disable extended types if compiling code that clashes with the few
new keywords used to implement the type system.
.TP 8
.B -gio-range-error\fI|\fP-gno-io-range-error
The standards requires that a vectored port have matching ranges for its
port declaration as well as any net/register declaration. It was common
practice in the past to only specify the range for the net/register
declaration and some tools still allow this. By default any mismatch is
reported as a error. Using \fB\-gno\-io\-range\-error\fP will produce a
warning instead of a fatal error for the case of a vectored net/register
and a scalar port declaration.
.TP 8
.B -gstrict-ca-eval\fI|\fP-gno-strict-ca-eval
The standard requires that if any input to a continuous assignment
expression changes value, the entire expression is re-evaluated. By
default, parts of the expression that do not depend on the changed
input value(s) are not re-evaluated. If an expression contains a call
to a function that doesn't depend solely on its input values or that
has side effects, the resulting behavior will differ from that
required by the standard. Using \fI\-gstrict\-ca\-eval\fP will force
standard compliant behavior (with some loss in performance).
.TP 8
.B -gstrict-expr-width\fI|\fP-gno-strict-expr-width
Enable or disable (default) strict compliance with the standard rules
for determining expression bit lengths. When disabled, the RHS of a
parameter assignment is evaluated as a lossless expression.
.TP 8
.B -I\fIincludedir\fP
Append directory \fIincludedir\fP to list of directories searched
for Verilog include files. The \fB\-I\fP switch may be used many times
to specify several directories to search, the directories are searched
in the order they appear on the command line.
.TP 8
.B -M\fIpath\fP
This is equivalent to \fB\-Mall=path\fP. Preserved for backwards
compatibility.
.TP 8
.B -M\fImode=path\fP
Write into the file specified by path a list of files that contribute to
the compilation of the design. If \fBmode\fP is \fBall\fP or \fBprefix\fP,
this includes files that are included by include directives and files
that are automatically loaded by library support as well as the files
explicitly specified by the user. If \fBmode\fP is \fBinclude\fP, only
files that are included by include directives are listed. If \fBmode\fP
is \fBmodule\fP, only files that are specified by the user or that are
automatically loaded by library support are listed. The output is one
file name per line, with no leading or trailing space. If \fBmode\fP
is \fBprefix\fP, files that are included by include directives are
prefixed by "I " and other files are prefixed by "M ".
.TP 8
.B -m\fImodule\fP
Add this module to the list of VPI modules to be loaded by the
simulation. Many modules can be specified, and all will be loaded, in
the order specified. The system module is implicit and always included.
If a System Function Table file (<module>.sft) exists for the module it
will be loaded automatically.
.TP 8
.B -N\fIpath\fP
This is used for debugging the compiler proper. Dump the final netlist
form of the design to the specified file. It otherwise does not affect
operation of the compiler. The dump happens after the design is
elaborated and optimized.
.TP 8
.B -o \fIfilename\fP
Place output in the file \fIfilename\fP. If no output file name is
specified, \fIiverilog\fP uses the default name \fBa.out\fP.
.TP 8
.B -p\fIflag=value\fP
Assign a value to a target specific flag. The \fB\-p\fP switch may be
used as often as necessary to specify all the desired flags. The flags
that are used depend on the target that is selected, and are described
in target specific documentation. Flags that are not used are ignored.
.TP 8
.B -S
Synthesize. Normally, if the target can accept behavioral
descriptions the compiler will leave processes in behavioral
form. The \fB\-S\fP switch causes the compiler to perform synthesis
even if it is not necessary for the target. If the target type is a
netlist format, the \fB\-S\fP switch is unnecessary and has no effect.
.TP 8
.B -s \fItopmodule\fP
Specify the top level module to elaborate. Icarus Verilog will by default
choose modules that are not instantiated in any other modules, but
sometimes that is not sufficient, or instantiates too many modules. If
the user specifies one or more root modules with \fB\-s\fP flags, then
they will be used as root modules instead.
.TP 8
.B -T\fImin|typ|max\fP
Use this switch to select min, typ or max times from min:typ:max
expressions. Normally, the compiler will simply use the typ value from
these expressions (printing a warning for the first ten it finds) but
this switch will tell the compiler explicitly which value to use. This
will suppress the warning that the compiler is making a choice.
.TP 8
.B -t\fItarget\fP
Use this switch to specify the target output format. See the
\fBTARGETS\fP section below for a list of valid output formats.
.TP 8
.B -v
Turn on verbose messages. This will print the command lines that are
executed to perform the actual compilation, along with version
information from the various components, as well as the version of the
product as a whole. You will notice that the command lines include
a reference to a key temporary file that passes information to the
compiler proper. To keep that file from being deleted at the end
of the process, provide a file name of your own in the environment
variable \fBIVERILOG_ICONFIG\fP.
.TP 8
.B -V
Print the version of the compiler, and exit.
.TP 8
.B -W\fIclass\fP
Turn on different classes of warnings. See the \fBWARNING TYPES\fP
section below for descriptions of the different warning groups. If
multiple \fB\-W\fP switches are used, the warning set is the union of
all the requested classes.
.TP 8
.B -y\fIlibdir\fP
Append the directory to the library module search path. When the
compiler finds an undefined module, it looks in these directories for
files with the right name.
.TP 8
.B -Y\fIsuffix\fP
Add suffix to the list of accepted file name suffixes used when
searching a library for cells. The list defaults to the single
entry \fI.v\fP.
.SH MODULE LIBRARIES
The Icarus Verilog compiler supports module libraries as directories
that contain Verilog source files. During elaboration, the compiler
notices the instantiation of undefined module types. If the user
specifies library search directories, the compiler will search the
directory for files with the name of the missing module type. If it
finds such a file, it loads it as a Verilog source file, they tries
again to elaborate the module.
Library module files should contain only a single module, but this is
not a requirement. Library modules may reference other modules in the
library or in the main design.
.SH TARGETS
The Icarus Verilog compiler supports a variety of targets, for
different purposes, and the \fB\-t\fP switch is used to select the
desired target.
.TP 8
.B null
The null target causes no code to be generated. It is useful for
checking the syntax of the Verilog source.
.TP 8
.B vvp
This is the default. The vvp target generates code for the vvp
runtime. The output is a complete program that simulates the design
but must be run by the \fBvvp\fP command. The -pfileline=1 option
can be used to add procedural statement debugging opcodes to the
generated code.
.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
switch. All the warning types (other than \fBall\fP) can also be
prefixed with \fBno\-\fP to turn off that warning. This is most useful
after a \fB\-Wall\fP argument to suppress isolated warning types.
.TP 8
.B all
This enables the implicit, portbind, select\-range, timescale, and
sensitivity\-entire\-array warning categories.
.TP 8
.B implicit
This enables warnings for creation of implicit declarations. For
example, if a scalar wire X is used but not declared in the Verilog
source, this will print a warning at its first use.
.TP 8
.B portbind
This enables warnings for ports of module instantiations that are not
connected but probably should be. Dangling input ports, for example,
will generate a warning.
.TP 8
.B select-range
This enables warnings for constant out of bound selects. This includes
partial or fully out of bound selects as well as a select containing
a 'bx or 'bz in the index.
.TP 8
.B timescale
This enables warnings for inconsistent use of the timescale
directive. It detects if some modules have no timescale, or if modules
inherit timescale from another file. Both probably mean that
timescales are inconsistent, and simulation timing can be confusing
and dependent on compilation order.
.TP 8
.B infloop
This enables warnings for \fRalways\fP statements that may have runtime
infinite loops (has paths with no or zero delay). This class of warnings
is not included in \fB\-Wall\fP and hence does not have a \fBno\-\fP variant.
A fatal error message will always be printed when the compiler can
determine that there will definitely be an infinite loop (all paths have
no or zero delay).
When you suspect an always statement is producing a runtime infinite loop
use this flag to find the always statements that need to have their logic
verified. It is expected that many of the warnings will be false
positives, since the code treats the value of all variables and signals
as indeterminate.
.TP 8
.B sensitivity-entire-vector
This enables warnings for when a part select within an "always @*"
statement results in the entire vector being added to the implicit
sensitivity list. Although this behaviour is prescribed by the IEEE
standard, it is not what might be expected and can have performance
implications if the vector is large.
.TP 8
.B sensitivity-entire-array
This enables warnings for when a word select within an "always @*"
statement results in the entire array being added to the implicit
sensitivity list. Although this behaviour is prescribed by the IEEE
standard, it is not what might be expected and can have performance
implications if the array is large.
.SH "SYSTEM FUNCTION TABLE FILES"
If the source file name as a \fB.sft\fP suffix, then it is taken to be
a system function table file. A System function table file is used to
describe to the compiler the return types for system functions. This
is necessary because the compiler needs this information to elaborate
expressions that contain these system functions, but cannot run the
sizetf functions since it has no run-time.
The format of the table is ASCII, one function per line. Empty lines
are ignored, and lines that start with the '\fI#\fP' character are
comment lines. Each non-comment line starts with the function name,
then the vpi type (i.e. vpiSysFuncReal). The following types are
supported:
.TP 8
.B vpiSysFuncReal
The function returns a real/realtime value.
.TP 8
.B vpiSysFuncInt
The function returns an integer.
.TP 8
.B vpiSysFuncSized <wid> <signed|unsigned>
The function returns a vector with the given width, and is signed or
unsigned according to the flag.
.SH "COMMAND FILES"
The command file allows the user to place source file names and
certain command line switches into a text file instead of on a long
command line. Command files can include C or C++ style comments, as
well as # comments, if the # starts the line.
.TP 8
.I "file name"
A simple file name or file path is taken to be the name of a Verilog
source file. The path starts with the first non-white-space
character. Variables are substituted in file names.
.TP 8
.B -c\ \fIcmdfile\fP -f\ \fIcmdfile\fP
A \fB\-c\fP or \fB\-f\fP token prefixes a command file, exactly like it
does on the command line. The cmdfile may be on the same line or the
next non-comment line.
.TP 8
.B -y\ \fIlibdir\fP
A \fB\-y\fP token prefixes a library directory in the command file,
exactly like it does on the command line. The parameter to the \fB\-y\fP
flag may be on the same line or the next non-comment line.
Variables in the \fIlibdir\fP are substituted.
.TP 8
.B +incdir+\fIincludedir\fP
The \fB+incdir+\fP token in command files gives directories to search
for include files in much the same way that \fB\-I\fP flags work on the
command line. The difference is that multiple \fI+includedir\fP
directories are valid parameters to a single \fB+incdir+\fP token,
although you may also have multiple \fB+incdir+\fP lines.
Variables in the \fIincludedir\fP are substituted.
.TP 8
.B +libext+\fIext\fP
The \fB+libext\fP token in command files fives file extensions to try
when looking for a library file. This is useful in conjunction with
\fB\-y\fP flags to list suffixes to try in each directory before moving
on to the next library directory.
.TP 8
.B +libdir+\fIdir\fP
This is another way to specify library directories. See the \-y flag.
.TP 8
.B +libdir-nocase+\fIdir\fP
This is like the \fB+libdir\fP statement, but file names inside the
directories declared here are case insensitive. The missing module
name in a lookup need not match the file name case, as long as the
letters are correct. For example, "foo" matches "Foo.v" but not
"bar.v".
.TP 8
.B +define+\fINAME\fP=\fIvalue\fP
The \fB+define+\fP token is the same as the \fB\-D\fP option on the
command line. The value part of the token is optional.
.TP 8
.B +parameter+\fINAME\fP=\fIvalue\fP
The \fB+parameter+\fP token is the same as the \fB\-P\fP option on the
command line.
.TP 8
.B +timescale+\fIvalue\fP
The \fB+timescale+\fP token is used to set the default timescale for
the simulation. This is the time units and precision before any
`timescale directive or after a `resetall directive. The default is
1s/1s.
.TP 8
.B +toupper-filename
This token causes file names after this in the command file to be
translated to uppercase. This helps with situations where a directory
has passed through a DOS machine, and in the process the file names
become munged.
.TP 8
.B +tolower-filename
This is similar to the \fB+toupper\-filename\fP hack described above.
.TP 8
.B +integer-width+\fIvalue\fP
This allows the programmer to select the width for integer variables
in the Verilog source. The default is 32, the value can be any desired
integer value.
.SH "VARIABLES IN COMMAND FILES"
In certain cases, iverilog supports variables in command files. These
are strings of the form "$(\fIvarname\fP)" or "${\fIvarname\fP}", where
\fIvarname\fP is the
name of the environment variable to read. The entire string is
replaced with the contents of that variable. Variables are only
substituted in contexts that explicitly support them, including file
and directory strings.
Variable values come from the operating system environment, and not
from preprocessor defines elsewhere in the file or the command line.
.SH PREDEFINED MACROS
The following macros are predefined by the compiler:
.TP 8
.B __ICARUS__ = 1
This is always defined when compiling with Icarus Verilog.
.TP 8
.B __VAMS_ENABLE__ = 1
This is defined if Verilog\-AMS is enabled.
.SH EXAMPLES
These examples assume that you have a Verilog source file called hello.v in
the current directory
To compile hello.v to an executable file called a.out:
iverilog hello.v
To compile hello.v to an executable file called hello:
iverilog \-o hello hello.v
To compile and run explicitly using the vvp runtime:
iverilog \-ohello.vvp \-tvvp hello.v
.SH "AUTHOR"
.nf
Steve Williams ([email protected])
.SH SEE ALSO
vvp(1),
.BR "<http://www.icarus.com/eda/verilog/>"
Tips on using, debugging, and developing the compiler can be found at
.BR "<http://iverilog.wikia.com/>"
.SH COPYRIGHT
.nf
Copyright \(co 2002\-2011 Stephen Williams
This document can be freely redistributed according to the terms of the
GNU General Public License version 2.0
-1202
View File
File diff suppressed because it is too large Load Diff
-95
View File
@@ -1,95 +0,0 @@
/*
* Copyright (c) 2002-2010 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 <string.h>
# include <stdlib.h>
# include <stdio.h>
# include "ivl_alloc.h"
char* substitutions(const char*str)
{
size_t nbuf = strlen(str) + 1;
char*buf = malloc(nbuf);
char*cp = buf;
while (*str) {
if ((str[0] == '$') && ((str[1] == '(') || str[1] == '{')) {
/* If I find a $(x) or ${x} string in the source, replace
it in the destination with the contents of the
environment variable x. */
char*name;
char*value;
const char*ep = strchr(str, (str[1]=='(') ? ')' : '}');
str += 2;
name = malloc(ep-str+1);
strncpy(name, str, ep-str);
name[ep-str] = 0;
str = ep + 1;
value = getenv(name);
if (value == 0) {
fprintf(stderr, "Warning: environment variable "
"\"%s\" not found during command file "
"processing.\n", name);
free(name);
continue;
}
free(name);
if (strlen(value) >= (nbuf - (cp-buf))) {
size_t old_size = cp - buf;
nbuf = (cp - buf) + strlen(value) + 1;
buf = realloc(buf, nbuf);
cp = buf + old_size;
}
strcpy(cp, value);
cp += strlen(cp);
} else {
if ( cp == (buf + nbuf) ) {
size_t old_size = nbuf;
nbuf = old_size + 32;
buf = realloc(buf, nbuf);
cp = buf + old_size;
}
*cp++ = *str++;
}
}
/* Add the trailing nul to the string, and reallocate the
buffer to be a tight fit. */
if ( cp == (buf + nbuf) ) {
size_t old_size = nbuf;
nbuf = old_size + 1;
buf = realloc(buf, nbuf);
buf[old_size] = 0;
} else {
*cp++ = 0;
nbuf = cp - buf;
buf = realloc(buf, nbuf);
}
return buf;
}
+11 -253
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2011 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -16,265 +16,23 @@
* 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"
#if !defined(WINNT)
#ident "$Id: dup_expr.cc,v 1.1 1999/11/27 19:07:57 steve Exp $"
#endif
# include "netlist.h"
# include <cassert>
# include <cstdlib>
# 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;
}
NetEBinary* NetEBinary::dup_expr() const
{
ivl_assert(*this, 0);
return 0;
}
NetEBAdd* NetEBAdd::dup_expr() const
{
NetEBAdd*tmp = new NetEBAdd(op_, left_->dup_expr(), right_->dup_expr(),
expr_width(), has_sign());
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetEBBits* NetEBBits::dup_expr() const
{
NetEBBits*tmp = new NetEBBits(op_, left_->dup_expr(), right_->dup_expr(),
expr_width(), has_sign());
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetEBComp* NetEBComp::dup_expr() const
{
NetEBComp*tmp = new NetEBComp(op_, left_->dup_expr(), right_->dup_expr());
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetEBDiv* NetEBDiv::dup_expr() const
{
NetEBDiv*tmp = new NetEBDiv(op_, left_->dup_expr(), right_->dup_expr(),
expr_width(), has_sign());
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetEBLogic* NetEBLogic::dup_expr() const
{
NetEBLogic*tmp = new NetEBLogic(op_, left_->dup_expr(), right_->dup_expr());
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetEBMult* NetEBMult::dup_expr() const
{
NetEBMult*tmp = new NetEBMult(op_, left_->dup_expr(), right_->dup_expr(),
expr_width(), has_sign());
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetEBPow* NetEBPow::dup_expr() const
{
NetEBPow*tmp = new NetEBPow(op_, left_->dup_expr(), right_->dup_expr(),
expr_width(), has_sign());
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetEBShift* NetEBShift::dup_expr() const
{
NetEBShift*tmp = new NetEBShift(op_, left_->dup_expr(), right_->dup_expr(),
expr_width(), has_sign());
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetEConcat* NetEConcat::dup_expr() const
{
NetEConcat*dup = new NetEConcat(parms_.count(), repeat_);
ivl_assert(*this, dup);
dup->set_line(*this);
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
if (parms_[idx]) {
NetExpr*tmp = parms_[idx]->dup_expr();
ivl_assert(*this, tmp);
dup->parms_[idx] = tmp;
}
dup->expr_width(expr_width());
return dup;
}
NetEConst* NetEConst::dup_expr() const
{
NetEConst*tmp = new NetEConst(value_);
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetEConstEnum* NetEConstEnum::dup_expr() const
{
NetEConstEnum*tmp = new NetEConstEnum(scope_, name_, enum_set_, value());
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetEConstParam* NetEConstParam::dup_expr() const
{
NetEConstParam*tmp = new NetEConstParam(scope_, name_, value());
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetECReal* NetECReal::dup_expr() const
{
NetECReal*tmp = new NetECReal(value_);
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetECRealParam* NetECRealParam::dup_expr() const
{
NetECRealParam*tmp = new NetECRealParam(scope_, name_, value());
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetEEvent* NetEEvent::dup_expr() const
{
ivl_assert(*this, 0);
return 0;
}
NetENetenum* NetENetenum::dup_expr() const
{
ivl_assert(*this, 0);
return 0;
}
NetEScope* NetEScope::dup_expr() const
{
ivl_assert(*this, 0);
assert(0);
return 0;
}
NetESelect* NetESelect::dup_expr() const
{
NetESelect*tmp = new NetESelect(expr_->dup_expr(),
base_? base_->dup_expr() : 0,
expr_width(), sel_type_);
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
/*
* $Log: dup_expr.cc,v $
* Revision 1.1 1999/11/27 19:07:57 steve
* Support the creation of scopes.
*
*/
NetESFunc* NetESFunc::dup_expr() const
{
NetESFunc*tmp = new NetESFunc(name_, type_, expr_width(), nparms());
ivl_assert(*this, tmp);
tmp->cast_signed(has_sign());
for (unsigned idx = 0 ; idx < nparms() ; idx += 1) {
ivl_assert(*this, parm(idx));
tmp->parm(idx, parm(idx)->dup_expr());
}
tmp->set_line(*this);
return tmp;
}
NetESignal* NetESignal::dup_expr() const
{
NetESignal*tmp = new NetESignal(net_, word_);
ivl_assert(*this, tmp);
tmp->expr_width(expr_width());
tmp->set_line(*this);
return tmp;
}
NetETernary* NetETernary::dup_expr() const
{
NetETernary*tmp = new NetETernary(cond_->dup_expr(),
true_val_->dup_expr(),
false_val_->dup_expr(),
expr_width(),
has_sign());
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetEUFunc* NetEUFunc::dup_expr() const
{
NetEUFunc*tmp;
svector<NetExpr*> tmp_parms (parms_.count());
for (unsigned idx = 0 ; idx < tmp_parms.count() ; idx += 1) {
ivl_assert(*this, parms_[idx]);
tmp_parms[idx] = parms_[idx]->dup_expr();
}
tmp = new NetEUFunc(scope_, func_, result_sig_->dup_expr(), tmp_parms,
need_const_);
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetEUBits* NetEUBits::dup_expr() const
{
NetEUBits*tmp = new NetEUBits(op_, expr_->dup_expr(), expr_width(), has_sign());
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetEUnary* NetEUnary::dup_expr() const
{
NetEUnary*tmp = new NetEUnary(op_, expr_->dup_expr(), expr_width(), has_sign());
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetEUReduce* NetEUReduce::dup_expr() const
{
NetEUReduce*tmp = new NetEUReduce(op_, expr_->dup_expr());
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetECast* NetECast::dup_expr() const
{
NetECast*tmp = new NetECast(op_, expr_->dup_expr(), expr_width(), has_sign());
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
-166
View File
@@ -1,166 +0,0 @@
/*
* Copyright (c) 2000-2003 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"
/*
* The elaborate_anet methods elaborate expressions that are intended
* to be the left side of procedural continuous assignments.
*/
# include "PExpr.h"
# include "netlist.h"
# include "netmisc.h"
# include <iostream>
NetNet* PExpr::elaborate_anet(Design*des, NetScope*scope) const
{
cerr << get_line() << ": error: Invalid expression on left side "
<< "of procedural continuous assignment." << endl;
return 0;
}
NetNet* PEConcat::elaborate_anet(Design*des, NetScope*scope) const
{
if (repeat_) {
cerr << get_line() << ": error: Repeat concatenations make "
"no sense in l-value expressions. I refuse." << endl;
des->errors += 1;
return 0;
}
svector<NetNet*>nets (parms_.count());
unsigned pins = 0;
unsigned errors = 0;
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
if (parms_[idx] == 0) {
cerr << get_line() << ": error: Empty expressions "
<< "not allowed in concatenations." << endl;
errors += 1;
continue;
}
nets[idx] = parms_[idx]->elaborate_anet(des, scope);
if (nets[idx] == 0)
errors += 1;
else
pins += nets[idx]->pin_count();
}
/* If any of the sub expressions failed to elaborate, then
delete all those that did and abort myself. */
if (errors) {
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
if (nets[idx]) delete nets[idx];
}
des->errors += 1;
return 0;
}
/* Make the temporary signal that connects to all the
operands, and connect it up. Scan the operands of the
concat operator from least significant to most significant,
which is opposite from how they are given in the list.
Allow for a repeat count other than 1 by repeating the
connect loop as many times as necessary. */
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT_REG, pins);
/* Assume that all the data types are the same. */
osig->data_type(nets[0]->data_type());
pins = 0;
for (unsigned idx = nets.count() ; idx > 0 ; idx -= 1) {
NetNet*cur = nets[idx-1];
assert(cur->data_type() == osig->data_type());
for (unsigned pin = 0; pin < cur->pin_count(); pin += 1) {
connect(osig->pin(pins), cur->pin(pin));
pins += 1;
}
}
osig->local_flag(true);
return osig;
}
NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
{
assert(scope);
NetNet* sig = 0;
NetMemory* mem = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
symbol_search(this, des, scope, path_, sig, mem, par, eve);
if (mem != 0) {
cerr << get_line() << ": error: memories not allowed "
<< "on left side of procedural continuous "
<< "assignment." << endl;
des->errors += 1;
return 0;
}
if (eve != 0) {
cerr << get_line() << ": error: named events not allowed "
<< "on left side of procedural continuous "
<< "assignment." << endl;
des->errors += 1;
return 0;
}
if (sig == 0) {
cerr << get_line() << ": error: reg ``" << path_ << "'' "
<< "is undefined in this scope." << endl;
des->errors += 1;
return 0;
}
switch (sig->type()) {
case NetNet::REG:
case NetNet::IMPLICIT_REG:
break;
default:
cerr << get_line() << ": error: " << path_ << " is not "
<< "a reg in this context." << endl;
des->errors += 1;
return 0;
}
assert(sig);
if (msb_ || lsb_) {
cerr << get_line() << ": error: bit/part selects not allowed "
<< "on left side of procedural continuous assignment."
<< endl;
des->errors += 1;
return 0;
}
return sig;
}
+223 -4079
View File
File diff suppressed because it is too large Load Diff
-662
View File
@@ -1,662 +0,0 @@
/*
* Copyright (c) 2000-2012 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* 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 "PExpr.h"
# include "netlist.h"
# include "netmisc.h"
# include "netstruct.h"
# include "compiler.h"
# include <cstdlib>
# include <iostream>
# include <climits>
# include "ivl_assert.h"
/*
* These methods generate a NetAssign_ object for the l-value of the
* assignment. This is common code for the = and <= statements.
*
* What gets generated depends on the structure of the l-value. If the
* l-value is a simple name (i.e., foo <= <value>) then the NetAssign_
* is created the width of the foo reg and connected to all the
* bits.
*
* If there is a part select (i.e., foo[3:1] <= <value>) the NetAssign_
* is made only as wide as it needs to be (3 bits in this example) and
* connected to the correct bits of foo. A constant bit select is a
* special case of the part select.
*
* If the bit-select is non-constant (i.e., foo[<expr>] = <value>) the
* NetAssign_ is made wide enough to connect to all the bits of foo,
* then the mux expression is elaborated and attached to the
* NetAssign_ node as a b_mux value. The target must interpret the
* presence of a bmux value as taking a single bit and assigning it to
* the bit selected by the bmux expression.
*
* If the l-value expression is non-trivial, but can be fully
* evaluated at compile time (meaning any bit selects are constant)
* then elaboration will make a single NetAssign_ that connects to a
* synthetic reg that in turn connects to all the proper pins of the
* l-value.
*
* This last case can turn up in statements like: {a, b[1]} = c;
* rather than create a NetAssign_ for each item in the concatenation,
* elaboration makes a single NetAssign_ and connects it up properly.
*/
/*
* The default interpretation of an l-value to a procedural assignment
* is to try to make a net elaboration, and see if the result is
* suitable for assignment.
*/
NetAssign_* PExpr::elaborate_lval(Design*, NetScope*, bool) const
{
NetNet*ll = 0;
if (ll == 0) {
cerr << get_fileline() << ": Assignment l-value too complex."
<< endl;
return 0;
}
NetAssign_*lv = new NetAssign_(ll);
return lv;
}
/*
* Concatenation expressions can appear as l-values. Handle them here.
*
* If adjacent l-values in the concatenation are not bit selects, then
* merge them into a single NetAssign_ object. This can happen is code
* like ``{ ...a, b, ...}''. As long as "a" and "b" do not have bit
* selects (or the bit selects are constant) we can merge the
* NetAssign_ objects.
*
* Be careful to get the bit order right. In the expression ``{a, b}''
* a is the MSB and b the LSB. Connect the LSB to the low pins of the
* NetAssign_ object.
*/
NetAssign_* PEConcat::elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const
{
if (repeat_) {
cerr << get_fileline() << ": error: Repeat concatenations make "
"no sense in l-value expressions. I refuse." << endl;
des->errors += 1;
return 0;
}
NetAssign_*res = 0;
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
if (parms_[idx] == 0) {
cerr << get_fileline() << ": error: Empty expressions "
<< "not allowed in concatenations." << endl;
des->errors += 1;
continue;
}
NetAssign_*tmp = parms_[idx]->elaborate_lval(des, scope, is_force);
/* If the l-value doesn't elaborate, the error was
already detected and printed. We just skip it and let
the compiler catch more errors. */
if (tmp == 0) continue;
if (tmp->expr_type() == IVL_VT_REAL) {
cerr << parms_[idx]->get_fileline() << ": error: "
<< "concatenation operand can not be real: "
<< *parms_[idx] << endl;
des->errors += 1;
continue;
}
/* Link the new l-value to the previous one. */
NetAssign_*last = tmp;
while (last->more)
last = last->more;
last->more = res;
res = tmp;
}
return res;
}
/*
* Handle the ident as an l-value. This includes bit and part selects
* of that ident.
*/
NetAssign_* PEIdent::elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const
{
NetNet* reg = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
perm_string method_name;
symbol_search(this, des, scope, path_, reg, par, eve);
/* If the signal is not found, check to see if this is a
member of a struct. Take the name of the form "a.b.member",
remove the member and store it into method_name, and retry
the search with "a.b". */
if (reg == 0 && path_.size() >= 2) {
pform_name_t use_path = path_;
method_name = peek_tail_name(use_path);
use_path.pop_back();
symbol_search(this, des, scope, use_path, reg, par, eve);
if (reg && reg->struct_type() == 0) {
method_name = perm_string();
reg = 0;
}
}
if (reg == 0) {
cerr << get_fileline() << ": error: Could not find variable ``"
<< path_ << "'' in ``" << scope_path(scope) <<
"''" << endl;
des->errors += 1;
return 0;
}
ivl_assert(*this, reg);
// We are processing the tail of a string of names. For
// example, the verilog may be "a.b.c", so we are processing
// "c" at this point.
const name_component_t&name_tail = path_.back();
// Use the last index to determine what kind of select
// (bit/part/etc) we are processing. For example, the verilog
// may be "a.b.c[1][2][<index>]". All but the last index must
// be simple expressions, only the <index> may be a part
// select etc., so look at it to determine how we will be
// proceeding.
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
if (!name_tail.index.empty())
use_sel = name_tail.index.back().sel;
// Special case: The l-value is an entire memory, or array
// slice. This is, in fact, an error in l-values. Detect the
// situation by noting if the index count is less than the
// array dimensions (unpacked).
if (reg->array_dimensions() > name_tail.index.size()) {
cerr << get_fileline() << ": error: Cannot assign to array "
<< path_ << ". Did you forget a word index?" << endl;
des->errors += 1;
return 0;
}
/* Get the signal referenced by the identifier, and make sure
it is a register. Wires are not allowed in this context,
unless this is the l-value of a force. */
if ((reg->type() != NetNet::REG) && !is_force) {
cerr << get_fileline() << ": error: " << path_ <<
" is not a valid l-value in " << scope_path(scope) <<
"." << endl;
cerr << reg->get_fileline() << ": : " << path_ <<
" is declared here as " << reg->type() << "." << endl;
des->errors += 1;
return 0;
}
if (reg->struct_type() && !method_name.nil()) {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_packed_member_(des, scope, lv, method_name);
return lv;
}
if (reg->array_dimensions() > 0)
return elaborate_lval_net_word_(des, scope, reg);
// This must be after the array word elaboration above!
if (reg->get_scalar() &&
use_sel != index_component_t::SEL_NONE) {
cerr << get_fileline() << ": error: can not select part of ";
if (reg->data_type() == IVL_VT_REAL) cerr << "real: ";
else cerr << "scalar: ";
cerr << reg->name() << endl;
des->errors += 1;
return 0;
}
if (use_sel == index_component_t::SEL_PART) {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_part_(des, scope, lv);
return lv;
}
if (use_sel == index_component_t::SEL_IDX_UP ||
use_sel == index_component_t::SEL_IDX_DO) {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_idx_(des, scope, lv, use_sel);
return lv;
}
if (use_sel == index_component_t::SEL_BIT) {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_bit_(des, scope, lv);
return lv;
}
ivl_assert(*this, use_sel == index_component_t::SEL_NONE);
/* No select expressions. */
NetAssign_*lv = new NetAssign_(reg);
return lv;
}
NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
NetScope*scope,
NetNet*reg) const
{
const name_component_t&name_tail = path_.back();
ivl_assert(*this, !name_tail.index.empty());
const index_component_t&index_head = name_tail.index.front();
if (index_head.sel == index_component_t::SEL_PART) {
cerr << get_fileline() << ": error: cannot perform a part "
<< "select on array " << reg->name() << "." << endl;
des->errors += 1;
return 0;
}
ivl_assert(*this, index_head.sel == index_component_t::SEL_BIT);
ivl_assert(*this, index_head.msb != 0);
ivl_assert(*this, index_head.lsb == 0);
NetExpr*word = elab_and_eval(des, scope, index_head.msb, -1);
// If there is a non-zero base to the memory, then build an
// expression to calculate the canonical address.
if (long base = reg->array_first()) {
word = normalize_variable_array_base(word, base,
reg->array_count());
eval_expr(word);
}
NetAssign_*lv = new NetAssign_(reg);
lv->set_word(word);
if (debug_elaborate)
cerr << get_fileline() << ": debug: Set array word=" << *word << endl;
// Test for the case that the index is a constant, and is out
// of bounds. The "word" expression is the word index already
// converted to canonical address, so this just needs to check
// that the address is not too big.
if (NetEConst*word_const = dynamic_cast<NetEConst*>(word)) {
verinum word_val = word_const->value();
long index = word_val.as_long();
if (index < 0 || index >= (long) reg->array_count()) {
cerr << get_fileline() << ": warning: Constant array index "
<< (index + reg->array_first())
<< " is out of range for array "
<< reg->name() << "." << endl;
}
}
/* An array word may also have part selects applied to them. */
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
if (name_tail.index.size() > 1)
use_sel = name_tail.index.back().sel;
if (reg->get_scalar() &&
use_sel != index_component_t::SEL_NONE) {
cerr << get_fileline() << ": error: can not select part of ";
if (reg->data_type() == IVL_VT_REAL) cerr << "real";
else cerr << "scalar";
cerr << " array word: " << reg->name()
<< "[" << *word << "]" << endl;
des->errors += 1;
return 0;
}
if (use_sel == index_component_t::SEL_BIT)
elaborate_lval_net_bit_(des, scope, lv);
if (use_sel == index_component_t::SEL_PART)
elaborate_lval_net_part_(des, scope, lv);
if (use_sel == index_component_t::SEL_IDX_UP ||
use_sel == index_component_t::SEL_IDX_DO)
elaborate_lval_net_idx_(des, scope, lv, use_sel);
return lv;
}
bool PEIdent::elaborate_lval_net_bit_(Design*des,
NetScope*scope,
NetAssign_*lv) const
{
list<long>prefix_indices;
bool rc = calculate_packed_indices_(des, scope, lv->sig(), prefix_indices);
if (!rc) return false;
const name_component_t&name_tail = path_.back();
ivl_assert(*this, !name_tail.index.empty());
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 (prefix_indices.size()+2 <= reg->packed_dims().size()) {
// Special case: this is a slice of a multi-dimensional
// packed array. For example:
// reg [3:0][7:0] x;
// x[2] = ...
// This shows up as the prefix_indices being too short
// for the packed dimensions of the vector. What we do
// here is convert to a "slice" of the vector.
if (mux == 0) {
long loff;
unsigned long lwid;
bool rcl = reg->sb_to_slice(prefix_indices, lsb, loff, lwid);
ivl_assert(*this, rcl);
lv->set_part(new NetEConst(verinum(loff)), lwid);
} else {
unsigned long lwid;
mux = normalize_variable_slice_base(prefix_indices, mux,
reg, lwid);
lv->set_part(mux, lwid);
}
} else if (mux) {
// Non-constant bit mux. Correct the mux for the range
// of the vector, then set the l-value part select
// expression.
mux = normalize_variable_bit_base(prefix_indices, mux, reg);
lv->set_part(mux, 1);
} else if (reg->vector_width() == 1 && reg->sb_is_valid(prefix_indices,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(prefix_indices,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
{
list<long> prefix_indices;
bool rc = calculate_packed_indices_(des, scope, lv->sig(), prefix_indices);
ivl_assert(*this, rc);
// 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 parts_defined_flag;
bool flag = calculate_parts_(des, scope, msb, lsb, parts_defined_flag);
if (!flag)
return false;
ivl_assert(*this, parts_defined_flag);
NetNet*reg = lv->sig();
ivl_assert(*this, reg);
const list<NetNet::range_t>&packed = reg->packed_dims();
// Part selects cannot select slices. So there must be enough
// prefix_indices to get all the way to the final dimension.
if (prefix_indices.size()+1 < packed.size()) {
cerr << get_fileline() << ": error: Cannot select a range "
<< "of slices from a packed array." << endl;
des->errors += 1;
return false;
}
long loff = reg->sb_to_idx(prefix_indices,lsb);
long moff = reg->sb_to_idx(prefix_indices,msb);
long wid = moff - loff + 1;
if (moff < loff) {
cerr << get_fileline() << ": error: part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is reversed." << endl;
des->errors += 1;
return false;
}
// Special case: The range winds up selecting the entire
// vector. Treat this as no part select at all.
if (loff == 0 && moff == (long)(reg->vector_width()-1)) {
return true;
}
/* If the part select extends beyond the extremes 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 >= (long)reg->vector_width()) {
cerr << get_fileline() << ": warning: Part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is out of range." << endl;
}
lv->set_part(new NetEConst(verinum(loff)), wid);
return true;
}
bool PEIdent::elaborate_lval_net_idx_(Design*des,
NetScope*scope,
NetAssign_*lv,
index_component_t::ctype_t use_sel) const
{
list<long>prefix_indices;
bool rc = calculate_packed_indices_(des, scope, lv->sig(), prefix_indices);
ivl_assert(*this, rc);
const name_component_t&name_tail = path_.back();;
ivl_assert(*this, !name_tail.index.empty());
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();
assert(reg);
if (reg->type() != NetNet::REG) {
cerr << get_fileline() << ": error: " << path_ <<
" is not a reg/integer/time in " << scope_path(scope) <<
"." << endl;
cerr << reg->get_fileline() << ": : " << path_ <<
" is declared here as " << reg->type() << "." << endl;
des->errors += 1;
return false;
}
unsigned long wid;
calculate_up_do_width_(des, scope, wid);
NetExpr*base = elab_and_eval(des, scope, index_tail.msb, -1);
ivl_select_type_t sel_type = IVL_SEL_OTHER;
// Handle the special case that the base is constant. For this
// case we can reduce the expression.
if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
// For the undefined case just let the constant pass and
// we will handle it in the code generator.
if (base_c->value().is_defined()) {
long lsv = base_c->value().as_long();
long offset = 0;
// Get the signal range.
const list<NetNet::range_t>&packed = reg->packed_dims();
ivl_assert(*this, packed.size() == prefix_indices.size()+1);
// We want the last range, which is where we work.
const NetNet::range_t&rng = packed.back();
if (((rng.msb < rng.lsb) &&
use_sel == index_component_t::SEL_IDX_UP) ||
((rng.msb > rng.lsb) &&
use_sel == index_component_t::SEL_IDX_DO)) {
offset = -wid + 1;
}
delete base;
long rel_base = reg->sb_to_idx(prefix_indices,lsv) + offset;
/* If we cover the entire lvalue just skip the select. */
if (rel_base == 0 && wid == reg->vector_width()) return true;
base = new NetEConst(verinum(rel_base));
if (warn_ob_select) {
if (rel_base < 0) {
cerr << get_fileline() << ": warning: " << reg->name();
if (reg->array_dimensions() > 0) cerr << "[]";
cerr << "[" << lsv;
if (use_sel == index_component_t::SEL_IDX_UP) {
cerr << "+:";
} else {
cerr << "-:";
}
cerr << wid << "] is selecting before vector." << endl;
}
if (rel_base + wid > reg->vector_width()) {
cerr << get_fileline() << ": warning: " << reg->name();
if (reg->array_dimensions() > 0) cerr << "[]";
cerr << "[" << lsv;
if (use_sel == index_component_t::SEL_IDX_UP) {
cerr << "+:";
} else {
cerr << "-:";
}
cerr << wid << "] is selecting after vector." << endl;
}
}
} else {
if (warn_ob_select) {
cerr << get_fileline() << ": warning: " << reg->name();
if (reg->array_dimensions() > 0) cerr << "[]";
cerr << "['bx";
if (use_sel == index_component_t::SEL_IDX_UP) {
cerr << "+:";
} else {
cerr << "-:";
}
cerr << wid << "] is always outside vector." << endl;
}
}
} else {
ivl_assert(*this, prefix_indices.size()+1 == reg->packed_dims().size());
/* Correct the mux for the range of the vector. */
if (use_sel == index_component_t::SEL_IDX_UP) {
base = normalize_variable_part_base(prefix_indices, base,
reg, wid, true);
sel_type = IVL_SEL_IDX_UP;
} else {
// This is assumed to be a SEL_IDX_DO.
base = normalize_variable_part_base(prefix_indices, base,
reg, wid, false);
sel_type = IVL_SEL_IDX_DOWN;
}
}
if (debug_elaborate)
cerr << get_fileline() << ": debug: Set part select width="
<< wid << ", base=" << *base << endl;
lv->set_part(base, wid, sel_type);
return true;
}
bool PEIdent::elaborate_lval_net_packed_member_(Design*des,
NetScope*,
NetAssign_*lv,
const perm_string&member_name) const
{
NetNet*reg = lv->sig();
ivl_assert(*this, reg);
netstruct_t*struct_type = reg->struct_type();
ivl_assert(*this, struct_type);
if (! struct_type->packed()) {
cerr << get_fileline() << ": sorry: Only packed structures "
<< "are supported in l-value." << endl;
des->errors += 1;
return false;
}
unsigned long off;
const netstruct_t::member_t* member = struct_type->packed_member(member_name, off);
if (member == 0) {
cerr << get_fileline() << ": error: Member " << member_name
<< " is not a member of variable " << reg->name() << endl;
des->errors += 1;
return false;
}
lv->set_part(new NetEConst(verinum(off)), member->width());
return true;
}
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
{
cerr << get_fileline() << ": error: Constant values not allowed "
<< "in l-value expressions." << endl;
des->errors += 1;
return 0;
}
+849 -724
View File
File diff suppressed because it is too large Load Diff
-1643
View File
File diff suppressed because it is too large Load Diff
-1230
View File
File diff suppressed because it is too large Load Diff
-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>
+1423 -4194
View File
File diff suppressed because it is too large Load Diff
-72
View File
@@ -1,72 +0,0 @@
/*
* Copyright (c) 2008,2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "config.h"
# include "AStatement.h"
# include "netlist.h"
# include "netmisc.h"
# include "util.h"
# include <typeinfo>
NetProc* AContrib::elaborate(Design*des, NetScope*scope) const
{
NetExpr*lval = elab_and_eval(des, scope, lval_, -1);
NetExpr*rval = elab_and_eval(des, scope, rval_, -1);
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*estatement = statement_->elaborate(des, scope);
if (estatement == 0)
return false;
NetAnalogTop*top = new NetAnalogTop(scope, type_, estatement);
// 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;
}
+302 -366
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2011 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -16,10 +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
*/
# include "config.h"
# include <iostream>
#if !defined(WINNT)
#ident "$Id: emit.cc,v 1.31 1999/11/28 23:42:02 steve Exp $"
#endif
/*
* The emit function is called to generate the output required of the
@@ -27,296 +26,190 @@
*/
# include "target.h"
# include "netlist.h"
# include <iostream>
# include <typeinfo>
# include <cassert>
# include <cstring>
bool NetNode::emit_node(struct target_t*) const
void NetNode::emit_node(ostream&o, struct target_t*tgt) const
{
cerr << "EMIT: Gate type? " << typeid(*this).name() << endl;
return false;
}
bool NetLogic::emit_node(struct target_t*tgt) const
void NetLogic::emit_node(ostream&o, struct target_t*tgt) const
{
tgt->logic(this);
return true;
tgt->logic(o, this);
}
bool NetUDP::emit_node(struct target_t*tgt) const
void NetUDP::emit_node(ostream&o, struct target_t*tgt) const
{
tgt->udp(this);
return true;
tgt->udp(o, this);
}
bool NetAbs::emit_node(struct target_t*tgt) const
void NetAddSub::emit_node(ostream&o, struct target_t*tgt) const
{
tgt->lpm_abs(this);
return true;
tgt->lpm_add_sub(o, this);
}
bool NetAddSub::emit_node(struct target_t*tgt) const
void NetAssign::emit_node(ostream&o, struct target_t*tgt) const
{
tgt->lpm_add_sub(this);
return true;
tgt->net_assign(o, this);
}
bool NetArrayDq::emit_node(struct target_t*tgt) const
void NetAssignNB::emit_node(ostream&o, struct target_t*tgt) const
{
return tgt->lpm_array_dq(this);
tgt->net_assign_nb(o, this);
}
bool NetCaseCmp::emit_node(struct target_t*tgt) const
void NetCaseCmp::emit_node(ostream&o, struct target_t*tgt) const
{
tgt->net_case_cmp(this);
return true;
tgt->net_case_cmp(o, this);
}
bool NetCastInt2::emit_node(struct target_t*tgt) const
void NetCLShift::emit_node(ostream&o, struct target_t*tgt) const
{
return tgt->lpm_cast_int2(this);
tgt->lpm_clshift(o, this);
}
bool NetCastInt4::emit_node(struct target_t*tgt) const
void NetCompare::emit_node(ostream&o, struct target_t*tgt) const
{
return tgt->lpm_cast_int4(this);
tgt->lpm_compare(o, this);
}
bool NetCastReal::emit_node(struct target_t*tgt) const
void NetConst::emit_node(ostream&o, struct target_t*tgt) const
{
return tgt->lpm_cast_real(this);
tgt->net_const(o, this);
}
bool NetCLShift::emit_node(struct target_t*tgt) const
void NetFF::emit_node(ostream&o, struct target_t*tgt) const
{
tgt->lpm_clshift(this);
return true;
tgt->lpm_ff(o, this);
}
bool NetCompare::emit_node(struct target_t*tgt) const
void NetMux::emit_node(ostream&o, struct target_t*tgt) const
{
tgt->lpm_compare(this);
return true;
tgt->lpm_mux(o, this);
}
bool NetConcat::emit_node(struct target_t*tgt) const
void NetRamDq::emit_node(ostream&o, struct target_t*tgt) const
{
return tgt->concat(this);
tgt->lpm_ram_dq(o, this);
}
bool NetConst::emit_node(struct target_t*tgt) const
void NetNEvent::emit_node(ostream&o, struct target_t*tgt) const
{
return tgt->net_const(this);
tgt->net_event(o, this);
}
bool NetDivide::emit_node(struct target_t*tgt) const
void NetBUFZ::emit_node(ostream&o, struct target_t*tgt) const
{
tgt->lpm_divide(this);
return true;
tgt->bufz(o, this);
}
bool NetFF::emit_node(struct target_t*tgt) const
bool NetProcTop::emit(ostream&o, struct target_t*tgt) const
{
tgt->lpm_ff(this);
return true;
return tgt->process(o, this);
}
bool NetLiteral::emit_node(struct target_t*tgt) const
{
return tgt->net_literal(this);
}
bool NetModulo::emit_node(struct target_t*tgt) const
{
tgt->lpm_modulo(this);
return true;
}
bool NetMult::emit_node(struct target_t*tgt) const
{
tgt->lpm_mult(this);
return true;
}
bool NetMux::emit_node(struct target_t*tgt) const
{
tgt->lpm_mux(this);
return true;
}
bool NetPartSelect::emit_node(struct target_t*tgt) const
{
return tgt->part_select(this);
}
bool NetPow::emit_node(struct target_t*tgt) const
{
tgt->lpm_pow(this);
return true;
}
bool NetReplicate::emit_node(struct target_t*tgt) const
{
return tgt->replicate(this);
}
bool NetSignExtend::emit_node(struct target_t*tgt) const
{
return tgt->sign_extend(this);
}
bool NetUReduce::emit_node(struct target_t*tgt) const
{
return tgt->ureduce(this);
}
bool NetSysFunc::emit_node(struct target_t*tgt) const
{
return tgt->net_sysfunction(this);
}
bool NetUserFunc::emit_node(struct target_t*tgt) const
{
return tgt->net_function(this);
}
bool NetTran::emit_node(struct target_t*tgt) const
{
return tgt->tran(this);
}
bool NetBUFZ::emit_node(struct target_t*tgt) const
{
return tgt->bufz(this);
}
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*) const
bool NetProc::emit_proc(ostream&o, struct target_t*tgt) const
{
cerr << "EMIT: Proc type? " << typeid(*this).name() << endl;
return false;
}
bool NetAlloc::emit_proc(struct target_t*tgt) const
bool NetAssign::emit_proc(ostream&o, struct target_t*tgt) const
{
tgt->proc_alloc(this);
tgt->proc_assign(o, this);
return true;
}
bool NetAssign::emit_proc(struct target_t*tgt) const
bool NetAssignNB::emit_proc(ostream&o, struct target_t*tgt) const
{
return tgt->proc_assign(this);
}
bool NetAssignNB::emit_proc(struct target_t*tgt) const
{
tgt->proc_assign_nb(this);
tgt->proc_assign_nb(o, this);
return true;
}
bool NetBlock::emit_proc(struct target_t*tgt) const
bool NetAssignMem::emit_proc(ostream&o, struct target_t*tgt) const
{
return tgt->proc_block(this);
}
bool NetCase::emit_proc(struct target_t*tgt) const
{
tgt->proc_case(this);
tgt->proc_assign_mem(o, this);
return true;
}
bool NetCAssign::emit_proc(struct target_t*tgt) const
bool NetAssignMemNB::emit_proc(ostream&o, struct target_t*tgt) const
{
return tgt->proc_cassign(this);
}
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);
}
bool NetDisable::emit_proc(struct target_t*tgt) const
{
return tgt->proc_disable(this);
}
bool NetForce::emit_proc(struct target_t*tgt) const
{
return tgt->proc_force(this);
}
bool NetForever::emit_proc(struct target_t*tgt) const
{
tgt->proc_forever(this);
tgt->proc_assign_mem_nb(o, this);
return true;
}
bool NetFree::emit_proc(struct target_t*tgt) const
bool NetBlock::emit_proc(ostream&o, struct target_t*tgt) const
{
tgt->proc_free(this);
return tgt->proc_block(o, this);
}
bool NetCase::emit_proc(ostream&o, struct target_t*tgt) const
{
tgt->proc_case(o, this);
return true;
}
bool NetPDelay::emit_proc(struct target_t*tgt) const
bool NetCondit::emit_proc(ostream&o, struct target_t*tgt) const
{
return tgt->proc_delay(this);
}
bool NetPDelay::emit_proc_recurse(struct target_t*tgt) const
{
if (statement_) return statement_->emit_proc(tgt);
tgt->proc_condit(o, this);
return true;
}
bool NetRelease::emit_proc(struct target_t*tgt) const
bool NetForever::emit_proc(ostream&o, struct target_t*tgt) const
{
return tgt->proc_release(this);
}
bool NetRepeat::emit_proc(struct target_t*tgt) const
{
tgt->proc_repeat(this);
tgt->proc_forever(o, this);
return true;
}
bool NetSTask::emit_proc(struct target_t*tgt) const
bool NetPDelay::emit_proc(ostream&o, struct target_t*tgt) const
{
tgt->proc_stask(this);
tgt->proc_delay(o, this);
return true;
}
bool NetUTask::emit_proc(struct target_t*tgt) const
void NetPDelay::emit_proc_recurse(ostream&o, struct target_t*tgt) const
{
tgt->proc_utask(this);
if (statement_) statement_->emit_proc(o, tgt);
}
bool NetPEvent::emit_proc(ostream&o, struct target_t*tgt) const
{
tgt->proc_event(o, this);
return true;
}
bool NetWhile::emit_proc(struct target_t*tgt) const
void NetPEvent::emit_proc_recurse(ostream&o, struct target_t*tgt) const
{
tgt->proc_while(this);
if (statement_) statement_->emit_proc(o, tgt);
}
bool NetRepeat::emit_proc(ostream&o, struct target_t*tgt) const
{
tgt->proc_repeat(o, this);
return true;
}
void NetBlock::emit_recurse(struct target_t*tgt) const
bool NetSTask::emit_proc(ostream&o, struct target_t*tgt) const
{
tgt->proc_stask(o, this);
return true;
}
bool NetUTask::emit_proc(ostream&o, struct target_t*tgt) const
{
tgt->proc_utask(o, this);
return true;
}
bool NetWhile::emit_proc(ostream&o, struct target_t*tgt) const
{
tgt->proc_while(o, this);
return true;
}
void NetBlock::emit_recurse(ostream&o, struct target_t*tgt) const
{
if (last_ == 0)
return;
@@ -324,188 +217,104 @@ void NetBlock::emit_recurse(struct target_t*tgt) const
NetProc*cur = last_;
do {
cur = cur->next_;
cur->emit_proc(tgt);
cur->emit_proc(o, tgt);
} while (cur != last_);
}
bool NetCondit::emit_recurse_if(struct target_t*tgt) const
void NetCondit::emit_recurse_if(ostream&o, struct target_t*tgt) const
{
if (if_)
return if_->emit_proc(tgt);
else
return true;
if_->emit_proc(o, tgt);
}
bool NetCondit::emit_recurse_else(struct target_t*tgt) const
void NetCondit::emit_recurse_else(ostream&o, struct target_t*tgt) const
{
if (else_)
return else_->emit_proc(tgt);
else
return true;
else_->emit_proc(o, tgt);
}
bool NetEvProbe::emit_node(struct target_t*tgt) const
{
tgt->net_probe(this);
return true;
}
bool NetEvTrig::emit_proc(struct target_t*tgt) const
{
return tgt->proc_trigger(this);
}
bool NetEvWait::emit_proc(struct target_t*tgt) const
{
return tgt->proc_wait(this);
}
bool NetEvWait::emit_recurse(struct target_t*tgt) const
{
if (!statement_) return true;
return statement_->emit_proc(tgt);
}
void NetForever::emit_recurse(struct target_t*tgt) const
void NetForever::emit_recurse(ostream&o, struct target_t*tgt) const
{
if (statement_)
statement_->emit_proc(tgt);
statement_->emit_proc(o, tgt);
}
void NetRepeat::emit_recurse(struct target_t*tgt) const
void NetRepeat::emit_recurse(ostream&o, struct target_t*tgt) const
{
if (statement_)
statement_->emit_proc(tgt);
statement_->emit_proc(o, tgt);
}
void NetScope::emit_scope(struct target_t*tgt) const
void NetWhile::emit_proc_recurse(ostream&o, struct target_t*tgt) const
{
tgt->scope(this);
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_)
tgt->event(cur);
for (list<netenum_t*>::const_iterator cur = enum_sets_.begin()
; cur != enum_sets_.end() ; ++cur)
tgt->enumeration(this, *cur);
for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
; cur != children_.end() ; ++ cur )
cur->second->emit_scope(tgt);
for (signals_map_iter_t cur = signals_map_.begin()
; cur != signals_map_.end() ; ++ cur ) {
tgt->signal(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 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);
}
if (type_ == MODULE) tgt->convert_module_ports(this);
proc_->emit_proc(o, tgt);
}
bool NetScope::emit_defs(struct target_t*tgt) const
bool Design::emit(ostream&o, struct target_t*tgt) const
{
bool flag = true;
switch (type_) {
case MODULE:
for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
; cur != children_.end() ; ++ cur )
flag &= cur->second->emit_defs(tgt);
break;
case FUNC:
flag &= tgt->func_def(this);
break;
case TASK:
tgt->task_def(this);
break;
default: /* BEGIN_END and FORK_JOIN, GENERATE... */
for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
; cur != children_.end() ; ++ cur )
flag &= cur->second->emit_defs(tgt);
break;
}
return flag;
}
void NetWhile::emit_proc_recurse(struct target_t*tgt) const
{
proc_->emit_proc(tgt);
}
int Design::emit(struct target_t*tgt) const
{
int rc = 0;
if (tgt->start_design(this) == false)
return -2;
bool rc = true;
tgt->start_design(o, this);
// enumerate the scopes
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
scope != root_scopes_.end(); ++ scope )
(*scope)->emit_scope(tgt);
{ map<string,NetScope*>::const_iterator sc;
for (sc = scopes_.begin() ; sc != scopes_.end() ; sc++) {
tgt->scope(o, (*sc).second);
}
}
// emit signals
if (signals_) {
NetNet*cur = signals_->sig_next_;
do {
tgt->signal(o, cur);
cur = cur->sig_next_;
} while (cur != signals_->sig_next_);
}
// emit memories
{
map<string,NetMemory*>::const_iterator mi;
for (mi = memories_.begin() ; mi != memories_.end() ; mi++) {
tgt->memory(o, (*mi).second);
}
}
// emit nodes
bool nodes_rc = true;
if (nodes_) {
NetNode*cur = nodes_->node_next_;
do {
nodes_rc = nodes_rc && cur->emit_node(tgt);
cur->emit_node(o, tgt);
cur = cur->node_next_;
} while (cur != nodes_->node_next_);
}
bool branches_rc = true;
for (NetBranch*cur = branches_ ; cur ; cur = cur->next_) {
branches_rc = tgt->branch(cur) && branches_rc;
// emit function definitions
{
map<string,NetFuncDef*>::const_iterator ta;
for (ta = funcs_.begin() ; ta != funcs_.end() ; ta ++) {
tgt->func_def(o, (*ta).second);
}
}
// emit task and function definitions
bool tasks_rc = true;
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
scope != root_scopes_.end(); ++ scope )
tasks_rc &= (*scope)->emit_defs(tgt);
// emit task definitions
{
map<string,NetTaskDef*>::const_iterator ta;
for (ta = tasks_.begin() ; ta != tasks_.end() ; ta ++) {
tgt->task_def(o, (*ta).second);
}
}
// emit the processes
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);
if (nodes_rc == false)
return -1;
if (tasks_rc == false)
return -2;
if (proc_rc == false)
return -3;
if (branches_rc == false)
return -4;
rc = rc && idx->emit(o, tgt);
tgt->end_design(o, this);
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);
@@ -521,34 +330,20 @@ void NetEConst::expr_scan(struct expr_scan_t*tgt) const
tgt->expr_const(this);
}
void NetEConstEnum::expr_scan(struct expr_scan_t*tgt) const
void NetEIdent::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_const(this);
tgt->expr_ident(this);
}
void NetEConstParam::expr_scan(struct expr_scan_t*tgt) const
void NetEMemory::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_param(this);
tgt->expr_memory(this);
}
void NetECReal::expr_scan(struct expr_scan_t*tgt) const
void NetEParam::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_creal(this);
}
void NetECRealParam::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_rparam(this);
}
void NetEEvent::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_event(this);
}
void NetENetenum::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_netenum(this);
cerr << get_line() << ":internal error: unexpected NetEParam."
<< endl;
}
void NetEScope::expr_scan(struct expr_scan_t*tgt) const
@@ -556,16 +351,6 @@ void NetEScope::expr_scan(struct expr_scan_t*tgt) const
tgt->expr_scope(this);
}
void NetESelect::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_select(this);
}
void NetESFunc::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_sfunc(this);
}
void NetEUFunc::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_ufunc(this);
@@ -576,6 +361,11 @@ void NetESignal::expr_scan(struct expr_scan_t*tgt) const
tgt->expr_signal(this);
}
void NetESubSignal::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_subsignal(this);
}
void NetETernary::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_ternary(this);
@@ -585,3 +375,149 @@ void NetEUnary::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_unary(this);
}
bool emit(ostream&o, const Design*des, const char*type)
{
for (unsigned idx = 0 ; target_table[idx] ; idx += 1) {
const struct target*tgt = target_table[idx];
if (tgt->name == type)
return des->emit(o, tgt->meth);
}
}
/*
* $Log: emit.cc,v $
* Revision 1.31 1999/11/28 23:42:02 steve
* NetESignal object no longer need to be NetNode
* objects. Let them keep a pointer to NetNet objects.
*
* Revision 1.30 1999/11/27 19:07:57 steve
* Support the creation of scopes.
*
* Revision 1.29 1999/11/21 00:13:08 steve
* Support memories in continuous assignments.
*
* Revision 1.28 1999/11/14 23:43:45 steve
* Support combinatorial comparators.
*
* Revision 1.27 1999/11/14 20:24:28 steve
* Add support for the LPM_CLSHIFT device.
*
* Revision 1.26 1999/11/04 03:53:26 steve
* Patch to synthesize unary ~ and the ternary operator.
* Thanks to Larry Doolittle <LRDoolittle@lbl.gov>.
*
* Add the LPM_MUX device, and integrate it with the
* ternary synthesis from Larry. Replace the lpm_mux
* generator in t-xnf.cc to use XNF EQU devices to
* put muxs into function units.
*
* Rewrite elaborate_net for the PETernary class to
* also use the LPM_MUX device.
*
* Revision 1.25 1999/11/01 02:07:40 steve
* Add the synth functor to do generic synthesis
* and add the LPM_FF device to handle rows of
* flip-flops.
*
* Revision 1.24 1999/10/10 01:59:54 steve
* Structural case equals device.
*
* Revision 1.23 1999/09/22 16:57:23 steve
* Catch parallel blocks in vvm emit.
*
* Revision 1.22 1999/09/20 02:21:10 steve
* Elaborate parameters in phases.
*
* Revision 1.21 1999/09/15 01:55:06 steve
* Elaborate non-blocking assignment to memories.
*
* Revision 1.20 1999/09/03 04:28:38 steve
* elaborate the binary plus operator.
*
* Revision 1.19 1999/08/31 22:38:29 steve
* Elaborate and emit to vvm procedural functions.
*
* Revision 1.18 1999/07/17 19:50:59 steve
* netlist support for ternary operator.
*
* Revision 1.17 1999/07/17 03:39:11 steve
* simplified process scan for targets.
*
* Revision 1.16 1999/07/07 04:20:57 steve
* Emit vvm for user defined tasks.
*
* Revision 1.15 1999/07/03 02:12:51 steve
* Elaborate user defined tasks.
*
* Revision 1.14 1999/06/19 21:06:16 steve
* Elaborate and supprort to vvm the forever
* and repeat statements.
*
* Revision 1.13 1999/06/09 03:00:06 steve
* Add support for procedural concatenation expression.
*
* Revision 1.12 1999/06/06 20:45:38 steve
* Add parse and elaboration of non-blocking assignments,
* Replace list<PCase::Item*> with an svector version,
* Add integer support.
*
* Revision 1.11 1999/05/12 04:03:19 steve
* emit NetAssignMem objects in vvm target.
*
* Revision 1.10 1999/05/07 01:21:18 steve
* Handle total lack of nodes and signals.
*
* Revision 1.9 1999/05/01 02:57:53 steve
* Handle much more complex event expressions.
*
* Revision 1.8 1999/04/25 00:44:10 steve
* Core handles subsignal expressions.
*
* Revision 1.7 1999/04/19 01:59:36 steve
* Add memories to the parse and elaboration phases.
*
* Revision 1.6 1999/02/08 02:49:56 steve
* Turn the NetESignal into a NetNode so
* that it can connect to the netlist.
* Implement the case statement.
* Convince t-vvm to output code for
* the case statement.
*
* Revision 1.5 1999/02/01 00:26:49 steve
* Carry some line info to the netlist,
* Dump line numbers for processes.
* Elaborate prints errors about port vector
* width mismatch
* Emit better handles null statements.
*
* Revision 1.4 1998/12/01 00:42:14 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.3 1998/11/09 18:55:34 steve
* Add procedural while loops,
* Parse procedural for loops,
* Add procedural wait statements,
* Add constant nodes,
* Add XNOR logic gate,
* Make vvm output look a bit prettier.
*
* Revision 1.2 1998/11/07 17:05:05 steve
* Handle procedural conditional, and some
* of the conditional expressions.
*
* Elaborate signals and identifiers differently,
* allowing the netlist to hold signal information.
*
* Revision 1.1 1998/11/03 23:28:57 steve
* Introduce verilog to CVS.
*
*/
+92 -175
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -16,216 +16,112 @@
* 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 <cstring>
# include <iostream>
#if !defined(WINNT)
#ident "$Id: eval.cc,v 1.12 1999/11/30 04:48:17 steve Exp $"
#endif
# include "PExpr.h"
# include "netlist.h"
# include "netmisc.h"
# include "compiler.h"
verinum* PExpr::eval_const(Design*, NetScope*) const
verinum* PExpr::eval_const(const Design*, const string&) const
{
return 0;
}
verinum* PEBinary::eval_const(Design*des, NetScope*scope) const
verinum* PEBinary::eval_const(const Design*des, const string&path) const
{
verinum*l = left_->eval_const(des, scope);
verinum*l = left_->eval_const(des, path);
if (l == 0) return 0;
verinum*r = right_->eval_const(des, scope);
verinum*r = right_->eval_const(des, path);
if (r == 0) {
delete l;
return 0;
}
verinum*res;
switch (op_) {
case '+': {
if (l->is_defined() && r->is_defined()) {
res = new verinum(*l + *r);
} else {
res = new verinum(verinum::Vx, l->len());
}
assert(l->is_defined());
assert(r->is_defined());
long lv = l->as_long();
long rv = r->as_long();
res = new verinum(lv+rv, l->len());
break;
}
case '-': {
if (l->is_defined() && r->is_defined()) {
res = new verinum(*l - *r);
} else {
res = new verinum(verinum::Vx, l->len());
}
assert(l->is_defined());
assert(r->is_defined());
long lv = l->as_long();
long rv = r->as_long();
res = new verinum(lv-rv, l->len());
break;
}
case '*': {
if (l->is_defined() && r->is_defined()) {
res = new verinum(*l * *r);
} else {
res = new verinum(verinum::Vx, l->len());
}
assert(l->is_defined());
assert(r->is_defined());
long lv = l->as_long();
long rv = r->as_long();
res = new verinum(lv * rv, l->len());
break;
}
case '/': {
if (l->is_defined() && r->is_defined()) {
long lv = l->as_long();
long rv = r->as_long();
res = new verinum(lv / rv, l->len());
} else {
res = new verinum(verinum::Vx, l->len());
}
assert(l->is_defined());
assert(r->is_defined());
long lv = l->as_long();
long rv = r->as_long();
res = new verinum(lv / rv, l->len());
break;
}
case '%': {
if (l->is_defined() && r->is_defined()) {
long lv = l->as_long();
long rv = r->as_long();
res = new verinum(lv % rv, l->len());
} else {
res = new verinum(verinum::Vx, l->len());
}
break;
}
case '>': {
if (l->is_defined() && r->is_defined()) {
long lv = l->as_long();
long rv = r->as_long();
res = new verinum(lv > rv, l->len());
} else {
res = new verinum(verinum::Vx, l->len());
}
break;
}
case '<': {
if (l->is_defined() && r->is_defined()) {
long lv = l->as_long();
long rv = r->as_long();
res = new verinum(lv < rv, l->len());
} else {
res = new verinum(verinum::Vx, l->len());
}
break;
}
case 'l': { // left shift (<<)
assert(l->is_defined());
assert(r->is_defined());
unsigned long rv = r->as_ulong();
res = new verinum(verinum::V0, l->len());
if (rv < res->len()) {
unsigned cnt = res->len() - rv;
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
res->set(idx+rv, l->get(idx));
}
long lv = l->as_long();
long rv = r->as_long();
res = new verinum(lv % rv, l->len());
break;
}
case 'r': { // right shift (>>)
assert(r->is_defined());
unsigned long rv = r->as_ulong();
res = new verinum(verinum::V0, l->len());
if (rv < res->len()) {
unsigned cnt = res->len() - rv;
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
res->set(idx, l->get(idx+rv));
}
break;
}
default:
delete l;
delete r;
return 0;
}
delete l;
delete r;
return res;
}
verinum* PEConcat::eval_const(Design*des, NetScope*scope) const
{
verinum*accum = parms_[0]->eval_const(des, scope);
if (accum == 0)
return 0;
for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) {
verinum*tmp = parms_[idx]->eval_const(des, scope);
if (tmp == 0) {
delete accum;
return 0;
}
assert(tmp);
*accum = concat(*accum, *tmp);
delete tmp;
}
return accum;
}
/*
* Evaluate an identifier as a constant expression. This is only
* possible if the identifier is that of a parameter.
*/
verinum* PEIdent::eval_const(Design*des, NetScope*scope) const
verinum* PEIdent::eval_const(const Design*des, const string&path) const
{
assert(scope);
NetNet*net;
NetEvent*eve;
const NetExpr*expr;
const name_component_t&name_tail = path_.back();
// Handle the special case that this ident is a genvar
// variable name. In that case, the genvar meaning preempts
// everything and we just return that value immediately.
if (scope->genvar_tmp
&& strcmp(name_tail.name,scope->genvar_tmp) == 0) {
return new verinum(scope->genvar_tmp_val);
}
symbol_search(this, des, scope, path_, net, expr, eve);
const NetExpr*expr = des->find_parameter(path, text_);
if (expr == 0)
return 0;
const NetEConst*eval = dynamic_cast<const NetEConst*>(expr);
if (eval == 0) {
cerr << get_fileline() << ": internal error: Unable to evaluate "
<< "constant expression (parameter=" << path_
<< "): " << *expr << endl;
assert(msb_ == 0);
if (dynamic_cast<const NetEParam*>(expr)) {
cerr << get_line() << ": sorry: I cannot evaluate ``" <<
text_ << "'' in this context." << endl;
return 0;
}
const NetEConst*eval = dynamic_cast<const NetEConst*>(expr);
assert(eval);
if (!name_tail.index.empty())
return 0;
return new verinum(eval->value());
}
verinum* PEFNumber::eval_const(Design*, NetScope*) const
{
long val = value_->as_long();
return new verinum(val);
}
verinum* PENumber::eval_const(Design*, NetScope*) const
verinum* PENumber::eval_const(const Design*, const string&) const
{
return new verinum(value());
}
verinum* PEString::eval_const(Design*, NetScope*) const
verinum* PETernary::eval_const(const Design*des, const string&path) const
{
return new verinum(string(text_));
}
verinum* PETernary::eval_const(Design*des, NetScope*scope) const
{
verinum*test = expr_->eval_const(des, scope);
verinum*test = expr_->eval_const(des, path);
if (test == 0)
return 0;
@@ -233,9 +129,9 @@ verinum* PETernary::eval_const(Design*des, NetScope*scope) const
delete test;
switch (bit) {
case verinum::V0:
return fal_->eval_const(des, scope);
return fal_->eval_const(des, path);
case verinum::V1:
return tru_->eval_const(des, scope);
return tru_->eval_const(des, path);
default:
return 0;
// XXXX It is possible to handle this case if both fal_
@@ -243,30 +139,51 @@ verinum* PETernary::eval_const(Design*des, NetScope*scope) const
}
}
verinum* PEUnary::eval_const(Design*des, NetScope*scope) const
{
verinum*val = expr_->eval_const(des, scope);
if (val == 0)
return 0;
switch (op_) {
case '+':
return val;
/*
* $Log: eval.cc,v $
* Revision 1.12 1999/11/30 04:48:17 steve
* Handle evaluation of ternary during elaboration.
*
* Revision 1.11 1999/11/28 23:42:02 steve
* NetESignal object no longer need to be NetNode
* objects. Let them keep a pointer to NetNet objects.
*
* Revision 1.10 1999/11/21 20:03:24 steve
* Handle multiply in constant expressions.
*
* Revision 1.9 1999/10/08 17:48:09 steve
* Support + in constant expressions.
*
* Revision 1.8 1999/09/20 02:21:10 steve
* Elaborate parameters in phases.
*
* Revision 1.7 1999/09/18 01:52:48 steve
* Remove spurious message.
*
* Revision 1.6 1999/09/16 04:18:15 steve
* elaborate concatenation repeats.
*
* Revision 1.5 1999/08/06 04:05:28 steve
* Handle scope of parameters.
*
* Revision 1.4 1999/07/17 19:51:00 steve
* netlist support for ternary operator.
*
* Revision 1.3 1999/05/30 01:11:46 steve
* Exressions are trees that can duplicate, and not DAGS.
*
* Revision 1.2 1999/05/10 00:16:58 steve
* Parse and elaborate the concatenate operator
* in structural contexts, Replace vector<PExpr*>
* and list<PExpr*> with svector<PExpr*>, evaluate
* constant expressions with parameters, handle
* memories as lvalues.
*
* Parse task declarations, integer types.
*
* Revision 1.1 1998/11/03 23:28:58 steve
* Introduce verilog to CVS.
*
*/
case '-': {
/* We need to expand the value a bit if we are
taking the 2's complement so that we are
guaranteed to not overflow. */
verinum tmp ((uint64_t)0, val->len()+1);
for (unsigned idx = 0 ; idx < val->len() ; idx += 1)
tmp.set(idx, val->get(idx));
*val = v_not(tmp) + verinum(verinum::V1, 1);
val->has_sign(true);
return val;
}
}
delete val;
return 0;
}
-74
View File
@@ -1,74 +0,0 @@
/*
* Copyright (c) 2002-2010 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 "util.h"
# include "PExpr.h"
# include "netlist.h"
# include <iostream>
# include <cassert>
/*
* The evaluate_attributes function evaluates the attribute
* expressions from the map, and returns a table in a form suitable
* for passing to netlist devices.
*/
attrib_list_t* evaluate_attributes(const map<perm_string,PExpr*>&att,
unsigned&natt,
Design*des, NetScope*scope)
{
natt = att.size();
if (natt == 0)
return 0;
attrib_list_t*table = new attrib_list_t [natt];
unsigned idx = 0;
typedef map<perm_string,PExpr*>::const_iterator iter_t;
for (iter_t cur = att.begin() ; cur != att.end() ; ++ cur , idx += 1) {
table[idx].key = (*cur).first;
PExpr*exp = (*cur).second;
/* 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) {
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)
tmp = new verinum(1);
assert(tmp);
table[idx].val = *tmp;
delete tmp;
}
assert(idx == natt);
return table;
}
+155 -1839
View File
File diff suppressed because it is too large Load Diff
-87
View File
@@ -1,87 +0,0 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* 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
*/
/*
* This source file demonstrates how to synthesize CLB flip-flops from
* Icarus Verilog, including giving the device an initial value.
*
* To compile this for XNF, try a command like this:
*
* iverilog -txnf -ppart=XC4010XLPQ160 -pncf=clbff.ncf -oclbff.xnf clbff.v
*
* That command causes an clbff.xnf and clbff.ncf file to be created.
* Next, make the clbff.ngd file with the command:
*
* xnf2ngd -l xilinxun -u clbff.xnf clbff.ngo
* ngdbuild clbff.ngo clbff.ngd
*
* Finally, map the file to fully render it in the target part. The
* par command is the step that actually optimizes the design and tries
* to meet timing constraints.
*
* map -o map.ncd clbff.ngd
* par -w map.ncd clbff.ncd
*
* At this point, you can use the FPGA Editor to edit the clbff.ncd
* file. Notice that the design uses two CLB flip-flops (possibly in
* the same CLB) with their outputs ANDed together. If you go into the
* block editor, you will see that the FF connected to main/Q<0> is
* configured so start up reset, and the FF connected to main/Q<1> is
* configured to start up set.
*/
module main;
wire clk, iclk;
wire i0, i1;
wire out;
wire [1:0] D = {i1, i0};
// This statement declares Q to be a 2 bit reg vector. The
// initial assignment will cause the synthesized device to take
// on an initial value specified here. Without the assignment,
// the initial value is unspecified. (Verilog simulates it as 2'bx.)
reg [1:0] Q = 2'b10;
// This simple logic gate get turned into a function unit.
// The par program will map this into a CLB F or G unit.
and (out, Q[0], Q[1]);
// This creates a global clock buffer. Notice how I attach an
// attribute to the named gate to force it to be mapped to the
// desired XNF device. This device will not be pulled into the
// IOB associated with iclk because of the attribute.
buf gbuf(clk, iclk);
$attribute(gbuf, "XNF-LCA", "GCLK:O,I");
// This is mapped to a DFF. Since Q and D are two bits wide, the
// code generator actually makes two DFF devices that share a
// clock input.
always @(posedge clk) Q <= D;
// These attribute commands assign pins to the listed wires.
// This can be done to wires and registers, as internally both
// are treated as named signals.
$attribute(out, "PAD", "o150");
$attribute(i0, "PAD", "i152");
$attribute(i1, "PAD", "i153");
$attribute(iclk,"PAD", "i154");
endmodule /* main */
-1035
View File
File diff suppressed because it is too large Load Diff
-81
View File
@@ -1,81 +0,0 @@
/*
* Copyright (c) 2002 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: hello_vpi.c,v 1.5 2007/01/17 05:35:48 steve Exp $"
#endif
/*
* This file contains an example VPI module to demonstrate the tools
* to create vpi modules. To compile this module, use the iverilog-vpi
* command like so:
*
* iverilog-vpi hello_vpi.c
*
* The result is the hello_vpi.vpi module. See the hello_vpi.vl
* program for example Verilog code to call this module.
*/
# include <vpi_user.h>
static PLI_INT32 my_hello_calltf(char *xx)
{
vpi_printf("Hello World, from VPI.\n");
return 0;
}
static void my_hello_register()
{
s_vpi_systf_data tf_data;
tf_data.type = vpiSysTask;
tf_data.tfname = "$my_hello";
tf_data.calltf = my_hello_calltf;
tf_data.compiletf = 0;
tf_data.sizetf = 0;
vpi_register_systf(&tf_data);
}
/*
* This is a table of register functions. This table is the external
* symbol that the simulator looks for when loading this .vpi module.
*/
void (*vlog_startup_routines[])() = {
my_hello_register,
0
};
/*
* $Log: hello_vpi.c,v $
* Revision 1.5 2007/01/17 05:35:48 steve
* Fix typo is hello_vpi.c example.
*
* Revision 1.4 2006/10/30 22:46:25 steve
* Updates for Cygwin portability (pr1585922)
*
* Revision 1.3 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
* Revision 1.2 2002/08/11 23:47:04 steve
* Add missing Log and Ident strings.
*
* Revision 1.1 2002/04/18 03:25:16 steve
* More examples.
*
*/
-49
View File
@@ -1,49 +0,0 @@
/*
* 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
* 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
*/
/*
* Here we have the canonical "Hello, World" program written in Verilog,
* with VPI. It uses the hello_vpi.vpi module that is compiled from
* the hello_vpi.c program also in this directory. See the
* hello_vpi.c for instructions on how to compile it.
*
* Compile this program with the command:
*
* iverilog -ohello_vpi hello_vpi.vl
*
* After churning for a little while, the program will create the output
* file "hello" which is compiled, linked and ready to run. Run this
* program like so:
*
* vvp -M. -mhello_vpi hello_vpi
*
* and the program will print the message to its output. Easy! For
* more on how to make the iverilog command work, see the iverilog
* manual page.
*/
module main();
initial
begin
$my_hello;
$finish ;
end
endmodule
-76
View File
@@ -1,76 +0,0 @@
/*
* Copyright (c) 1998-1999 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
*/
/*
* IVL should generate an AND gate, and should make an OBUF and two
* IBUF objects, along with the PAD objects.
*
* To compile this for XNF, try a command like this:
*
* iverilog -txnf -ppart=XC4010XLPQ160 -ooutff.xnf -pncf=outff.ncf outff.v
*
* That command causes an outff.xnf and outff.ncf file to be created.
* Next, make the outff.ngd file with the command:
*
* xnf2ngd -l xilinxun -u outff.xnf outff.ngo
* ngdbuild outff.ngo outff.ngd
*
* Finally, map the file to fully render it in the target part. The
* par command is the step that actually optimizes the design and tries
* to meet timing constraints.
*
* map -o map.ncd outff.ngd
* par -w map.ncd outff.ncd
*
* At this point, you can use the FPGA Editor to edit the outff.ncd
* file to see that the AND gate is in a CLB and the IOB for pin 150
* has its flip-flop in use, and that gbuf is a global buffer.
*/
module main;
wire clk, iclk;
wire i0, i1;
wire out;
reg o0;
// This simple logic gate get turned into a function unit.
// The par program will map this into a CLB F or G unit.
and (out, i0, i1);
// This creates a global clock buffer. Notice how I attach an
// attribute to the named gate to force it to be mapped to the
// desired XNF device. This device will not be pulled into the
// IOB associated with iclk because of the attribute.
buf gbuf(clk, iclk);
$attribute(gbuf, "XNF-LCA", "GCLK:O,I");
// This is mapped to a DFF. Since o0 is connected to a PAD, it
// is turned into a OUTFF so that it get placed into an IOB.
always @(posedge clk) o0 = out;
// These attribute commands assign pins to the listed wires.
// This can be done to wires and registers, as internally both
// are treated as named signals.
$attribute(o0, "PAD", "o150");
$attribute(i0, "PAD", "i152");
$attribute(i1, "PAD", "i153");
$attribute(iclk,"PAD", "i154");
endmodule /* main */
-121
View File
@@ -1,121 +0,0 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* 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
*/
/*
* This example shows how to use Icarus Verilog to generate PLD output.
* The design is intended to fit into a 22v10 in a PLCC package, with
* pin assignments locked down by design. The command to compile this
* into a jedec file is;
*
* iverilog -tpal -ppart=generic-22v10-plcc -opal_reg.jed pal_reg.v
*
* The output file name (passed through the -o<file> switch) can be
* any file you desire. If the compilation and fitting all succeed, the
* output file will be a JEDEC file that you can take to your favorite
* PROM programmer to program the part.
*
* This source demonstrates some important principles of synthesizing
* a design for a PLD, including how to specify synchronous logic, and
* how to assign signals to pins. The pin assignment in particular is
* part specific, and must be right for the fitting to succeed.
*/
/*
* The register module is an 8 bit register that copies the input to
* the output registers on the rising edge of the clk input. The
* always statement creates a simple d-type flip-flop that is loaded
* on the rising edge of the clock.
*
* The output drivers are controlled by a single active low output
* enable. I used bufif0 devices in this example, but the exact same
* thing can be achieved with a continuous assignment like so:
*
* assign out = oe? 8'hzz : Q;
*
* Many people prefer the expression form. It is true that it does
* seem to express the intent a bit more clearly.
*/
module register (out, val, clk, oe);
output [7:0] out;
input [7:0] val;
input clk, oe;
reg [7:0] Q;
wire [7:0] out;
bufif0 drv[7:0](out, Q, oe);
always @(posedge clk) Q = val;
endmodule
/*
* The module pal is used to attach pin information to all the pins of
* the device. We use this to lock down the pin assignments of the
* synthesized result. The pin number assignments are for a 22v10 in
* a PLCC package.
*
* Note that this module has no logic in it. It is a convention I use
* that I put all the functionality in a separate module (seen above)
* and isolate the Icarus Verilog specific $attribute madness into a
* top-level module. The advantage of this style is that the entire
* module can be `ifdef'ed out when doing simulation and you don't
* need to worry that functionality will be affected.
*/
module pal;
wire out7, out6, out5, out4, out3, out2, out1, out0;
wire inp7, inp6, inp5, inp4, inp3, inp2, inp1, inp0;
wire clk, oe;
// The PAD attributes attach the wires to pins of the
// device. Output pins are prefixed by a 'o', and input pins by an
// 'i'. If not all the available output pins are used, then the
// remaining are available for the synthesizer to drop internal
// registers or extra logic layers.
$attribute(out7, "PAD", "o27");
$attribute(out6, "PAD", "o26");
$attribute(out5, "PAD", "o25");
$attribute(out4, "PAD", "o24");
$attribute(out3, "PAD", "o23");
$attribute(out2, "PAD", "o21");
$attribute(out1, "PAD", "o20");
$attribute(out0, "PAD", "o19");
$attribute(inp7, "PAD", "i10");
$attribute(inp6, "PAD", "i9");
$attribute(inp5, "PAD", "i7");
$attribute(inp4, "PAD", "i6");
$attribute(inp3, "PAD", "i5");
$attribute(inp2, "PAD", "i4");
$attribute(inp1, "PAD", "i3");
$attribute(inp0, "PAD", "i2");
//$attribute(clk, "PAD", "CLK");
$attribute(oe, "PAD", "i13");
register dev({out7, out6, out5, out4, out3, out2, out1, out0},
{inp7, inp6, inp5, inp4, inp3, inp2, inp1, inp0},
clk, oe);
endmodule // pal
-114
View File
@@ -1,114 +0,0 @@
/*
* Copyright (c) 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
* 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
*/
/*
* This example program simulates a 16x1 ram, and is used as an
* example for using VCD output and waveform viewers.
*
* Like any other Verilog simulation, compile this program with the
* command:
*
* iverilog show_vcd.vl
*
* This will generate the show_vcd command in the current directory.
* When you run the command, you will see the output from all the
* calls to $display, but also there will be a dump file ``show_vcd.vcd''.
* The name of this file is set by the statement:
*
* $dumpfile("show_vcd.vcd");
*
* in the main module. The output file uses the standard VCD file format
* so can be viewed using off-the-shelf waveform viewers. The remaining
* steps describe how to use GTKWave to view the file. If you are using
* a different viewer, see the documentation for that tool.
*
* To view the output generated by running show_vcd, start the GTKWave
* viewer with the command:
*
* gtkwave show_vcd.vcd
*
* The GTKWave program will display its main window, and show in a small
* status box (upper left corner) that it succeeded in loading the dump
* file. However, there are no waveforms displayed yet. Select signals to
* add to the waveform display using the menu selection:
*
* "Search --> Signal Search Tree"
*
* This will bring up a dialog box that shows in directory tree format
* the signals of the program. Select the signals you wish to view, and
* click one of the buttons on the bottom of the dialog box to display
* the selected signals in the waveform window. Click "Exit" on the box
* to get rid of it.
*
* The magic that makes all this work is contained in the $dumpfile and
* $dumpvars system tasks. The $dumpfile task tells the simulation where
* to write the VCD output. This task must be called once before the
* $dumpvars task is called.
*
* The $dumpvars task tells the simulation what variables to write to
* the VCD output. The first parameter is how far to descend while
* scanning a scope, and the remaining parameters are signals or scope
* names to include in the dump. If a scope name is given, all the
* signals within the scope are dumped. If a wire or register name is
* given, that signal is included.
*/
module ram16x1 (q, d, a, we, wclk);
output q;
input d;
input [3:0] a;
input we;
input wclk;
reg mem[15:0];
assign q = mem[a];
always @(posedge wclk) if (we) mem[a] = d;
endmodule /* ram16x1 */
module main;
wire q;
reg d;
reg [3:0] a;
reg we, wclk;
ram16x1 r1 (q, d, a, we, wclk);
initial begin
$dumpfile("show_vcd.vcd");
$dumpvars(1, main.r1);
wclk = 0;
we = 1;
for (a = 0 ; a < 4'hf ; a = a + 1) begin
d = a[0];
#1 wclk = 1;
#1 wclk = 0;
$display("r1[%x] == %b", a, q);
end
for (a = 0 ; a < 4'hf ; a = a + 1)
#1 if (q !== a[0]) begin
$display("FAILED -- mem[%h] !== %b", a, a[0]);
$finish;
end
$display("PASSED");
end
endmodule /* main */
-378
View File
@@ -1,378 +0,0 @@
/*
* Copyright (c) 2002 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
*
* $Id: sqrt-virtex.v,v 1.5 2007/03/22 16:08:18 steve Exp $"
*/
/*
* This module is a synthesizable square-root function. It is also a
* detailed example of how to target Xilinx Virtex parts using
* Icarus Verilog. In fact, for no particular reason other than to
* be excessively specific, I will step through the process of
* generating a design for a Spartan-II XC2S15-VQ100, and also how to
* generate a generic library part for larger Virtex designs.
*
* In addition to Icarus Verilog, you will need implementation
* software from Xilinx. As of this writing, this example was tested
* with Foundation 4.2i, but it should work the same with ISE and
* WebPACK software.
*
* This example source contains all the Verilog needed to do
* everything described below. We use conditional compilation to
* select the bits of Verilog that are needed to perform each specific
* task.
*
* SIMULATE THE DESIGN
*
* This source file includes a simulation test bench. To compile the
* program to include this test bench, use the command line:
*
* iverilog -DSIMULATE=1 -oa.out sqrt-virtex.v
*
* This generates the file "a.out" that can then be executed with the
* command:
*
* vvp a.out
*
* This causes the simulation to run a long set of example sqrt
* calculations. Each result is checked by the test bench to assure
* that the result is valid. When it is done, the program prints
* "PASSED" and finishes the simulation.
*
* When you take a close look at the "main" module below, you will see
* that it uses Verilog constructs that are not synthesizable. This
* is fine, as we will never try to synthesize it.
*
* LIBRARY PARTS
*
* One can use the sqrt32 module to generate an EDIF file suitable for
* use as a library part. This part can be imported to the Xilinx
* schematic editor, then placed like any other pre-existing
* macro. One can also pass the generated EDIF as a precompiled macro
* that other designers may use as they see fit.
*
* To make an EDIF file from the sqrt32 module, execute the command:
*
* iverilog -osqrt32.edf -tfpga -parch=virtex sqrt-virtex.v
*
* The -parch=virtex tells the code generator to generate code for the
* virtex architecture family (we don't yet care what specific part)
* and the -osqrt32.edf places the output into the file
* sqrt32.edf.
*
* Without any preprocessor directives, the only module is the sqrt32
* module, so sqrt32 is compiled as the root. The ports of the module
* are automatically made into ports of the sqrt32.edf netlist, and
* the contents of the sqrt32 module are connected appropriately.
*
* COMPLETE CHIP DESIGNS
*
* To make a complete chip design, there are other bits that need to
* be accounted for. Signals must be assigned to pins, and some
* special devices may need to be created. We also want to write into
* the EDIF file complete part information so that the implementation
* tools know how to route the complete design. The command to compile
* for our target part is:
*
* iverilog -ochip.edf -tfpga \
* -parch=virtex -ppart=XC2S15-VQ100 \
* -DMAKE_CHIP=1 sqrt-virtex.v
*
* This command uses the "chip" module as the root. This module in
* turn has ports that are destined to be the pins of the completed
* part. The -ppart= option gives complete part information, that is
* in turn written into the EDIF file. This saves us the drudgery of
* repeating that part number for later commands.
*
* The next steps involve Xilinx software, and to talk to Xilinx
* software, the netlist must be in the form of an "ngd" file, a
* binary netlist format. The command:
*
* ngdbuild chip.edf chip.ngd
*
* does the trick. The input to ngdbuild is the chip.edf file created
* by Icarus Verilog, and the output is the chip.ngd file that the
* implementation tools may read. From this point, it is best to refer
* to Xilinx documentation for the software you are using, but the
* quick summary is:
*
* map -o map.ncd chip.ngd
* par -w map.ncd chip.ncd
*
* The result of this sequence of commands is the chip.ncd file that
* is ready to be viewed by FPGA Edit, or converted to a bit stream,
* or whatever.
*
* POST MAP SIMULATION
*
* Warm fuzzies are good, and retesting your design after the part
* is mapped by the Xilinx backend tools is a cheap source of fuzzies.
* The command to make a Verilog file out of the mapped design is:
*
* ngd2ver chip.ngd chip_root.v
*
* This command creates from the chip.ngd the file "chip_root.v" that
* contains Verilog code that simulates the mapped design. This output
* Verilog has the single root module "chip_root", which came from the
* name of the root module when we were making the EDIF file in the
* first place. The module has ports named just line the ports of the
* chip_root module below.
*
* The generated Verilog uses the library in the directory
* $(XILINX)/verilog/src/simprims. This directory comes with the ISE
* WebPACK installation that you are using. Icarus Verilog is able to
* simulate using that library.
*
* To compile a post-map simulation of the chip_root.v, use the
* command:
*
* iverilog -DSIMULATE -DPOST_MAP -ob.out \
* -y $(XILINX)/verilog/src/simprims \
* sqrt-virtex.v chip_root.v \
* $(XILINX)/verilog/src/glbl.v
*
* This command line generates b.out from the source files
* sqrt-virtex.v and chip_root.v (the latter from ngd2ver)
* and the "-y <path>" flag specifies the library directory that will
* be needed. The glbl.v source file is also included to provide the
* GSR and related signals.
*
* 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
* the same way the pre-synthesis design works.
*
* Run this design with the command:
*
* vvp b.out
*
* And there you go.
*/
`ifndef POST_MAP
/*
* This module approximates the square root of an unsigned 32bit
* number. The algorithm works by doing a bit-wise binary search.
* Starting from the most significant bit, the accumulated value
* tries to put a 1 in the bit position. If that makes the square
* too big for the input, the bit is left zero, otherwise it is set
* in the result. This continues for each bit, decreasing in
* significance, until all the bits are calculated or all the
* remaining bits are zero.
*
* Since the result is an integer, this function really calculates
* value of the expression:
*
* x = floor(sqrt(y))
*
* where sqrt(y) is the exact square root of y and floor(N) is the
* largest integer <= N.
*
* For 32 bit numbers, this will never run more than 16 iterations,
* which amounts to 16 clocks.
*/
module sqrt32(clk, rdy, reset, x, .y(acc));
input clk;
output rdy;
input reset;
input [31:0] x;
output [15:0] acc;
// acc holds the accumulated result, and acc2 is the accumulated
// square of the accumulated result.
reg [15:0] acc;
reg [31:0] acc2;
// Keep track of which bit I'm working on.
reg [4:0] bitl;
wire [15:0] bit = 1 << bitl;
wire [31:0] bit2 = 1 << (bitl << 1);
// The output is ready when the bitl counter underflows.
wire rdy = bitl[4];
// guess holds the potential next values for acc, and guess2 holds
// the square of that guess. The guess2 calculation is a little bit
// subtle. The idea is that:
//
// guess2 = (acc + bit) * (acc + bit)
// = (acc * acc) + 2*acc*bit + bit*bit
// = acc2 + 2*acc*bit + bit2
// = acc2 + 2 * (acc<<bitl) + bit
//
// This works out using shifts because bit and bit2 are known to
// have only a single bit in them.
wire [15:0] guess = acc | bit;
wire [31:0] guess2 = acc2 + bit2 + ((acc << bitl) << 1);
(* ivl_synthesis_on *)
always @(posedge clk or posedge reset)
if (reset) begin
acc = 0;
acc2 = 0;
bitl = 15;
end else begin
if (guess2 <= x) begin
acc <= guess;
acc2 <= guess2;
end
bitl <= bitl - 5'd1;
end
endmodule // sqrt32
`endif // `ifndef POST_MAP
`ifdef SIMULATE
/*
* This module is a test bench for the sqrt32 module. It runs some
* test input values through the sqrt32 module, and checks that the
* output is valid. If an invalid output is generated, print and
* error message and stop immediately. If all the tested values pass,
* then print PASSED after the test is complete.
*/
module main;
reg [31:0] x;
reg clk, reset;
wire [15:0] y;
wire rdy;
`ifdef POST_MAP
chip_root dut(.clk(clk), .reset(reset), .rdy(rdy), .x(x), .y(y));
`else
sqrt32 dut(.clk(clk), .reset(reset), .rdy(rdy), .x(x), .y(y));
`endif
(* ivl_synthesis_off *)
always #5 clk = !clk;
task reset_dut;
begin
reset = 1;
@(posedge clk) ;
#1 reset = 0;
@(negedge clk) ;
end
endtask // reset_dut
task crank_dut;
begin
while (rdy == 0) begin
@(posedge clk) /* wait */;
end
end
endtask // crank_dut
`ifdef POST_MAP
reg GSR;
assign glbl.GSR = GSR;
`endif
integer idx;
(* ivl_synthesis_off *)
initial begin
reset = 0;
clk = 0;
/* If doing a post-map simulation, when we need to wiggle
The GSR bit to simulate chip power-up. */
`ifdef POST_MAP
GSR = 1;
#100 GSR = 0;
`endif
#100 x = 1;
reset_dut;
crank_dut;
$display("x=%d, y=%d", x, y);
x = 3;
reset_dut;
crank_dut;
$display("x=%d, y=%d", x, y);
x = 4;
reset_dut;
crank_dut;
$display("x=%d, y=%d", x, y);
for (idx = 0 ; idx < 200 ; idx = idx + 1) begin
x = $random;
reset_dut;
crank_dut;
$display("x=%d, y=%d", x, y);
if (x < (y * y)) begin
$display("ERROR: y is too big");
$finish;
end
if (x > ((y + 1)*(y + 1))) begin
$display("ERROR: y is too small");
$finish;
end
end
$display("PASSED");
$finish;
end
endmodule // main
`endif
`ifdef MAKE_CHIP
/*
* This module represents the chip packaging that we intend to
* generate. We bind pins here, and route the clock to the global
* clock buffer.
*/
module chip_root(clk, rdy, reset, x, y);
input clk;
output rdy;
input reset;
input [31:0] x;
output [15:0] y;
wire clk_int;
(* cellref="BUFG:O,I" *)
buf gbuf (clk_int, clk);
sqrt32 dut(.clk(clk_int), .reset(reset), .rdy(rdy), .x(x), .y(y));
/* Assign the clk to GCLK0, which is on pin P39. */
$attribute(clk, "PAD", "P39");
// We don't care where the remaining pins go, so set the pin number
// to 0. This tells the implementation tools that we want a PAD,
// but we don't care which. Also note the use of a comma (,)
// separated list to assign pins to the bits of a vector.
$attribute(rdy, "PAD", "0");
$attribute(reset, "PAD", "0");
$attribute(x, "PAD", "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0");
$attribute(y, "PAD", "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0");
endmodule // chip_root
`endif

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