mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-24 23:06:56 +02:00
Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
afa2478801 | ||
|
|
79feb44f10 | ||
|
|
c03d76a0d7 | ||
|
|
d0f303463d | ||
|
|
35fe8fae00 | ||
|
|
2e95a740da | ||
|
|
2f4e5bf5b6 |
@@ -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()
|
||||
{
|
||||
}
|
||||
@@ -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
|
||||
@@ -16,6 +16,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: Attrib.cc,v 1.6 2004/02/20 18:53:33 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
@@ -99,3 +102,37 @@ const verinum& Attrib::attr_value(unsigned idx) const
|
||||
assert(idx < nlist_);
|
||||
return list_[idx].val;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: Attrib.cc,v $
|
||||
* Revision 1.6 2004/02/20 18:53:33 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
* Revision 1.5 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.4 2002/05/26 01:39:02 steve
|
||||
* Carry Verilog 2001 attributes with processes,
|
||||
* all the way through to the ivl_target API.
|
||||
*
|
||||
* Divide signal reference counts between rval
|
||||
* and lval references.
|
||||
*
|
||||
* Revision 1.3 2002/05/23 03:08:50 steve
|
||||
* Add language support for Verilog-2001 attribute
|
||||
* syntax. Hook this support into existing $attribute
|
||||
* handling, and add number and void value types.
|
||||
*
|
||||
* Add to the ivl_target API new functions for access
|
||||
* of complex attributes attached to gates.
|
||||
*
|
||||
* Revision 1.2 2001/07/25 03:10:48 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.1 2000/12/04 17:37:03 steve
|
||||
* Add Attrib class for holding NetObj attributes.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: Attrib.h,v 1.5 2004/02/20 18:53:33 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "StringHeap.h"
|
||||
# include "verinum.h"
|
||||
@@ -57,4 +60,31 @@ class Attrib {
|
||||
Attrib& operator= (const Attrib&);
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: Attrib.h,v $
|
||||
* Revision 1.5 2004/02/20 18:53:33 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
* Revision 1.4 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.3 2002/05/26 01:39:02 steve
|
||||
* Carry Verilog 2001 attributes with processes,
|
||||
* all the way through to the ivl_target API.
|
||||
*
|
||||
* Divide signal reference counts between rval
|
||||
* and lval references.
|
||||
*
|
||||
* Revision 1.2 2002/05/23 03:08:50 steve
|
||||
* Add language support for Verilog-2001 attribute
|
||||
* syntax. Hook this support into existing $attribute
|
||||
* handling, and add number and void value types.
|
||||
*
|
||||
* Add to the ivl_target API new functions for access
|
||||
* of complex attributes attached to gates.
|
||||
*
|
||||
* Revision 1.1 2000/12/04 17:37:03 steve
|
||||
* Add Attrib class for holding NetObj attributes.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
||||
@@ -4,24 +4,23 @@ HOW TO REPORT BUGS
|
||||
Before I can fix an error, I need to understand what the problem
|
||||
is. Try to explain what is wrong and why you think it is wrong. Please
|
||||
try to include sample code that demonstrates the problem. Include a
|
||||
description of what Icarus Verilog does that is wrong, and what you
|
||||
expect should happen. And include the command line flags passed to the
|
||||
compiler to make the error happen. (This is often overlooked, and
|
||||
sometimes important.)
|
||||
description of what ivl does that is wrong, and what you expect should
|
||||
happen. And include the command line flags passed to the compiler to make
|
||||
the error happen. (This is often overlooked, and sometimes important.)
|
||||
|
||||
* The Compiler Doesn't Compile
|
||||
|
||||
If Icarus Verilog doesn't compile, I need to know about the
|
||||
If the Icarus Verilog don't compile, I need to know about the
|
||||
compilation tools you are using. Specifically, I need to know:
|
||||
|
||||
- Operating system and processor type,
|
||||
- Compiler w/ version,
|
||||
- Versions of any libraries being linked, and
|
||||
- Library version, and
|
||||
- anything else you think relevant.
|
||||
|
||||
Be aware that I do not have at my disposal a porting lab. I have the
|
||||
workstation on my desk, a Mac laptop, and the Linux/Intel box with a
|
||||
logic analyzer and 'scope hanging off it.
|
||||
alpha on my desk, and the Linux/Intel box with a logic analyzer and
|
||||
'scope hanging off it.
|
||||
|
||||
* The Compiler Crashes
|
||||
|
||||
@@ -29,26 +28,26 @@ No compiler should crash, no matter what kind of garbage is fed to
|
||||
it. If the compiler crashes, you definitely found a bug and I need to
|
||||
know about it.
|
||||
|
||||
Icarus Verilog internally checks its state while it works, and if it
|
||||
detects something wrong that it cannot recover from, it will abort
|
||||
Ivl internally checks its state while it works, and if it detects
|
||||
something wrong that it cannot recover from, it will abort
|
||||
intentionally. The "assertion failure" message that the program
|
||||
prints in the process of dying is very important. It tells me where in
|
||||
the source the bad thing happened. Include that message in the bug
|
||||
report.
|
||||
|
||||
If there are no assertion messages, I need to know that as well.
|
||||
If there are not assertion messages, I need to know that as well.
|
||||
|
||||
I also need a complete test program that demonstrates the crash.
|
||||
|
||||
* It Doesn't Like My Perfectly Valid Program(tm)
|
||||
|
||||
I need to know what you think is right that Icarus Verilog gets
|
||||
wrong. Does it reject your "Perfectly Valid Program(tm)" or does it
|
||||
compile it but give incorrect results? The latter is the most
|
||||
insidious as it doesn't scream out to be fixed unless someone is
|
||||
watching closely. However, if I get a sample program from you, and I
|
||||
can compile it, and I run it and nuclear junk doesn't fall from the
|
||||
sky, I'm moving on to the next problem.
|
||||
I need to know what you think is right that ivl gets wrong. Does it
|
||||
reject your "Perfectly Valid Program(tm)" or does it compile it but
|
||||
give incorrect results? The latter is the most insidious as it doesn't
|
||||
scream out to be fixed unless someone is watching closely. However, if
|
||||
I get a sample program from you, and I can compile it, and I run it
|
||||
and nuclear junk doesn't fall from the sky, I'm moving on to the next
|
||||
problem.
|
||||
|
||||
So, if your program doesn't compile, tell me so, tell me where the
|
||||
error occurs, and include a complete Perfectly Valid Test Program(tm).
|
||||
@@ -58,25 +57,24 @@ know. What's on my disk is more recent then the latest snapshot.
|
||||
|
||||
If your program does compile, but generates incorrect output, I need
|
||||
to know what it says and what you think it should say. From this I can
|
||||
take your sample program and work on Icarus Verilog until it gets the
|
||||
proper results. For this to work, of course, I first need to know what
|
||||
is wrong with the output. Spell it out, because I've been known to
|
||||
miss the obvious. Compiler writers often get buried in the details of
|
||||
the wrong problem.
|
||||
take your sample program and work on ivl until it gets the proper
|
||||
results. For this to work, of course, I first need to know what is
|
||||
wrong with the output. Spell it out, because I've been known to miss
|
||||
the obvious. Compiler writers often get buried in the details of the
|
||||
wrong problem.
|
||||
|
||||
* It Generates Incorrect Target Code
|
||||
* It Generates Incorrect Target Code (XNF, EDIF/LPM, etc.)
|
||||
|
||||
As Icarus Verilog adds target code generators, there will be cases
|
||||
where errors in the output netlist format occur. This is a tough nut
|
||||
because I might not have all the tools to test the target format you
|
||||
are reporting problems with. However, if you clearly explain what is
|
||||
right and wrong about the generated output, I will probably be able
|
||||
to fix the problem. It may take a few iterations.
|
||||
As ivl adds target code generators, there will be cases where errors
|
||||
in the output netlist format occur. This is a tough nut because I
|
||||
might not have all the tools to test the target format you are
|
||||
reporting problems with. However, if you clearly explain what is right
|
||||
and wrong about the generated netlist, I will probably be able to fix
|
||||
the problem. It may take a few iterations.
|
||||
|
||||
In this case, if possible include not only the sample Verilog program,
|
||||
but the generated netlist file(s) and a clear indication of what went
|
||||
wrong or what is expected. If it is not clear to me, I will ask for
|
||||
clarification.
|
||||
wrong. If it is not clear to me, I will ask for clarification.
|
||||
|
||||
* The Output is Correct, But Less Than Ideal
|
||||
|
||||
@@ -93,13 +91,13 @@ demonstrates the problem. If the error occurs after elaboration,
|
||||
please include a top level module in the program that is suitable for
|
||||
the target format. If I have to write the module myself, I might not
|
||||
write it in a way that tickles the bug. So please, send all the
|
||||
Verilog source that I need to invoke the error.
|
||||
Verilog source (after preprocessing) that I need to invoke the error.
|
||||
|
||||
Also, include the command line you use to invoke the compiler. For
|
||||
example:
|
||||
|
||||
iverilog -o foo.out -tvvp foo.v
|
||||
iverilog foo.vl -s starthere
|
||||
ivl foo.vl -o foo.cc -tvvm
|
||||
ivl foo.vl -s starthere
|
||||
|
||||
If the error occurs with the null target (``-tnull'') then a top level
|
||||
module may not be needed as long as the ``-s <name>'' switch is
|
||||
@@ -110,19 +108,15 @@ invoke the error without any Verilog other than what is included?" And
|
||||
while we are at it, please place a copyright notice in your test
|
||||
program and include a GPL license statement if you can. Your test
|
||||
program may find its way into the test suite, and the notices will
|
||||
make it all nice and legal. Please look at the existing tests in the
|
||||
test suite <http://sourceforge.net/ivtest> for examples of good test
|
||||
programs.
|
||||
make it all nice and legal.
|
||||
|
||||
RESEARCHING EXISTING/PAST BUGS, AND FILING REPORTS
|
||||
|
||||
The URL <http://sourceforge.net/tracker/?group_id=149850> is the main
|
||||
bug tracking system. Once you believe you have found a bug, you may
|
||||
browse the bugs database for existing bugs that may be related to
|
||||
yours. You might find that your bug has already been fixed in a later
|
||||
release or snapshot. If that's the case, then you are set. Also,
|
||||
consider if you are reporting a bug or really asking for a new
|
||||
feature, and use the appropriate tracker.
|
||||
The URL <http://www.icarus.com/cgi-bin/ivl-bugs> is the main bug
|
||||
tracking system. Once you believe you have found a bug, you may browse
|
||||
the bugs database for existing bugs that may be related to yours. You
|
||||
might find that your bug has already been fixed in a later release or
|
||||
snapshot. If that's the case, then you are set.
|
||||
|
||||
The bug database supports basic keyword searches, and you can
|
||||
optionally limit your search to active bugs, or fixed bugs. You may
|
||||
@@ -131,7 +125,8 @@ broken. You may for example find a related bug that explains your
|
||||
symptom.
|
||||
|
||||
The root page of the bug report database describes how to submit your
|
||||
completed bug report.
|
||||
completed bug report. You may submit it via the web form, or via
|
||||
e-mail.
|
||||
|
||||
HOW TO SEND PATCHES
|
||||
|
||||
@@ -139,26 +134,21 @@ Bug reports with patches are very welcome, especially if they are
|
||||
formatted such that I can inspect them, decide that they are obviously
|
||||
correct, and apply them without worry.
|
||||
|
||||
I prefer patches generated by the git source code tracking system. If
|
||||
you are editing the source, you really should be using the latest
|
||||
version from git. Please see the developer documentation for more
|
||||
detailed instructions -- <http://iverilog.wikia.com/wiki/>.
|
||||
I prefer context diffs as emitted by diff from GNU diffutils. Human
|
||||
beings can read such things, and they are resilient to changing
|
||||
originals. A good set of flags to diff are ``diff -cNB''. With such
|
||||
diffs, I can look at the changes you are offering and probably tell at
|
||||
a glance that they are plausible. Then I can use patch(1) to apply
|
||||
them. Or I can apply them by hand.
|
||||
|
||||
When you make a patch, submit it to the "Patches" tracker at
|
||||
<http://sourceforge.net/tracker/?group_id=149850>. Patches added to
|
||||
the "Patches" tracker enter the developer workflow, are checked,
|
||||
applied to the appropriate git branch, and are pushed. Then the
|
||||
tracker item is closed.
|
||||
|
||||
If you send patches, *please* tell me what this patch is supposed to
|
||||
accomplish, which branch you intended to be patched, and if
|
||||
appropriate include a test program that demonstrates the efficacy of
|
||||
the patch. (If I have no idea what the patch is for, I will ask for
|
||||
clarification before applying it.)
|
||||
However, if you send patches, *please* tell me what this patch is
|
||||
supposed to accomplish, and if appropriate include a test program that
|
||||
demonstrates the efficacy of the patch. (If I have no idea what the
|
||||
patch is for, I will ask for clarification before applying it.)
|
||||
|
||||
COPYRIGHT ISSUES
|
||||
|
||||
Icarus Verilog is Copyright (c) 1998-2008 Stephen Williams except
|
||||
Icarus Verilog is Copyright (c) 1998-2003 Stephen Williams except
|
||||
where otherwise noted. Minor patches are covered as derivative works
|
||||
(or editorial comment or whatever the appropriate legal term is) and
|
||||
folded into the rest of ivl. However, if a submission can reasonably
|
||||
@@ -168,3 +158,19 @@ then falls under the "otherwise noted" category.
|
||||
|
||||
I must insist that any copyright material submitted for inclusion
|
||||
include the GPL license notice as shown in the rest of the source.
|
||||
|
||||
|
||||
$Id: BUGS.txt,v 1.5 2007/03/22 16:08:14 steve Exp $
|
||||
$Log: BUGS.txt,v $
|
||||
Revision 1.5 2007/03/22 16:08:14 steve
|
||||
Spelling fixes from Larry
|
||||
|
||||
Revision 1.4 2003/02/19 04:36:31 steve
|
||||
Notes on hte bug database.
|
||||
|
||||
Revision 1.3 2003/01/30 16:23:07 steve
|
||||
Spelling fixes.
|
||||
|
||||
Revision 1.2 1999/08/06 04:05:28 steve
|
||||
Handle scope of parameters.
|
||||
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: HName.cc,v 1.8 2007/06/02 03:42:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "HName.h"
|
||||
@@ -117,3 +120,33 @@ ostream& operator<< (ostream&out, const hname_t&that)
|
||||
return out;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: HName.cc,v $
|
||||
* Revision 1.8 2007/06/02 03:42:12 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.7 2007/05/16 19:12:33 steve
|
||||
* Fix hname_t use of space for 1 perm_string.
|
||||
*
|
||||
* Revision 1.6 2007/04/26 03:06:21 steve
|
||||
* Rework hname_t to use perm_strings.
|
||||
*
|
||||
* Revision 1.5 2002/11/02 03:27:52 steve
|
||||
* Allow named events to be referenced by
|
||||
* hierarchical names.
|
||||
*
|
||||
* Revision 1.4 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.3 2002/01/05 04:36:06 steve
|
||||
* include malloc.h only when available.
|
||||
*
|
||||
* Revision 1.2 2001/12/18 04:52:45 steve
|
||||
* Include config.h for namespace declaration.
|
||||
*
|
||||
* Revision 1.1 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __HName_H
|
||||
#define __HName_H
|
||||
/*
|
||||
* Copyright (c) 2001-2008 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2001-2007 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -18,9 +18,11 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: HName.h,v 1.7 2007/06/02 03:42:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <iostream>
|
||||
# include <list>
|
||||
# include "StringHeap.h"
|
||||
#ifdef __GNUC__
|
||||
#if __GNUC__ > 2
|
||||
@@ -55,7 +57,7 @@ class hname_t {
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
// If the number is anything other than INT_MIN, then this is
|
||||
// If the number is anything other then INT_MIN, then this is
|
||||
// the numeric part of the name. Otherwise, it is not part of
|
||||
// the name at all.
|
||||
int number_;
|
||||
@@ -68,16 +70,30 @@ extern bool operator == (const hname_t&, const hname_t&);
|
||||
extern bool operator != (const hname_t&, const hname_t&);
|
||||
extern ostream& operator<< (ostream&, const hname_t&);
|
||||
|
||||
inline ostream& operator<< (ostream&out, const list<hname_t>&ll)
|
||||
{
|
||||
list<hname_t>::const_iterator cur = ll.begin();
|
||||
out << *cur;
|
||||
cur ++;
|
||||
while (cur != ll.end()) {
|
||||
out << "." << *cur;
|
||||
cur ++;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: HName.h,v $
|
||||
* Revision 1.7 2007/06/02 03:42:12 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.6 2007/05/16 19:12:33 steve
|
||||
* Fix hname_t use of space for 1 perm_string.
|
||||
*
|
||||
* Revision 1.5 2007/04/26 03:06:21 steve
|
||||
* Rework hname_t to use perm_strings.
|
||||
*
|
||||
* Revision 1.4 2002/11/02 03:27:51 steve
|
||||
* Allow named events to be referenced by
|
||||
* hierarchical names.
|
||||
*
|
||||
* Revision 1.3 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.2 2002/06/14 03:25:51 steve
|
||||
* Compiler portability.
|
||||
*
|
||||
* Revision 1.1 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
||||
+68
-72
@@ -18,35 +18,12 @@
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
# Normally, the "make" will build all the files only by dependencies.
|
||||
# The MODE, however, can control your rebuild intentions. The proper way
|
||||
# to use the MODE is on the make command like, this this:
|
||||
#
|
||||
# make MODE=XXXX all
|
||||
#
|
||||
# The possible MODE= values are:
|
||||
#
|
||||
# regular
|
||||
# Build as normal
|
||||
#
|
||||
# full
|
||||
# Do some extra builds. in particular:
|
||||
# Build version.h again, even if it already exists.
|
||||
#
|
||||
MODE=regular
|
||||
|
||||
# This version string is only used in the version message printed
|
||||
# by the compiler. It reflects the assigned version number for the
|
||||
# product as a whole. Most components also print the CVS Name: token
|
||||
# in order to get a more automatic version stamp as well.
|
||||
VERSION = 0.9.devel
|
||||
|
||||
# This string is used as an installation suffix. It modifies certain
|
||||
# key install paths/files such that a build and install of Icarus Verilog
|
||||
# with the same $(prefix) but a different $(suffix) will not interfere.
|
||||
# The normal configuratin leaves suffix empty
|
||||
suffix = @install_suffix@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
@@ -58,9 +35,7 @@ VPATH = $(srcdir)
|
||||
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
# This is actually the directory where we install our own header files.
|
||||
# It is a little different from the generic includedir.
|
||||
includedir = @includedir@/iverilog$(suffix)
|
||||
includedir = @includedir@
|
||||
mandir = @mandir@
|
||||
|
||||
dllib=@DLLIB@
|
||||
@@ -77,15 +52,15 @@ MAN = @MAN@
|
||||
PS2PDF = @PS2PDF@
|
||||
GIT = @GIT@
|
||||
|
||||
CPPFLAGS = @DEFS@ -I. -I$(srcdir) -DVERSION='"$(VERSION)"' @CPPFLAGS@
|
||||
CPPFLAGS = @ident_support@ @DEFS@ -I. -I$(srcdir) @CPPFLAGS@
|
||||
CXXFLAGS = -Wall @CXXFLAGS@
|
||||
PICFLAGS = @PICFLAG@
|
||||
LDFLAGS = @rdynamic@ @LDFLAGS@
|
||||
|
||||
all: dep version.h ivl@EXEEXT@
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) VERSION=$(VERSION) $@); done
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
for dir in ivlpp ; \
|
||||
do (cd $$dir ; $(MAKE) VERSION=$(VERSION) $@); done
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
cd driver ; $(MAKE) VERSION=$(VERSION) $@
|
||||
|
||||
# In the windows world, the installer will need a dosify program to
|
||||
@@ -121,25 +96,23 @@ distclean: clean
|
||||
rm -f Makefile config.status config.log config.cache config.h
|
||||
rm -f _pli_types.h
|
||||
|
||||
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o t-dll-analog.o
|
||||
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o
|
||||
FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o
|
||||
|
||||
O = main.o async.o design_dump.o discipline.o dup_expr.o \
|
||||
elaborate.o elab_expr.o elaborate_analog.o \
|
||||
O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o elab_expr.o \
|
||||
elab_lval.o elab_net.o elab_pexpr.o elab_scope.o \
|
||||
elab_sig.o elab_sig_analog.o emit.o eval.o eval_attrib.o \
|
||||
elab_sig.o emit.o eval.o eval_attrib.o \
|
||||
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
|
||||
load_module.o netlist.o netmisc.o net_analog.o net_assign.o \
|
||||
net_design.o net_event.o net_expr.o net_func.o \
|
||||
load_module.o netlist.o netmisc.o net_assign.o \
|
||||
net_design.o net_event.o net_expr.o net_force.o net_func.o \
|
||||
net_link.o net_modulo.o net_nex_input.o net_nex_output.o \
|
||||
net_proc.o net_scope.o net_tran.o net_udp.o pad_to_width.o \
|
||||
parse.o parse_misc.o pform.o pform_analog.o pform_disciplines.o \
|
||||
pform_dump.o pform_types.o \
|
||||
parse.o parse_misc.o pform.o pform_disciplines.o pform_dump.o pform_types.o \
|
||||
set_width.o symbol_search.o sync.o sys_funcs.o \
|
||||
verinum.o verireal.o target.o \
|
||||
verinum.o verireal.o target.o targets.o \
|
||||
Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \
|
||||
PExpr.o PGate.o PGenerate.o PScope.o PSpec.o \
|
||||
PTask.o PUdp.o PFunction.o PWire.o Statement.o AStatement.o StringHeap.o \
|
||||
PTask.o PUdp.o PFunction.o PWire.o Statement.o StringHeap.o \
|
||||
$(FF) $(TT)
|
||||
|
||||
Makefile: Makefile.in config.h.in config.status
|
||||
@@ -166,13 +139,12 @@ SUBDIRS += driver-vpi
|
||||
else
|
||||
all: dep iverilog-vpi
|
||||
|
||||
iverilog-vpi: iverilog-vpi.sh Makefile
|
||||
iverilog-vpi: iverilog-vpi.sh
|
||||
sed -e 's;@SHARED@;@shared@;' -e 's;@PIC@;@PICFLAG@;' \
|
||||
-e 's;@SUFFIX@;$(suffix);' \
|
||||
-e 's;@IVCC@;$(CC);' \
|
||||
-e 's;@IVCXX@;$(CXX);' \
|
||||
-e 's;@IVCFLAGS@;$(CXXFLAGS);' \
|
||||
-e 's;@INCLUDEDIR@;$(includedir);' \
|
||||
-e 's;@INCLUDEDIR@;@includedir@;' \
|
||||
-e 's;@LIBDIR@;@libdir@;' $< > $@
|
||||
chmod +x $@
|
||||
endif
|
||||
@@ -213,9 +185,7 @@ iverilog-vpi.pdf: iverilog-vpi.ps
|
||||
# For VERSION_TAG in driver/main.c, first try git-describe, then look for a
|
||||
# version.h file in the source tree (included in snapshots and releases), and
|
||||
# finally use nothing.
|
||||
ifeq ($(MODE),full)
|
||||
.PHONY: version.h
|
||||
endif
|
||||
# "true" and "false" in the next few lines are Unix shell command names
|
||||
ifeq ($(GIT),none)
|
||||
GIT_PRESENT = false
|
||||
@@ -238,43 +208,51 @@ version.h:
|
||||
|
||||
ifeq (@MINGW32@,yes)
|
||||
ifeq ($(MAN),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi$(suffix).1
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
|
||||
else
|
||||
ifeq ($(PS2PDF),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi$(suffix).1
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
|
||||
else
|
||||
INSTALL_DOC = $(prefix)/iverilog-vpi$(suffix).pdf $(mandir)/man1/iverilog-vpi$(suffix).1
|
||||
INSTALL_DOC = $(prefix)/iverilog-vpi.pdf $(mandir)/man1/iverilog-vpi.1
|
||||
all: dep iverilog-vpi.pdf
|
||||
endif
|
||||
endif
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
else
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi$(suffix).1
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
endif
|
||||
|
||||
ifeq (@MINGW32@,yes)
|
||||
WIN32_INSTALL =
|
||||
WIN32_INSTALL = $(prefix)/hello.vl $(prefix)/sqrt.vl $(prefix)/sqrt-virtex.v $(prefix)/QUICK_START.txt
|
||||
else
|
||||
WIN32_INSTALL = $(bindir)/iverilog-vpi$(suffix)
|
||||
WIN32_INSTALL = $(bindir)/iverilog-vpi
|
||||
endif
|
||||
|
||||
install: all installdirs $(libdir)/ivl$(suffix)/ivl@EXEEXT@ $(libdir)/ivl$(suffix)/include/constants.vams $(libdir)/ivl$(suffix)/include/disciplines.vams $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
|
||||
XNF_INSTALL = $(libdir)/ivl/xnf.conf $(libdir)/ivl/xnf-s.conf
|
||||
|
||||
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/include/constants.vams $(libdir)/ivl/include/disciplines.vams $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
for dir in vpi ivlpp driver; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
|
||||
$(bindir)/iverilog-vpi$(suffix): ./iverilog-vpi
|
||||
$(INSTALL_SCRIPT) ./iverilog-vpi $(DESTDIR)$(bindir)/iverilog-vpi$(suffix)
|
||||
$(bindir)/iverilog-vpi: ./iverilog-vpi
|
||||
$(INSTALL_SCRIPT) ./iverilog-vpi $(DESTDIR)$(bindir)/iverilog-vpi
|
||||
|
||||
$(libdir)/ivl$(suffix)/ivl@EXEEXT@: ./ivl@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(DESTDIR)$(libdir)/ivl$(suffix)/ivl@EXEEXT@
|
||||
$(libdir)/ivl/ivl@EXEEXT@: ./ivl@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(DESTDIR)$(libdir)/ivl/ivl@EXEEXT@
|
||||
|
||||
$(libdir)/ivl$(suffix)/include/constants.vams: $(srcdir)/constants.vams
|
||||
$(INSTALL_DATA) $(srcdir)/constants.vams $(DESTDIR)$(libdir)/ivl$(suffix)/include/constants.vams
|
||||
$(libdir)/ivl/include/constants.vams: $(srcdir)/constants.vams
|
||||
$(INSTALL_DATA) $(srcdir)/constants.vams $@
|
||||
|
||||
$(libdir)/ivl$(suffix)/include/disciplines.vams: $(srcdir)/disciplines.vams
|
||||
$(INSTALL_DATA) $(srcdir)/disciplines.vams $(DESTDIR)$(libdir)/ivl$(suffix)/include/disciplines.vams
|
||||
$(libdir)/ivl/include/disciplines.vams: $(srcdir)/disciplines.vams
|
||||
$(INSTALL_DATA) $(srcdir)/disciplines.vams $@
|
||||
|
||||
$(libdir)/ivl/xnf-s.conf: $(srcdir)/xnf-s.conf
|
||||
$(INSTALL_DATA) $(srcdir)/xnf-s.conf $(DESTDIR)$(libdir)/ivl/xnf-s.conf
|
||||
|
||||
$(libdir)/ivl/xnf.conf: $(srcdir)/xnf.conf
|
||||
$(INSTALL_DATA) $(srcdir)/xnf.conf $(DESTDIR)$(libdir)/ivl/xnf.conf
|
||||
|
||||
$(includedir)/ivl_target.h: $(srcdir)/ivl_target.h
|
||||
$(INSTALL_DATA) $(srcdir)/ivl_target.h $(DESTDIR)$(includedir)/ivl_target.h
|
||||
@@ -291,31 +269,49 @@ $(includedir)/acc_user.h: $(srcdir)/acc_user.h
|
||||
$(includedir)/veriuser.h: $(srcdir)/veriuser.h
|
||||
$(INSTALL_DATA) $(srcdir)/veriuser.h $(DESTDIR)$(includedir)/veriuser.h
|
||||
|
||||
$(mandir)/man1/iverilog-vpi$(suffix).1: $(srcdir)/iverilog-vpi.man
|
||||
$(INSTALL_DATA) $(srcdir)/iverilog-vpi.man $(DESTDIR)$(mandir)/man1/iverilog-vpi$(suffix).1
|
||||
$(mandir)/man1/iverilog-vpi.1: $(srcdir)/iverilog-vpi.man
|
||||
$(INSTALL_DATA) $(srcdir)/iverilog-vpi.man $(DESTDIR)$(mandir)/man1/iverilog-vpi.1
|
||||
|
||||
$(prefix)/iverilog-vpi$(suffix).pdf: iverilog-vpi.pdf
|
||||
$(INSTALL_DATA) iverilog-vpi.pdf $(DESTDIR)$(prefix)/iverilog-vpi$(suffix).pdf
|
||||
$(prefix)/iverilog-vpi.pdf: iverilog-vpi.pdf
|
||||
$(INSTALL_DATA) iverilog-vpi.pdf $(DESTDIR)$(prefix)/iverilog-vpi.pdf
|
||||
|
||||
# In windows installations, put a few examples and the quick_start
|
||||
# into the destination directory.
|
||||
ifeq (@MINGW32@,yes)
|
||||
$(prefix)/hello.vl: $(srcdir)/examples/hello.vl
|
||||
./dosify.exe $(srcdir)/examples/hello.vl tmp.vl
|
||||
mv tmp.vl $(prefix)/hello.vl
|
||||
|
||||
$(prefix)/sqrt.vl: $(srcdir)/examples/sqrt.vl
|
||||
./dosify.exe $(srcdir)/examples/sqrt.vl tmp.vl
|
||||
mv tmp.vl $(prefix)/sqrt.vl
|
||||
|
||||
$(prefix)/sqrt-virtex.v: $(srcdir)/examples/sqrt-virtex.v
|
||||
./dosify.exe $(srcdir)/examples/sqrt-virtex.v tmp.vl
|
||||
mv tmp.vl $(prefix)/sqrt-virtex.v
|
||||
|
||||
$(prefix)/QUICK_START.txt: $(srcdir)/QUICK_START.txt
|
||||
./dosify.exe $(srcdir)/QUICK_START.txt tmp.txt
|
||||
mv tmp.txt $(prefix)/QUICK_START.txt
|
||||
endif
|
||||
|
||||
installdirs: mkinstalldirs
|
||||
$(srcdir)/mkinstalldirs $(DESTDIR)$(bindir) $(DESTDIR)$(includedir) $(DESTDIR)$(libdir)/ivl$(suffix) \
|
||||
$(DESTDIR)$(libdir)/ivl$(suffix)/include $(DESTDIR)$(mandir) $(DESTDIR)$(mandir)/man1
|
||||
$(srcdir)/mkinstalldirs $(DESTDIR)$(bindir) $(DESTDIR)$(includedir) $(DESTDIR)$(libdir)/ivl \
|
||||
$(DESTDIR)$(libdir)/ivl/include $(DESTDIR)$(mandir) $(DESTDIR)$(mandir)/man1
|
||||
|
||||
uninstall:
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
for dir in vpi ivlpp driver; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
for f in ivl@EXEEXT@ include/constants.vams include/disciplines.vams; \
|
||||
do rm -f $(DESTDIR)$(libdir)/ivl$(suffix)/$$f; done
|
||||
-rmdir $(DESTDIR)$(libdir)/ivl$(suffix)/include
|
||||
-rmdir $(DESTDIR)$(libdir)/ivl$(suffix)
|
||||
for f in verilog$(suffix) iverilog-vpi$(suffix) gverilog$(suffix)@EXEEXT@; \
|
||||
for f in xnf.conf xnf-s.conf ivl@EXEEXT@ include/constants.vams include/disciplines.vams; \
|
||||
do rm -f $(DESTDIR)$(libdir)/ivl/$$f; done
|
||||
-rmdir $(DESTDIR)$(libdir)/ivl/include
|
||||
-rmdir $(DESTDIR)$(libdir)/ivl
|
||||
for f in verilog iverilog-vpi gverilog@EXEEXT@; \
|
||||
do rm -f $(DESTDIR)$(bindir)/$$f; done
|
||||
for f in ivl_target.h vpi_user.h _pli_types.h acc_user.h veriuser.h; \
|
||||
do rm -f $(DESTDIR)$(includedir)/$$f; done
|
||||
-test X$(suffix) = X || rmdir $(DESTDIR)/$(includedir)
|
||||
rm -f $(DESTDIR)$(mandir)/man1/iverilog-vpi$(suffix).1 $(DESTDIR)$(prefix)/iverilog-vpi$(suffix).pdf
|
||||
rm -f $(DESTDIR)$(mandir)/man1/iverilog-vpi.1 $(DESTDIR)$(prefix)/iverilog-vpi.pdf
|
||||
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O)
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
/* n is a permallocated string. */
|
||||
Module::Module(perm_string n)
|
||||
: PScope(n)
|
||||
: PScope(n, 0)
|
||||
{
|
||||
library_flag = false;
|
||||
default_nettype = NetNet::NONE;
|
||||
@@ -41,9 +41,19 @@ void Module::add_gate(PGate*gate)
|
||||
gates_.push_back(gate);
|
||||
}
|
||||
|
||||
void Module::add_task(perm_string name, PTask*task)
|
||||
{
|
||||
tasks_[name] = task;
|
||||
}
|
||||
|
||||
void Module::add_function(perm_string name, PFunction *func)
|
||||
{
|
||||
funcs_[name] = func;
|
||||
}
|
||||
|
||||
unsigned Module::port_count() const
|
||||
{
|
||||
return ports.size();
|
||||
return ports.count();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -51,10 +61,10 @@ unsigned Module::port_count() const
|
||||
* module. If the port is internally unconnected, return an empty
|
||||
* array.
|
||||
*/
|
||||
const vector<PEIdent*>& Module::get_port(unsigned idx) const
|
||||
const svector<PEIdent*>& Module::get_port(unsigned idx) const
|
||||
{
|
||||
assert(idx < ports.size());
|
||||
static const vector<PEIdent*> zero;
|
||||
assert(idx < ports.count());
|
||||
static svector<PEIdent*> zero;
|
||||
|
||||
if (ports[idx])
|
||||
return ports[idx]->expr;
|
||||
@@ -65,7 +75,7 @@ const vector<PEIdent*>& Module::get_port(unsigned idx) const
|
||||
unsigned Module::find_port(const char*name) const
|
||||
{
|
||||
assert(name != 0);
|
||||
for (unsigned idx = 0 ; idx < ports.size() ; idx += 1) {
|
||||
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
|
||||
if (ports[idx] == 0) {
|
||||
/* It is possible to have undeclared ports. These
|
||||
are ports that are skipped in the declaration,
|
||||
@@ -79,7 +89,7 @@ unsigned Module::find_port(const char*name) const
|
||||
return idx;
|
||||
}
|
||||
|
||||
return ports.size();
|
||||
return ports.count();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -22,8 +22,7 @@
|
||||
|
||||
# include <list>
|
||||
# include <map>
|
||||
# include <vector>
|
||||
# include <utility>
|
||||
# include "svector.h"
|
||||
# include "StringHeap.h"
|
||||
# include "HName.h"
|
||||
# include "named.h"
|
||||
@@ -59,7 +58,7 @@ class Module : public PScope, public LineInfo {
|
||||
public:
|
||||
struct port_t {
|
||||
perm_string name;
|
||||
vector<PEIdent*> expr;
|
||||
svector<PEIdent*> expr;
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -76,6 +75,40 @@ class Module : public PScope, public LineInfo {
|
||||
|
||||
NetNet::Type default_nettype;
|
||||
|
||||
struct range_t {
|
||||
// True if this is an exclude
|
||||
bool exclude_flag;
|
||||
// lower bound
|
||||
// If low_open_flag is false and low_expr=0, then use -inf
|
||||
bool low_open_flag;
|
||||
PExpr*low_expr;
|
||||
// upper bound
|
||||
// If high_open_flag is false and high_expr=0, then use +inf
|
||||
bool high_open_flag;
|
||||
PExpr*high_expr;
|
||||
// Next range description in list
|
||||
struct range_t*next;
|
||||
};
|
||||
|
||||
/* The module has parameters that are evaluated when the
|
||||
module is elaborated. During parsing, I put the parameters
|
||||
into this map. */
|
||||
struct param_expr_t : public LineInfo {
|
||||
param_expr_t() : type(IVL_VT_NO_TYPE), msb(0), lsb(0), signed_flag(false), expr(0), range(0) { }
|
||||
// Type information
|
||||
ivl_variable_type_t type;
|
||||
PExpr*msb;
|
||||
PExpr*lsb;
|
||||
bool signed_flag;
|
||||
// Value expression
|
||||
PExpr*expr;
|
||||
// If there are range constrants, list them here
|
||||
range_t*range;
|
||||
};
|
||||
map<perm_string,param_expr_t>parameters;
|
||||
map<perm_string,param_expr_t>localparams;
|
||||
|
||||
|
||||
/* specparams are simpler then other params, in that they have
|
||||
no type information. They are merely constant
|
||||
expressions. */
|
||||
@@ -85,8 +118,7 @@ class Module : public PScope, public LineInfo {
|
||||
new parameters within the module, but may be used to set
|
||||
values within this module (when instantiated) or in other
|
||||
instantiated modules. */
|
||||
typedef pair<pform_name_t,PExpr*> named_expr_t;
|
||||
list<named_expr_t>defparms;
|
||||
map<pform_name_t,PExpr*>defparms;
|
||||
|
||||
/* Parameters may be overridden at instantiation time;
|
||||
the overrides do not contain explicit parameter names,
|
||||
@@ -98,7 +130,7 @@ class Module : public PScope, public LineInfo {
|
||||
|
||||
/* This is an array of port descriptors, which is in turn a
|
||||
named array of PEident pointers. */
|
||||
vector<port_t*> ports;
|
||||
svector<port_t*> ports;
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
|
||||
@@ -106,10 +138,6 @@ class Module : public PScope, public LineInfo {
|
||||
set by the `timescale directive. */
|
||||
int time_unit, time_precision;
|
||||
|
||||
/* Task definitions within this module */
|
||||
map<perm_string,PTask*> tasks;
|
||||
map<perm_string,PFunction*> funcs;
|
||||
|
||||
/* The module has a list of genvars that may be used in
|
||||
various generate schemes. */
|
||||
map<perm_string,LineInfo*> genvars;
|
||||
@@ -124,9 +152,11 @@ class Module : public PScope, public LineInfo {
|
||||
perm_string mod_name() const { return pscope_name(); }
|
||||
|
||||
void add_gate(PGate*gate);
|
||||
void add_task(perm_string name, PTask*def);
|
||||
void add_function(perm_string name, PFunction*def);
|
||||
|
||||
unsigned port_count() const;
|
||||
const vector<PEIdent*>& get_port(unsigned idx) const;
|
||||
const svector<PEIdent*>& get_port(unsigned idx) const;
|
||||
unsigned find_port(const char*name) const;
|
||||
|
||||
PGate* get_gate(perm_string name);
|
||||
@@ -137,12 +167,14 @@ class Module : public PScope, public LineInfo {
|
||||
bool elaborate(Design*, NetScope*scope) const;
|
||||
|
||||
typedef map<perm_string,NetExpr*> replace_t;
|
||||
bool elaborate_scope(Design*, NetScope*scope, const replace_t&rep);
|
||||
bool elaborate_scope(Design*, NetScope*scope, const replace_t&rep) const;
|
||||
|
||||
bool elaborate_sig(Design*, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
list<PGate*> gates_;
|
||||
map<perm_string,PTask*> tasks_;
|
||||
map<perm_string,PFunction*> funcs_;
|
||||
|
||||
static void elaborate_parm_item_(perm_string name, const param_expr_t&cur,
|
||||
Design*des, NetScope*scope);
|
||||
|
||||
+5
-5
@@ -101,7 +101,7 @@ static NetExpr*calculate_val(Design*des, NetScope*scope, const PExpr*expr)
|
||||
return dex;
|
||||
}
|
||||
|
||||
static NetExpr* make_delay_nets(Design*des, NetScope*scope, NetExpr*expr)
|
||||
static NetExpr* make_delay_nets(Design*des, NetExpr*expr)
|
||||
{
|
||||
if (dynamic_cast<NetESignal*> (expr))
|
||||
return expr;
|
||||
@@ -109,7 +109,7 @@ static NetExpr* make_delay_nets(Design*des, NetScope*scope, NetExpr*expr)
|
||||
if (dynamic_cast<NetEConst*> (expr))
|
||||
return expr;
|
||||
|
||||
NetNet*sig = expr->synthesize(des, scope);
|
||||
NetNet*sig = expr->synthesize(des);
|
||||
if (sig == 0) {
|
||||
cerr << expr->get_fileline() << ": error: Expression " << *expr
|
||||
<< " is not suitable for delay expression." << endl;
|
||||
@@ -132,17 +132,17 @@ void PDelays::eval_delays(Design*des, NetScope*scope,
|
||||
if (delay_[0]) {
|
||||
rise_time = calculate_val(des, scope, delay_[0]);
|
||||
if (as_nets_flag)
|
||||
rise_time = make_delay_nets(des, scope, rise_time);
|
||||
rise_time = make_delay_nets(des, rise_time);
|
||||
|
||||
if (delay_[1]) {
|
||||
fall_time = calculate_val(des, scope, delay_[1]);
|
||||
if (as_nets_flag)
|
||||
fall_time = make_delay_nets(des, scope, fall_time);
|
||||
fall_time = make_delay_nets(des, fall_time);
|
||||
|
||||
if (delay_[2]) {
|
||||
decay_time = calculate_val(des, scope, delay_[2]);
|
||||
if (as_nets_flag)
|
||||
decay_time = make_delay_nets(des, scope, decay_time);
|
||||
decay_time = make_delay_nets(des, decay_time);
|
||||
|
||||
} else {
|
||||
if (rise_time < fall_time)
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PDelays.h,v 1.9 2006/01/03 05:22:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "svector.h"
|
||||
# include <string>
|
||||
@@ -69,4 +72,34 @@ class PDelays {
|
||||
|
||||
ostream& operator << (ostream&o, const PDelays&);
|
||||
|
||||
/*
|
||||
* $Log: PDelays.h,v $
|
||||
* Revision 1.9 2006/01/03 05:22:14 steve
|
||||
* Handle complex net node delays.
|
||||
*
|
||||
* Revision 1.8 2006/01/02 05:33:19 steve
|
||||
* Node delays can be more general expressions in structural contexts.
|
||||
*
|
||||
* Revision 1.7 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.6 2002/06/14 03:25:51 steve
|
||||
* Compiler portability.
|
||||
*
|
||||
* Revision 1.5 2001/12/29 20:19:31 steve
|
||||
* Do not delete delay expressions of UDP instances.
|
||||
*
|
||||
* Revision 1.4 2001/11/22 06:20:59 steve
|
||||
* Use NetScope instead of string for scope path.
|
||||
*
|
||||
* Revision 1.3 2001/01/16 02:44:17 steve
|
||||
* Use the iosfwd header if available.
|
||||
*
|
||||
* Revision 1.2 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1999/09/04 19:11:46 steve
|
||||
* Add support for delayed non-blocking assignments.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PEvent.cc,v 1.5 2004/02/19 06:57:10 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
@@ -35,3 +38,26 @@ perm_string PEvent::name() const
|
||||
return name_;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: PEvent.cc,v $
|
||||
* Revision 1.5 2004/02/19 06:57:10 steve
|
||||
* Memory and Event names use perm_string.
|
||||
*
|
||||
* Revision 1.4 2003/03/01 06:25:30 steve
|
||||
* Add the lex_strings string handler, and put
|
||||
* scope names and system task/function names
|
||||
* into this table. Also, permallocate event
|
||||
* names from the beginning.
|
||||
*
|
||||
* Revision 1.3 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.2 2001/07/25 03:10:48 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.1 2000/04/01 19:31:57 steve
|
||||
* Named events as far as the pform.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PEvent.h,v 1.9 2004/02/19 06:57:10 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "LineInfo.h"
|
||||
# include "StringHeap.h"
|
||||
@@ -51,4 +54,38 @@ class PEvent : public LineInfo {
|
||||
PEvent& operator= (const PEvent&);
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: PEvent.h,v $
|
||||
* Revision 1.9 2004/02/19 06:57:10 steve
|
||||
* Memory and Event names use perm_string.
|
||||
*
|
||||
* Revision 1.8 2003/03/01 06:25:30 steve
|
||||
* Add the lex_strings string handler, and put
|
||||
* scope names and system task/function names
|
||||
* into this table. Also, permallocate event
|
||||
* names from the beginning.
|
||||
*
|
||||
* Revision 1.7 2003/01/30 16:23:07 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.6 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.5 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
*
|
||||
* Revision 1.4 2001/01/16 02:44:18 steve
|
||||
* Use the iosfwd header if available.
|
||||
*
|
||||
* Revision 1.3 2000/04/09 17:44:30 steve
|
||||
* Catch event declarations during scope elaborate.
|
||||
*
|
||||
* Revision 1.2 2000/04/04 03:20:15 steve
|
||||
* Simulate named event trigger and waits.
|
||||
*
|
||||
* Revision 1.1 2000/04/01 19:31:57 steve
|
||||
* Named events as far as the pform.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2008 Stephen Williams <[email protected]>
|
||||
* Copyright (c) 1998-2007 Stephen Williams <[email protected]>
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -21,31 +21,28 @@
|
||||
|
||||
# include <iostream>
|
||||
|
||||
# include "compiler.h"
|
||||
# include "PExpr.h"
|
||||
# include "Module.h"
|
||||
# include "netmisc.h"
|
||||
# include <typeinfo>
|
||||
|
||||
PExpr::PExpr()
|
||||
{
|
||||
expr_type_ = IVL_VT_NO_TYPE;
|
||||
}
|
||||
|
||||
PExpr::~PExpr()
|
||||
{
|
||||
}
|
||||
|
||||
bool PExpr::has_aa_term(Design*, NetScope*) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PExpr::is_the_same(const PExpr*that) const
|
||||
{
|
||||
return typeid(this) == typeid(that);
|
||||
}
|
||||
|
||||
bool PExpr::is_constant(Module*) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
NetNet* PExpr::elaborate_lnet(Design*des, NetScope*) const
|
||||
{
|
||||
cerr << get_fileline() << ": error: expression not valid in assign l-value: "
|
||||
@@ -70,10 +67,9 @@ PEBinary::~PEBinary()
|
||||
{
|
||||
}
|
||||
|
||||
bool PEBinary::has_aa_term(Design*des, NetScope*scope) const
|
||||
bool PEBinary::is_constant(Module*mod) const
|
||||
{
|
||||
assert(left_ && right_);
|
||||
return left_->has_aa_term(des, scope) || right_->has_aa_term(des, scope);
|
||||
return left_->is_constant(mod) && right_->is_constant(mod);
|
||||
}
|
||||
|
||||
PEBComp::PEBComp(char op, PExpr*l, PExpr*r)
|
||||
@@ -85,36 +81,8 @@ PEBComp::~PEBComp()
|
||||
{
|
||||
}
|
||||
|
||||
PEBLogic::PEBLogic(char op, PExpr*l, PExpr*r)
|
||||
: PEBinary(op, l, r)
|
||||
{
|
||||
assert(op == 'a' || op == 'o');
|
||||
}
|
||||
|
||||
PEBLogic::~PEBLogic()
|
||||
{
|
||||
}
|
||||
|
||||
PEBLeftWidth::PEBLeftWidth(char op, PExpr*l, PExpr*r)
|
||||
: PEBinary(op, l, r)
|
||||
{
|
||||
}
|
||||
|
||||
PEBLeftWidth::~PEBLeftWidth()
|
||||
{
|
||||
}
|
||||
|
||||
PEBPower::PEBPower(char op, PExpr*l, PExpr*r)
|
||||
: PEBLeftWidth(op, l, r)
|
||||
{
|
||||
}
|
||||
|
||||
PEBPower::~PEBPower()
|
||||
{
|
||||
}
|
||||
|
||||
PEBShift::PEBShift(char op, PExpr*l, PExpr*r)
|
||||
: PEBLeftWidth(op, l, r)
|
||||
: PEBinary(op, l, r)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -122,7 +90,7 @@ PEBShift::~PEBShift()
|
||||
{
|
||||
}
|
||||
|
||||
PECallFunction::PECallFunction(const pform_name_t&n, const vector<PExpr *> &parms)
|
||||
PECallFunction::PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms)
|
||||
: path_(n), parms_(parms)
|
||||
{
|
||||
}
|
||||
@@ -135,7 +103,7 @@ static pform_name_t pn_from_ps(perm_string n)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
PECallFunction::PECallFunction(perm_string n, const vector<PExpr*>&parms)
|
||||
PECallFunction::PECallFunction(perm_string n, const svector<PExpr*>&parms)
|
||||
: path_(pn_from_ps(n)), parms_(parms)
|
||||
{
|
||||
}
|
||||
@@ -145,33 +113,22 @@ PECallFunction::PECallFunction(perm_string n)
|
||||
{
|
||||
}
|
||||
|
||||
// NOTE: Anachronism. Try to work all use of svector out.
|
||||
PECallFunction::PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms)
|
||||
: path_(n), parms_(vector_from_svector(parms))
|
||||
{
|
||||
}
|
||||
|
||||
PECallFunction::PECallFunction(perm_string n, const svector<PExpr*>&parms)
|
||||
: path_(pn_from_ps(n)), parms_(vector_from_svector(parms))
|
||||
{
|
||||
}
|
||||
|
||||
PECallFunction::~PECallFunction()
|
||||
{
|
||||
}
|
||||
|
||||
bool PECallFunction::has_aa_term(Design*des, NetScope*scope) const
|
||||
PEConcat::PEConcat(const svector<PExpr*>&p, PExpr*r)
|
||||
: parms_(p), repeat_(r)
|
||||
{
|
||||
bool flag = false;
|
||||
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
|
||||
flag = parms_[idx]->has_aa_term(des, scope) || flag;
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
PEConcat::PEConcat(const svector<PExpr*>&p, PExpr*r)
|
||||
: parms_(p), tested_widths_(p.count()), repeat_(r)
|
||||
bool PEConcat::is_constant(Module *mod) const
|
||||
{
|
||||
bool constant = repeat_? repeat_->is_constant(mod) : true;
|
||||
for (unsigned i = 0; constant && i < parms_.count(); ++i) {
|
||||
constant = constant && parms_[i]->is_constant(mod);
|
||||
}
|
||||
return constant;
|
||||
}
|
||||
|
||||
PEConcat::~PEConcat()
|
||||
@@ -179,18 +136,6 @@ PEConcat::~PEConcat()
|
||||
delete repeat_;
|
||||
}
|
||||
|
||||
bool PEConcat::has_aa_term(Design*des, NetScope*scope) const
|
||||
{
|
||||
bool flag = false;
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
flag = parms_[idx]->has_aa_term(des, scope) || flag;
|
||||
}
|
||||
if (repeat_)
|
||||
flag = repeat_->has_aa_term(des, scope) || flag;
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
PEEvent::PEEvent(PEEvent::edge_t t, PExpr*e)
|
||||
: type_(t), expr_(e)
|
||||
{
|
||||
@@ -205,12 +150,6 @@ PEEvent::edge_t PEEvent::type() const
|
||||
return type_;
|
||||
}
|
||||
|
||||
bool PEEvent::has_aa_term(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(expr_);
|
||||
return expr_->has_aa_term(des, scope);
|
||||
}
|
||||
|
||||
PExpr* PEEvent::expr() const
|
||||
{
|
||||
return expr_;
|
||||
@@ -231,6 +170,11 @@ const verireal& PEFNumber::value() const
|
||||
return *value_;
|
||||
}
|
||||
|
||||
bool PEFNumber::is_constant(Module*) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
PEIdent::PEIdent(const pform_name_t&that)
|
||||
: path_(that)
|
||||
{
|
||||
@@ -245,20 +189,35 @@ PEIdent::~PEIdent()
|
||||
{
|
||||
}
|
||||
|
||||
bool PEIdent::has_aa_term(Design*des, NetScope*scope) const
|
||||
/*
|
||||
* An identifier can be in a constant expression if (and only if) it is
|
||||
* a parameter or genvar.
|
||||
*
|
||||
* NOTE: This test does not work if the name is hierarchical!
|
||||
*/
|
||||
bool PEIdent::is_constant(Module*mod) const
|
||||
{
|
||||
NetNet* net = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
if (mod == 0) return false;
|
||||
|
||||
const NetExpr*ex1, *ex2;
|
||||
/* */
|
||||
perm_string tmp = path_.back().name;
|
||||
|
||||
scope = symbol_search(0, des, scope, path_, net, par, eve, ex1, ex2);
|
||||
{ map<perm_string,Module::param_expr_t>::const_iterator cur;
|
||||
cur = mod->parameters.find(tmp);
|
||||
if (cur != mod->parameters.end()) return true;
|
||||
}
|
||||
|
||||
if (scope)
|
||||
return scope->is_auto();
|
||||
else
|
||||
return false;
|
||||
{ map<perm_string,Module::param_expr_t>::const_iterator cur;
|
||||
cur = mod->localparams.find(tmp);
|
||||
if (cur != mod->localparams.end()) return true;
|
||||
}
|
||||
|
||||
{ map<perm_string,LineInfo*>::const_iterator cur;
|
||||
cur = mod->genvars.find(tmp);
|
||||
if (cur != mod->genvars.end()) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
PENumber::PENumber(verinum*vp)
|
||||
@@ -286,6 +245,11 @@ bool PENumber::is_the_same(const PExpr*that) const
|
||||
return *value_ == *obj->value_;
|
||||
}
|
||||
|
||||
bool PENumber::is_constant(Module*) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
PEString::PEString(char*s)
|
||||
: text_(s)
|
||||
{
|
||||
@@ -301,6 +265,11 @@ string PEString::value() const
|
||||
return text_;
|
||||
}
|
||||
|
||||
bool PEString::is_constant(Module*) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
PETernary::PETernary(PExpr*e, PExpr*t, PExpr*f)
|
||||
: expr_(e), tru_(t), fal_(f)
|
||||
{
|
||||
@@ -310,12 +279,11 @@ PETernary::~PETernary()
|
||||
{
|
||||
}
|
||||
|
||||
bool PETernary::has_aa_term(Design*des, NetScope*scope) const
|
||||
bool PETernary::is_constant(Module*m) const
|
||||
{
|
||||
assert(expr_ && tru_ && fal_);
|
||||
return expr_->has_aa_term(des, scope)
|
||||
|| tru_->has_aa_term(des, scope)
|
||||
|| fal_->has_aa_term(des, scope);
|
||||
return expr_->is_constant(m)
|
||||
&& tru_->is_constant(m)
|
||||
&& fal_->is_constant(m);
|
||||
}
|
||||
|
||||
PEUnary::PEUnary(char op, PExpr*ex)
|
||||
@@ -327,8 +295,8 @@ PEUnary::~PEUnary()
|
||||
{
|
||||
}
|
||||
|
||||
bool PEUnary::has_aa_term(Design*des, NetScope*scope) const
|
||||
bool PEUnary::is_constant(Module*m) const
|
||||
{
|
||||
assert(expr_);
|
||||
return expr_->has_aa_term(des, scope);
|
||||
return expr_->is_constant(m);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
# include <string>
|
||||
# include <vector>
|
||||
# include <valarray>
|
||||
# include "netlist.h"
|
||||
# include "verinum.h"
|
||||
# include "LineInfo.h"
|
||||
@@ -37,6 +36,9 @@ class NetScope;
|
||||
* The PExpr class hierarchy supports the description of
|
||||
* expressions. The parser can generate expression objects from the
|
||||
* source, possibly reducing things that it knows how to reduce.
|
||||
*
|
||||
* The elaborate_net method is used by structural elaboration to build
|
||||
* up a netlist interpretation of the expression.
|
||||
*/
|
||||
|
||||
class PExpr : public LineInfo {
|
||||
@@ -47,15 +49,11 @@ class PExpr : public LineInfo {
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
// This method tests whether the expression contains any
|
||||
// references to automatically allocated variables.
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
// This method tests the width that the expression wants to
|
||||
// be. It is used by elaboration of assignments to figure out
|
||||
// the width of the expression.
|
||||
//
|
||||
// The "min" is the width of the local context, so is the
|
||||
// The "min" is the width of the local context, so it the
|
||||
// minimum width that this function should return. Initially
|
||||
// this is the same as the lval width.
|
||||
//
|
||||
@@ -68,22 +66,13 @@ class PExpr : public LineInfo {
|
||||
// the subexpression should not make l-value related
|
||||
// optimizations.
|
||||
//
|
||||
// The expr_type is an output argument that gives the
|
||||
// calculated type for the expression.
|
||||
//
|
||||
// The unsized_flag is set to true if the expression is
|
||||
// The unsigned_flag is set to true if the expression is
|
||||
// unsized and therefore expandable. This happens if a
|
||||
// sub-expression is an unsized literal. Some expressions make
|
||||
// special use of that.
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&unsized_flag);
|
||||
|
||||
// After the test_width method is complete, these methods
|
||||
// return valid results.
|
||||
ivl_variable_type_t expr_type() const { return expr_type_; }
|
||||
unsigned expr_width() const { return expr_width_; }
|
||||
bool&unsized_flag) const;
|
||||
|
||||
// During the elaborate_sig phase, we may need to scan
|
||||
// expressions to find implicit net declarations.
|
||||
@@ -109,6 +98,17 @@ class PExpr : public LineInfo {
|
||||
// evaluation of parameters.
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
|
||||
// This method elaborate the expression as gates, for use in a
|
||||
// continuous assign or other wholly structural context.
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0 =Link::STRONG,
|
||||
Link::strength_t drive1 =Link::STRONG)
|
||||
const;
|
||||
|
||||
// This method elaborates the expression as gates, but
|
||||
// restricted for use as l-values of continuous assignments.
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
|
||||
@@ -138,12 +138,11 @@ class PExpr : public LineInfo {
|
||||
// expressions that must be structurally "identical".
|
||||
virtual bool is_the_same(const PExpr*that) const;
|
||||
|
||||
protected:
|
||||
// The derived class test_width methods should fill these in.
|
||||
ivl_variable_type_t expr_type_;
|
||||
unsigned expr_width_;
|
||||
|
||||
static void suppress_binary_operand_sign_if_needed_(NetExpr*lp, NetExpr*rp);
|
||||
// Return true if this expression is a valid constant
|
||||
// expression. the Module pointer is needed to find parameter
|
||||
// identifiers and any other module specific interpretations
|
||||
// of expressions.
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
private: // not implemented
|
||||
PExpr(const PExpr&);
|
||||
@@ -161,31 +160,30 @@ class PEConcat : public PExpr {
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&unsized_flag);
|
||||
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
|
||||
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
virtual NetEConcat*elaborate_pexpr(Design*des, NetScope*) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const;
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
private:
|
||||
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
bool bidirectional_flag) const;
|
||||
private:
|
||||
svector<PExpr*>parms_;
|
||||
std::valarray<unsigned>tested_widths_;
|
||||
|
||||
PExpr*repeat_;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -210,8 +208,6 @@ class PEEvent : public PExpr {
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
edge_t type_;
|
||||
PExpr *expr_;
|
||||
@@ -233,14 +229,21 @@ class PEFNumber : public PExpr {
|
||||
any rounding that is needed to get the value. */
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&unsized_flag);
|
||||
/* A PEFNumber is a constant, so this returns true. */
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
private:
|
||||
@@ -259,13 +262,9 @@ class PEIdent : public PExpr {
|
||||
void append_name(perm_string);
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&unsized_flag);
|
||||
bool&unsized_flag) const;
|
||||
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
@@ -279,6 +278,15 @@ class PEIdent : public PExpr {
|
||||
NetScope*scope,
|
||||
bool is_force) const;
|
||||
|
||||
// Structural r-values are OK.
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
@@ -287,6 +295,7 @@ class PEIdent : public PExpr {
|
||||
// only applies to Ident expressions.
|
||||
NetNet* elaborate_port(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
const pform_name_t& path() const { return path_; }
|
||||
@@ -306,19 +315,17 @@ class PEIdent : public PExpr {
|
||||
|
||||
private:
|
||||
NetAssign_*elaborate_lval_net_word_(Design*, NetScope*, NetNet*) const;
|
||||
bool elaborate_lval_net_bit_(Design*, NetScope*, NetAssign_*) const;
|
||||
bool elaborate_lval_net_part_(Design*, NetScope*, NetAssign_*) const;
|
||||
bool elaborate_lval_net_idx_(Design*, NetScope*, NetAssign_*,
|
||||
index_component_t::ctype_t) const;
|
||||
|
||||
private:
|
||||
NetExpr*elaborate_expr_param_(Design*des,
|
||||
NetScope*scope,
|
||||
const NetExpr*par,
|
||||
NetScope*found,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb,
|
||||
int expr_wid) const;
|
||||
NetExpr*elaborate_expr_param(Design*des,
|
||||
NetScope*scope,
|
||||
const NetExpr*par,
|
||||
NetScope*found,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb) const;
|
||||
NetExpr*elaborate_expr_param_part_(Design*des,
|
||||
NetScope*scope,
|
||||
const NetExpr*par,
|
||||
@@ -358,6 +365,38 @@ class PEIdent : public PExpr {
|
||||
NetESignal*net,
|
||||
NetScope*found) const;
|
||||
|
||||
public:
|
||||
|
||||
NetNet* elaborate_net_array_(Design*des, NetScope*scope,
|
||||
NetNet*sig, unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
|
||||
NetNet* elaborate_net_net_(Design*des, NetScope*scope,
|
||||
NetNet*sig, unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
NetNet* elaborate_net_net_idx_up_(Design*des, NetScope*scope,
|
||||
NetNet*sig, unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
NetNet* elaborate_net_bitmux_(Design*des, NetScope*scope,
|
||||
NetNet*sig,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
|
||||
private:
|
||||
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
bool bidirectional_flag) const;
|
||||
@@ -366,6 +405,8 @@ class PEIdent : public PExpr {
|
||||
|
||||
bool eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||
long&midx, long&lidx) const;
|
||||
NetNet*process_select_(Design*des, NetScope*scope, NetNet*sig) const;
|
||||
|
||||
};
|
||||
|
||||
class PENumber : public PExpr {
|
||||
@@ -379,9 +420,15 @@ class PENumber : public PExpr {
|
||||
virtual void dump(ostream&) const;
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&unsized_flag);
|
||||
bool&unsized_flag) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
@@ -392,6 +439,7 @@ class PENumber : public PExpr {
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual bool is_the_same(const PExpr*that) const;
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
private:
|
||||
verinum*const value_;
|
||||
@@ -415,14 +463,22 @@ class PEString : public PExpr {
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&unsized_flag);
|
||||
bool&unsized_flag) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool) const;
|
||||
virtual NetEConst*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
verinum* eval_const(Design*, NetScope*) const;
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
private:
|
||||
char*text_;
|
||||
};
|
||||
@@ -435,22 +491,47 @@ class PEUnary : public PExpr {
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&unsized_flag);
|
||||
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
private:
|
||||
NetExpr* elaborate_expr_bits_(NetExpr*operand, int expr_wid) const;
|
||||
NetNet* elab_net_uminus_const_logic_(Design*des, NetScope*scope,
|
||||
NetEConst*expr,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
NetNet* elab_net_uminus_const_real_(Design*des, NetScope*scope,
|
||||
NetECReal*expr,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
NetNet* elab_net_unary_real_(Design*des, NetScope*scope,
|
||||
NetExpr*expr,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
|
||||
private:
|
||||
char op_;
|
||||
@@ -463,17 +544,23 @@ class PEBinary : public PExpr {
|
||||
explicit PEBinary(char op, PExpr*l, PExpr*r);
|
||||
~PEBinary();
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&unsized_flag);
|
||||
bool&unsized_flag) const;
|
||||
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
@@ -487,13 +574,54 @@ class PEBinary : public PExpr {
|
||||
NetExpr*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
|
||||
NetExpr*elaborate_eval_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
|
||||
|
||||
NetExpr*elaborate_expr_base_bits_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
|
||||
NetExpr*elaborate_expr_base_div_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
|
||||
NetExpr*elaborate_expr_base_lshift_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
|
||||
NetExpr*elaborate_expr_base_rshift_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
|
||||
NetExpr*elaborate_expr_base_mult_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
|
||||
NetExpr*elaborate_expr_base_add_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
|
||||
static void suppress_operand_sign_if_needed_(NetExpr*lp, NetExpr*rp);
|
||||
|
||||
private:
|
||||
NetNet* elaborate_net_add_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_bit_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_cmp_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_div_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_mod_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_log_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_mul_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_pow_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_shift_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -508,78 +636,20 @@ class PEBComp : public PEBinary {
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&flag);
|
||||
bool&flag) const;
|
||||
|
||||
NetExpr* elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
};
|
||||
|
||||
/*
|
||||
* This derived class is for handling logical expressions: && and ||.
|
||||
*/
|
||||
class PEBLogic : public PEBinary {
|
||||
|
||||
public:
|
||||
explicit PEBLogic(char op, PExpr*l, PExpr*r);
|
||||
~PEBLogic();
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&flag);
|
||||
|
||||
NetExpr* elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
};
|
||||
|
||||
/*
|
||||
* A couple of the binary operands have a special sub-expression rule
|
||||
* where the expression width is carried entirely by the left
|
||||
* expression, and the right operand is self-determined.
|
||||
*/
|
||||
class PEBLeftWidth : public PEBinary {
|
||||
|
||||
public:
|
||||
explicit PEBLeftWidth(char op, PExpr*l, PExpr*r);
|
||||
~PEBLeftWidth() =0;
|
||||
|
||||
virtual NetExpr*elaborate_expr_leaf(Design*des, NetExpr*lp, NetExpr*rp,
|
||||
int expr_wid) const =0;
|
||||
|
||||
protected:
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&flag);
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*scope) const;
|
||||
|
||||
};
|
||||
|
||||
class PEBPower : public PEBLeftWidth {
|
||||
|
||||
public:
|
||||
explicit PEBPower(char op, PExpr*l, PExpr*r);
|
||||
~PEBPower();
|
||||
|
||||
NetExpr*elaborate_expr_leaf(Design*des, NetExpr*lp, NetExpr*rp,
|
||||
int expr_wid) const;
|
||||
};
|
||||
|
||||
class PEBShift : public PEBLeftWidth {
|
||||
class PEBShift : public PEBinary {
|
||||
|
||||
public:
|
||||
explicit PEBShift(char op, PExpr*l, PExpr*r);
|
||||
~PEBShift();
|
||||
|
||||
NetExpr*elaborate_expr_leaf(Design*des, NetExpr*lp, NetExpr*rp,
|
||||
int expr_wid) const;
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval, bool&flag) const;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -592,18 +662,23 @@ class PETernary : public PExpr {
|
||||
explicit PETernary(PExpr*e, PExpr*t, PExpr*f);
|
||||
~PETernary();
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&unsized_flag);
|
||||
bool&unsized_flag) const;
|
||||
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetETernary*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
virtual NetETernary*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
@@ -621,42 +696,45 @@ class PETernary : public PExpr {
|
||||
*/
|
||||
class PECallFunction : public PExpr {
|
||||
public:
|
||||
explicit PECallFunction(const pform_name_t&n, const vector<PExpr *> &parms);
|
||||
// Call of system function (name is not hierarchical)
|
||||
explicit PECallFunction(perm_string n, const vector<PExpr *> &parms);
|
||||
explicit PECallFunction(perm_string n);
|
||||
|
||||
// svector versions. Should be removed!
|
||||
explicit PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms);
|
||||
// Call of system function (name is not hierarchical)
|
||||
explicit PECallFunction(perm_string n, const svector<PExpr *> &parms);
|
||||
|
||||
explicit PECallFunction(perm_string n);
|
||||
~PECallFunction();
|
||||
|
||||
virtual void dump(ostream &) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_wid, bool sys_task_arg) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&unsized_flag);
|
||||
bool&unsized_flag) const;
|
||||
|
||||
private:
|
||||
pform_name_t path_;
|
||||
vector<PExpr *> parms_;
|
||||
svector<PExpr *> parms_;
|
||||
|
||||
bool check_call_matches_definition_(Design*des, NetScope*dscope) const;
|
||||
|
||||
NetExpr* elaborate_sfunc_(Design*des, NetScope*scope, int expr_wid) const;
|
||||
NetExpr* elaborate_access_func_(Design*des, NetScope*scope, ivl_nature_t) const;
|
||||
NetNet* elaborate_net_sfunc_(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
unsigned test_width_sfunc_(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&unsized_flag);
|
||||
bool&unsized_flag) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+1
-2
@@ -21,10 +21,9 @@
|
||||
|
||||
#include "PTask.h"
|
||||
|
||||
PFunction::PFunction(perm_string name, PScope*parent, bool is_auto__)
|
||||
PFunction::PFunction(perm_string name, PScope*parent)
|
||||
: PScope(name, parent), ports_(0), statement_(0)
|
||||
{
|
||||
is_auto_ = is_auto__;
|
||||
return_type_.type = PTF_NONE;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PGate_H
|
||||
#define __PGate_H
|
||||
/*
|
||||
* Copyright (c) 1998-2008 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2004 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -18,6 +18,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PGate.h,v 1.32 2006/04/10 00:37:42 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "svector.h"
|
||||
# include "StringHeap.h"
|
||||
@@ -80,7 +83,7 @@ class PGate : public LineInfo {
|
||||
bool as_net_flag =false) const;
|
||||
|
||||
unsigned pin_count() const { return pins_? pins_->count() : 0; }
|
||||
PExpr*pin(unsigned idx) const { return (*pins_)[idx]; }
|
||||
const PExpr*pin(unsigned idx) const { return (*pins_)[idx]; }
|
||||
|
||||
strength_t strength0() const;
|
||||
strength_t strength1() const;
|
||||
@@ -167,16 +170,8 @@ class PGBuiltin : public PGate {
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
unsigned calculate_array_count_(Design*, NetScope*,
|
||||
long&high, long&low) const;
|
||||
|
||||
unsigned calculate_output_count_(void) const;
|
||||
|
||||
NetNode* create_gate_for_output_(Design*, NetScope*,
|
||||
perm_string gate_name,
|
||||
unsigned instance_width) const;
|
||||
|
||||
Type type_;
|
||||
|
||||
PExpr*msb_;
|
||||
PExpr*lsb_;
|
||||
};
|
||||
@@ -237,17 +232,15 @@ class PGModule : public PGate {
|
||||
PExpr*msb_;
|
||||
PExpr*lsb_;
|
||||
|
||||
friend class delayed_elaborate_scope_mod_instances;
|
||||
void elaborate_mod_(Design*, Module*mod, NetScope*scope) const;
|
||||
void elaborate_udp_(Design*, PUdp *udp, NetScope*scope) const;
|
||||
void elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const;
|
||||
void elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*sc) const;
|
||||
bool elaborate_sig_mod_(Design*des, NetScope*scope, Module*mod) const;
|
||||
bool elaborate_sig_udp_(Design*des, NetScope*scope, PUdp*udp) const;
|
||||
|
||||
NetNet*resize_net_to_port_(Design*des, NetScope*scope,
|
||||
NetNet*sig, unsigned port_wid,
|
||||
NetNet::PortType dir, bool as_signed) const;
|
||||
NetNet::PortType dir) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+14
-72
@@ -16,96 +16,38 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PGenerate.cc,v 1.4 2007/06/02 03:42:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PGenerate.h"
|
||||
# include "PWire.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
PGenerate::PGenerate(unsigned id)
|
||||
: id_number(id)
|
||||
{
|
||||
direct_nested_ = false;
|
||||
parent = 0;
|
||||
lexical_scope = 0;
|
||||
}
|
||||
|
||||
PGenerate::~PGenerate()
|
||||
{
|
||||
}
|
||||
|
||||
PWire* PGenerate::get_wire(perm_string name) const
|
||||
{
|
||||
map<perm_string,PWire*>::const_iterator obj = wires.find(name);
|
||||
if (obj == wires.end())
|
||||
return 0;
|
||||
else
|
||||
return (*obj).second;
|
||||
}
|
||||
|
||||
void PGenerate::add_gate(PGate*gate)
|
||||
{
|
||||
gates.push_back(gate);
|
||||
}
|
||||
|
||||
void PGenerate::probe_for_direct_nesting_(void)
|
||||
void PGenerate::add_behavior(PProcess*proc)
|
||||
{
|
||||
direct_nested_ = false;
|
||||
|
||||
ivl_assert(*this, scheme_type==GS_CASE_ITEM || scheme_type==GS_CONDIT || scheme_type==GS_ELSE);
|
||||
|
||||
// If this scheme has received an explicit name, then it
|
||||
// cannot be direct nested.
|
||||
if (scope_name[0] != '$') return;
|
||||
|
||||
if (tasks.size() > 0) return;
|
||||
if (funcs.size() > 0) return;
|
||||
if (gates.size() > 0) return;
|
||||
if (parameters.size() > 0) return;
|
||||
if (localparams.size() > 0) return;
|
||||
if (events.size() > 0) return;
|
||||
if (wires.size() > 0) return;
|
||||
if (behaviors.size() > 0) return;
|
||||
if (analog_behaviors.size() > 0) return;
|
||||
|
||||
if (generate_schemes.size() == 0) return;
|
||||
|
||||
switch (generate_schemes.size()) {
|
||||
case 1: {
|
||||
PGenerate*child = generate_schemes.front();
|
||||
if (child->scheme_type == GS_CONDIT)
|
||||
direct_nested_ = true;
|
||||
if (child->scheme_type == GS_CASE)
|
||||
direct_nested_ = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
PGenerate*child1 = generate_schemes.front();
|
||||
PGenerate*child2 = generate_schemes.back();
|
||||
if (child1->scheme_type==GS_CONDIT && child2->scheme_type==GS_ELSE)
|
||||
direct_nested_ = true;
|
||||
if (child2->scheme_type==GS_CONDIT && child1->scheme_type==GS_ELSE)
|
||||
direct_nested_ = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ostream& operator << (ostream&out, PGenerate::scheme_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case PGenerate::GS_NONE:
|
||||
out << "GS_NONE";
|
||||
break;
|
||||
case PGenerate::GS_LOOP:
|
||||
out << "GS_LOOP";
|
||||
break;
|
||||
case PGenerate::GS_CONDIT:
|
||||
out << "GS_CONDIT";
|
||||
break;
|
||||
case PGenerate::GS_ELSE:
|
||||
out << "GS_ELSE";
|
||||
break;
|
||||
case PGenerate::GS_CASE:
|
||||
out << "GS_CASE";
|
||||
break;
|
||||
case PGenerate::GS_CASE_ITEM:
|
||||
out << "GS_CASE_ITEM";
|
||||
break;
|
||||
case PGenerate::GS_NBLOCK:
|
||||
out << "GS_NBLOCK";
|
||||
break;
|
||||
}
|
||||
return out;
|
||||
behaviors.push_back(proc);
|
||||
}
|
||||
|
||||
+13
-34
@@ -1,7 +1,7 @@
|
||||
#ifndef __PGenerate_H
|
||||
#define __PGenerate_H
|
||||
/*
|
||||
* Copyright (c) 2006-2008 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2006 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -18,22 +18,21 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PGenerate.h,v 1.4 2007/06/02 03:42:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "LineInfo.h"
|
||||
# include "StringHeap.h"
|
||||
# include "HName.h"
|
||||
# include "PScope.h"
|
||||
# include <list>
|
||||
# include <map>
|
||||
# include <valarray>
|
||||
# include "pform_types.h"
|
||||
|
||||
class Design;
|
||||
class NetScope;
|
||||
class PExpr;
|
||||
class PFunction;
|
||||
class PProcess;
|
||||
class PTask;
|
||||
class PGate;
|
||||
class PWire;
|
||||
|
||||
@@ -50,10 +49,10 @@ class PWire;
|
||||
* The parent points to the GS_CASE that contains this item.
|
||||
* the loop_test is compared with the parent->loop_test expression.
|
||||
*/
|
||||
class PGenerate : public LineInfo, public LexicalScope {
|
||||
class PGenerate : public LineInfo {
|
||||
|
||||
public:
|
||||
explicit PGenerate(unsigned id_number);
|
||||
PGenerate(unsigned id_number);
|
||||
~PGenerate();
|
||||
|
||||
// Generate schemes have an ID number, for when the scope is
|
||||
@@ -61,12 +60,8 @@ class PGenerate : public LineInfo, public LexicalScope {
|
||||
const unsigned id_number;
|
||||
perm_string scope_name;
|
||||
|
||||
// This is used during parsing to stack lexical scopes within
|
||||
// this generate scheme.
|
||||
PScope*lexical_scope;
|
||||
|
||||
enum scheme_t {GS_NONE, GS_LOOP, GS_CONDIT, GS_ELSE,
|
||||
GS_CASE, GS_CASE_ITEM, GS_NBLOCK};
|
||||
GS_CASE, GS_CASE_ITEM};
|
||||
scheme_t scheme_type;
|
||||
|
||||
// generate loops have an index variable and three
|
||||
@@ -75,20 +70,17 @@ class PGenerate : public LineInfo, public LexicalScope {
|
||||
PExpr*loop_init;
|
||||
PExpr*loop_test;
|
||||
PExpr*loop_step;
|
||||
// Case items may have multiple guard expression values. It is
|
||||
// enough for any on of the guards to match the case statement
|
||||
// test value.
|
||||
std::valarray<PExpr*> item_test;
|
||||
|
||||
map<perm_string,PWire*>wires;
|
||||
PWire* get_wire(perm_string name) const;
|
||||
|
||||
list<PGate*> gates;
|
||||
void add_gate(PGate*);
|
||||
|
||||
// Tasks instantiated within this scheme.
|
||||
map<perm_string,PTask*> tasks;
|
||||
map<perm_string,PFunction*>funcs;
|
||||
list<PProcess*> behaviors;
|
||||
void add_behavior(PProcess*behave);
|
||||
|
||||
// Generate schemes can contain further generate schemes.
|
||||
list<PGenerate*> generate_schemes;
|
||||
list<PGenerate*> generates;
|
||||
PGenerate*parent;
|
||||
|
||||
// This method is called by the elaboration of a module to
|
||||
@@ -107,32 +99,19 @@ class PGenerate : public LineInfo, public LexicalScope {
|
||||
bool generate_scope_loop_(Design*des, NetScope*container);
|
||||
bool generate_scope_condit_(Design*des, NetScope*container, bool else_flag);
|
||||
bool generate_scope_case_(Design*des, NetScope*container);
|
||||
bool generate_scope_nblock_(Design*des, NetScope*container);
|
||||
|
||||
// Call probe during elaborate_scope to calulate the
|
||||
// directed_nested_ flag. It is OK to store the direct_nested_
|
||||
// information here because "direct nested" is a property of
|
||||
// the lexical generate code.
|
||||
void probe_for_direct_nesting_(void);
|
||||
bool direct_nested_;
|
||||
|
||||
// Elaborate_scope within a generated scope.
|
||||
void elaborate_subscope_(Design*des, NetScope*scope);
|
||||
void elaborate_subscope_direct_(Design*des, NetScope*scope);
|
||||
|
||||
// These are the scopes created by generate_scope.
|
||||
list<NetScope*>scope_list_;
|
||||
// internal function called on each scope generated by this scheme.
|
||||
bool elaborate_sig_(Design*des, NetScope*scope) const;
|
||||
bool elaborate_sig_direct_(Design*des, NetScope*scope) const;
|
||||
bool elaborate_(Design*des, NetScope*scope) const;
|
||||
bool elaborate_direct_(Design*des, NetScope*scope) const;
|
||||
|
||||
private: // not implemented
|
||||
PGenerate(const PGenerate&);
|
||||
PGenerate& operator= (const PGenerate&);
|
||||
};
|
||||
|
||||
extern std::ostream& operator << (std::ostream&, PGenerate::scheme_t);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -19,13 +19,8 @@
|
||||
|
||||
# include "PScope.h"
|
||||
|
||||
PScope::PScope(perm_string n, PScope*parent)
|
||||
: name_(n), parent_(parent)
|
||||
{
|
||||
}
|
||||
|
||||
PScope::PScope(perm_string n)
|
||||
: name_(n), parent_(0)
|
||||
PScope::PScope(perm_string n, PScope*p)
|
||||
: name_(n), parent_(p)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -33,7 +28,7 @@ PScope::~PScope()
|
||||
{
|
||||
}
|
||||
|
||||
PWire* LexicalScope::wires_find(perm_string name)
|
||||
PWire* PScope::wires_find(perm_string name)
|
||||
{
|
||||
map<perm_string,PWire*>::const_iterator cur = wires.find(name);
|
||||
if (cur == wires.end())
|
||||
|
||||
@@ -19,15 +19,11 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "LineInfo.h"
|
||||
# include "StringHeap.h"
|
||||
# include "pform_types.h"
|
||||
# include "ivl_target.h"
|
||||
# include <map>
|
||||
|
||||
class PEvent;
|
||||
class PExpr;
|
||||
class AProcess;
|
||||
class PProcess;
|
||||
class PWire;
|
||||
|
||||
@@ -39,74 +35,10 @@ class NetScope;
|
||||
* represents lexical scope. For example, a module, a function/task, a
|
||||
* named block is derived from a PScope.
|
||||
*
|
||||
* NOTE: This is not the same concept as the "scope" of an elaborated
|
||||
* NOTE: This is note the same concept as the "scope" of an elaborated
|
||||
* hierarchy. That is represented by NetScope objects after elaboration.
|
||||
*/
|
||||
|
||||
class LexicalScope {
|
||||
|
||||
public:
|
||||
explicit LexicalScope() { }
|
||||
// A virtual destructor is so that dynamic_cast can work.
|
||||
virtual ~LexicalScope() { }
|
||||
|
||||
struct range_t {
|
||||
// True if this is an exclude
|
||||
bool exclude_flag;
|
||||
// lower bound
|
||||
// If low_open_flag is false and low_expr=0, then use -inf
|
||||
bool low_open_flag;
|
||||
PExpr*low_expr;
|
||||
// upper bound
|
||||
// If high_open_flag is false and high_expr=0, then use +inf
|
||||
bool high_open_flag;
|
||||
PExpr*high_expr;
|
||||
// Next range description in list
|
||||
struct range_t*next;
|
||||
};
|
||||
|
||||
/* The scope has parameters that are evaluated when the scope
|
||||
is elaborated. During parsing, I put the parameters into
|
||||
this map. */
|
||||
struct param_expr_t : public LineInfo {
|
||||
param_expr_t() : type(IVL_VT_NO_TYPE), msb(0), lsb(0), signed_flag(false), expr(0), range(0) { }
|
||||
// Type information
|
||||
ivl_variable_type_t type;
|
||||
PExpr*msb;
|
||||
PExpr*lsb;
|
||||
bool signed_flag;
|
||||
// Value expression
|
||||
PExpr*expr;
|
||||
// If there are range constraints, list them here
|
||||
range_t*range;
|
||||
};
|
||||
map<perm_string,param_expr_t>parameters;
|
||||
map<perm_string,param_expr_t>localparams;
|
||||
|
||||
// Named events in the scope.
|
||||
map<perm_string,PEvent*>events;
|
||||
|
||||
// Nets and variables (wires) in the scope
|
||||
map<perm_string,PWire*>wires;
|
||||
PWire* wires_find(perm_string name);
|
||||
|
||||
// Behaviors (processes) in this scope
|
||||
list<PProcess*> behaviors;
|
||||
list<AProcess*> analog_behaviors;
|
||||
|
||||
protected:
|
||||
void dump_parameters_(ostream&out, unsigned indent) const;
|
||||
|
||||
void dump_localparams_(ostream&out, unsigned indent) const;
|
||||
|
||||
void dump_events_(ostream&out, unsigned indent) const;
|
||||
|
||||
void dump_wires_(ostream&out, unsigned indent) const;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
class PScope : public LexicalScope {
|
||||
class PScope {
|
||||
|
||||
public:
|
||||
// When created, a scope has a name and a parent. The name is
|
||||
@@ -118,13 +50,24 @@ class PScope : public LexicalScope {
|
||||
// modules. Scopes for tasks and functions point to their
|
||||
// containing module.
|
||||
PScope(perm_string name, PScope*parent);
|
||||
PScope(perm_string name);
|
||||
virtual ~PScope();
|
||||
|
||||
perm_string pscope_name() const { return name_; }
|
||||
PScope* pscope_parent() { return parent_; }
|
||||
|
||||
// Nets an variables (wires) in the scope
|
||||
map<perm_string,PWire*>wires;
|
||||
PWire* wires_find(perm_string name);
|
||||
|
||||
// Named events in the scope.
|
||||
map<perm_string,PEvent*>events;
|
||||
|
||||
// Behaviors (processes) in this scope
|
||||
list<PProcess*> behaviors;
|
||||
|
||||
protected:
|
||||
void dump_wires_(ostream&out, unsigned indent) const;
|
||||
|
||||
bool elaborate_sig_wires_(Design*des, NetScope*scope) const;
|
||||
|
||||
bool elaborate_behaviors_(Design*des, NetScope*scope) const;
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PSpec.cc,v 1.2 2007/02/12 01:52:21 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PSpec.h"
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PSpec.h,v 1.3 2007/04/13 02:34:35 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "LineInfo.h"
|
||||
# include "StringHeap.h"
|
||||
|
||||
@@ -21,10 +21,9 @@
|
||||
|
||||
# include "PTask.h"
|
||||
|
||||
PTask::PTask(perm_string name, PScope*parent, bool is_auto__)
|
||||
PTask::PTask(perm_string name, PScope*parent)
|
||||
: PScope(name, parent), ports_(0), statement_(0)
|
||||
{
|
||||
is_auto_ = is_auto__;
|
||||
}
|
||||
|
||||
PTask::~PTask()
|
||||
@@ -42,3 +41,31 @@ void PTask::set_statement(Statement*s)
|
||||
assert(statement_ == 0);
|
||||
statement_ = s;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: PTask.cc,v $
|
||||
* Revision 1.7 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.6 2001/07/25 03:10:48 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.5 2001/04/19 03:04:47 steve
|
||||
* Spurious assert of empty statemnt.
|
||||
*
|
||||
* Revision 1.4 2001/01/13 22:20:08 steve
|
||||
* Parse parameters within nested scopes.
|
||||
*
|
||||
* Revision 1.3 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.2 1999/07/24 02:11:19 steve
|
||||
* Elaborate task input ports.
|
||||
*
|
||||
* Revision 1.1 1999/07/03 02:12:51 steve
|
||||
* Elaborate user defined tasks.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ struct PTaskFuncArg {
|
||||
class PTask : public PScope, public LineInfo {
|
||||
|
||||
public:
|
||||
explicit PTask(perm_string name, PScope*parent, bool is_auto);
|
||||
explicit PTask(perm_string name, PScope*parent);
|
||||
~PTask();
|
||||
|
||||
void set_ports(svector<PWire *>*p);
|
||||
@@ -69,14 +69,11 @@ class PTask : public PScope, public LineInfo {
|
||||
// Elaborate the statement to finish off the task definition.
|
||||
void elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
bool is_auto() const { return is_auto_; };
|
||||
|
||||
void dump(ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
svector<PWire*>*ports_;
|
||||
Statement*statement_;
|
||||
bool is_auto_;
|
||||
|
||||
private: // Not implemented
|
||||
PTask(const PTask&);
|
||||
@@ -93,7 +90,7 @@ class PTask : public PScope, public LineInfo {
|
||||
class PFunction : public PScope, public LineInfo {
|
||||
|
||||
public:
|
||||
explicit PFunction(perm_string name, PScope*parent, bool is_auto);
|
||||
explicit PFunction(perm_string name, PScope*parent);
|
||||
~PFunction();
|
||||
|
||||
void set_ports(svector<PWire *>*p);
|
||||
@@ -108,15 +105,12 @@ class PFunction : public PScope, public LineInfo {
|
||||
/* Elaborate the behavioral statement. */
|
||||
void elaborate(Design *des, NetScope*) const;
|
||||
|
||||
bool is_auto() const { return is_auto_; };
|
||||
|
||||
void dump(ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
PTaskFuncArg return_type_;
|
||||
svector<PWire *> *ports_;
|
||||
Statement *statement_;
|
||||
bool is_auto_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PUdp.cc,v 1.3 2004/03/08 00:47:44 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PUdp.h"
|
||||
|
||||
@@ -35,3 +38,16 @@ unsigned PUdp::find_port(const char*name)
|
||||
return ports.count();
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: PUdp.cc,v $
|
||||
* Revision 1.3 2004/03/08 00:47:44 steve
|
||||
* primitive ports can bind bi name.
|
||||
*
|
||||
* Revision 1.2 2004/02/18 17:11:54 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
* Revision 1.1 2003/07/15 05:07:13 steve
|
||||
* Move PUdp constructor into compiled file.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PUdp.h,v 1.12 2004/03/08 00:47:44 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <map>
|
||||
# include "StringHeap.h"
|
||||
@@ -75,4 +78,53 @@ class PUdp {
|
||||
PUdp& operator= (const PUdp&);
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: PUdp.h,v $
|
||||
* Revision 1.12 2004/03/08 00:47:44 steve
|
||||
* primitive ports can bind bi name.
|
||||
*
|
||||
* Revision 1.11 2004/02/18 17:11:54 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
* Revision 1.10 2003/07/15 05:07:13 steve
|
||||
* Move PUdp constructor into compiled file.
|
||||
*
|
||||
* Revision 1.9 2003/07/15 03:49:22 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.8 2003/01/30 16:23:07 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.7 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.6 2002/05/23 03:08:51 steve
|
||||
* Add language support for Verilog-2001 attribute
|
||||
* syntax. Hook this support into existing $attribute
|
||||
* handling, and add number and void value types.
|
||||
*
|
||||
* Add to the ivl_target API new functions for access
|
||||
* of complex attributes attached to gates.
|
||||
*
|
||||
* Revision 1.5 2001/04/22 23:09:45 steve
|
||||
* More UDP consolidation from Stephan Boettcher.
|
||||
*
|
||||
* Revision 1.4 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.3 1999/06/15 03:44:53 steve
|
||||
* Get rid of the STL vector template.
|
||||
*
|
||||
* Revision 1.2 1998/12/01 00:42:13 steve
|
||||
* Elaborate UDP devices,
|
||||
* Support UDP type attributes, and
|
||||
* pass those attributes to nodes that
|
||||
* are instantiated by elaboration,
|
||||
* Put modules into a map instead of
|
||||
* a simple list.
|
||||
*
|
||||
* Revision 1.1 1998/11/25 02:35:53 steve
|
||||
* Parse UDP primitives all the way to pform.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
||||
@@ -198,13 +198,13 @@ void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
|
||||
}
|
||||
}
|
||||
|
||||
void PWire::set_discipline(ivl_discipline_t d)
|
||||
void PWire::set_discipline(discipline_t*d)
|
||||
{
|
||||
assert(discipline_ == 0);
|
||||
discipline_ = d;
|
||||
}
|
||||
|
||||
ivl_discipline_t PWire::get_discipline(void) const
|
||||
discipline_t* PWire::get_discipline(void) const
|
||||
{
|
||||
return discipline_;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PWire.h,v 1.21 2007/05/24 04:07:11 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
# include "LineInfo.h"
|
||||
@@ -33,6 +36,7 @@ class ostream;
|
||||
|
||||
class PExpr;
|
||||
class Design;
|
||||
class discipline_t;
|
||||
|
||||
/*
|
||||
* The different type of PWire::set_range() calls.
|
||||
@@ -78,8 +82,8 @@ class PWire : public LineInfo {
|
||||
|
||||
void set_memory_idx(PExpr*ldx, PExpr*rdx);
|
||||
|
||||
void set_discipline(ivl_discipline_t);
|
||||
ivl_discipline_t get_discipline(void) const;
|
||||
void set_discipline(discipline_t*);
|
||||
discipline_t* get_discipline(void) const;
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
|
||||
@@ -111,7 +115,7 @@ class PWire : public LineInfo {
|
||||
PExpr*lidx_;
|
||||
PExpr*ridx_;
|
||||
|
||||
ivl_discipline_t discipline_;
|
||||
discipline_t*discipline_;
|
||||
|
||||
private: // not implemented
|
||||
PWire(const PWire&);
|
||||
|
||||
+29
-11
@@ -12,7 +12,10 @@ home page at <http://www.icarus.com/eda/verilog>.
|
||||
|
||||
Icarus Verilog is not aimed at being a simulator in the traditional
|
||||
sense, but a compiler that generates code employed by back-end
|
||||
tools.
|
||||
tools. These back-end tools currently include a simulator engine
|
||||
called VVP, an XNF (Xilinx Netlist Format) generator and an EDIF FPGA
|
||||
netlist generator. In the future, backends are expected for EDIF/LPM,
|
||||
structural Verilog, VHDL, etc.
|
||||
|
||||
For instructions on how to run Icarus Verilog,
|
||||
see the ``iverilog'' man page.
|
||||
@@ -85,6 +88,10 @@ Normally, this command automatically figures out everything it needs
|
||||
to know. It generally works pretty well. There are a few flags to the
|
||||
configure script that modify its behavior:
|
||||
|
||||
--without-ipal
|
||||
This turns off support for Icarus PAL, whether ipal
|
||||
libraries are installed or not.
|
||||
|
||||
--prefix=<root>
|
||||
The default is /usr/local, which causes the tool suite to
|
||||
be compiled for install in /usr/local/bin,
|
||||
@@ -95,16 +102,27 @@ configure script that modify its behavior:
|
||||
common to use --prefix=/opt. You can configure for a non-root
|
||||
install with --prefix=$HOME.
|
||||
|
||||
--enable-suffix
|
||||
--enable-suffix=<your-suffix>
|
||||
--disable-suffix
|
||||
Enable/disable changing the names of install files to use
|
||||
a suffix string so that this version or install can co-
|
||||
exist with other versions. This renames the installed
|
||||
commands (iverilog, iverilog-vpi, vvp) and the installed
|
||||
library files and include directory so that installations
|
||||
with the same prefix but different suffix are guaranteed
|
||||
to not interfere with each other.
|
||||
--enable-vvp32 (experimental)
|
||||
If compiling on AMD64 systems, this enables the
|
||||
compilation of 32bit compatible vvp (vvp32) and the vpi
|
||||
modules that match.
|
||||
|
||||
2.2.1 Special AMD64 Instructions
|
||||
|
||||
(The Icarus Verilog RPM for x86_64 is build using these instructions.)
|
||||
|
||||
If you are building for Linux/AMD64 (a.k.a x86_64) then to get the
|
||||
most out of your install, first make sure you have both 64bit and
|
||||
32bit development libraries installed. Then configure with this
|
||||
somewhat more complicated command:
|
||||
|
||||
./configure libdir64='$(prefix)/lib64' vpidir1=vpi64 vpidir2=. --enable-vvp32
|
||||
|
||||
This reflects the convention on AMD64 systems that 64bit libraries go
|
||||
into lib64 directories. The "--enable-vvp32" also turns on 32bit
|
||||
compatibility files. A 32bit version of vvp (vvp32) will be created,
|
||||
as well as 32bit versions of the development libraries and bundled VPI
|
||||
libraries.
|
||||
|
||||
2.3 (Optional) Testing
|
||||
|
||||
|
||||
+56
-37
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2008 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-1999 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,6 +16,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: Statement.cc,v 1.30 2007/05/24 04:07:11 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
@@ -26,20 +29,20 @@ Statement::~Statement()
|
||||
{
|
||||
}
|
||||
|
||||
PAssign_::PAssign_(PExpr*lval__, PExpr*ex, bool is_constant)
|
||||
: event_(0), count_(0), lval_(lval__), rval_(ex), is_constant_(is_constant)
|
||||
PAssign_::PAssign_(PExpr*lval, PExpr*ex)
|
||||
: event_(0), lval_(lval), rval_(ex)
|
||||
{
|
||||
delay_ = 0;
|
||||
}
|
||||
|
||||
PAssign_::PAssign_(PExpr*lval__, PExpr*de, PExpr*ex)
|
||||
: event_(0), count_(0), lval_(lval__), rval_(ex), is_constant_(false)
|
||||
PAssign_::PAssign_(PExpr*lval, PExpr*de, PExpr*ex)
|
||||
: event_(0), lval_(lval), rval_(ex)
|
||||
{
|
||||
delay_ = de;
|
||||
}
|
||||
|
||||
PAssign_::PAssign_(PExpr*lval__, PExpr*cnt, PEventStatement*ev, PExpr*ex)
|
||||
: event_(ev), count_(cnt), lval_(lval__), rval_(ex), is_constant_(false)
|
||||
PAssign_::PAssign_(PExpr*lval, PEventStatement*ev, PExpr*ex)
|
||||
: event_(ev), lval_(lval), rval_(ex)
|
||||
{
|
||||
delay_ = 0;
|
||||
}
|
||||
@@ -50,23 +53,18 @@ PAssign_::~PAssign_()
|
||||
delete rval_;
|
||||
}
|
||||
|
||||
PAssign::PAssign(PExpr*lval__, PExpr*ex)
|
||||
: PAssign_(lval__, ex, false)
|
||||
PAssign::PAssign(PExpr*lval, PExpr*ex)
|
||||
: PAssign_(lval, ex)
|
||||
{
|
||||
}
|
||||
|
||||
PAssign::PAssign(PExpr*lval__, PExpr*d, PExpr*ex)
|
||||
: PAssign_(lval__, d, ex)
|
||||
PAssign::PAssign(PExpr*lval, PExpr*d, PExpr*ex)
|
||||
: PAssign_(lval, d, ex)
|
||||
{
|
||||
}
|
||||
|
||||
PAssign::PAssign(PExpr*lval__, PExpr*cnt, PEventStatement*d, PExpr*ex)
|
||||
: PAssign_(lval__, cnt, d, ex)
|
||||
{
|
||||
}
|
||||
|
||||
PAssign::PAssign(PExpr*lval__, PExpr*ex, bool is_constant)
|
||||
: PAssign_(lval__, ex, is_constant)
|
||||
PAssign::PAssign(PExpr*lval, PEventStatement*d, PExpr*ex)
|
||||
: PAssign_(lval, d, ex)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -74,18 +72,13 @@ PAssign::~PAssign()
|
||||
{
|
||||
}
|
||||
|
||||
PAssignNB::PAssignNB(PExpr*lval__, PExpr*ex)
|
||||
: PAssign_(lval__, ex, false)
|
||||
PAssignNB::PAssignNB(PExpr*lval, PExpr*ex)
|
||||
: PAssign_(lval, ex)
|
||||
{
|
||||
}
|
||||
|
||||
PAssignNB::PAssignNB(PExpr*lval__, PExpr*d, PExpr*ex)
|
||||
: PAssign_(lval__, d, ex)
|
||||
{
|
||||
}
|
||||
|
||||
PAssignNB::PAssignNB(PExpr*lval__, PExpr*cnt, PEventStatement*d, PExpr*ex)
|
||||
: PAssign_(lval__, cnt, d, ex)
|
||||
PAssignNB::PAssignNB(PExpr*lval, PExpr*d, PExpr*ex)
|
||||
: PAssign_(lval, d, ex)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -99,7 +92,7 @@ PBlock::PBlock(perm_string n, PScope*parent, BL_TYPE t)
|
||||
}
|
||||
|
||||
PBlock::PBlock(BL_TYPE t)
|
||||
: PScope(perm_string()), bl_type_(t)
|
||||
: PScope(perm_string(),0), bl_type_(t)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -228,15 +221,6 @@ void PEventStatement::set_statement(Statement*st)
|
||||
statement_ = st;
|
||||
}
|
||||
|
||||
bool PEventStatement::has_aa_term(Design*des, NetScope*scope)
|
||||
{
|
||||
bool flag = false;
|
||||
for (unsigned idx = 0 ; idx < expr_.count() ; idx += 1) {
|
||||
flag = expr_[idx]->has_aa_term(des, scope) || flag;
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
PForce::PForce(PExpr*l, PExpr*r)
|
||||
: lval_(l), expr_(r)
|
||||
{
|
||||
@@ -314,3 +298,38 @@ PWhile::~PWhile()
|
||||
delete cond_;
|
||||
delete statement_;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: Statement.cc,v $
|
||||
* Revision 1.30 2007/05/24 04:07:11 steve
|
||||
* Rework the heirarchical identifier parse syntax and pform
|
||||
* to handle more general combinations of heirarch and bit selects.
|
||||
*
|
||||
* Revision 1.29 2004/02/18 17:11:54 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
* Revision 1.28 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.27 2002/04/21 22:31:02 steve
|
||||
* Redo handling of assignment internal delays.
|
||||
* Leave it possible for them to be calculated
|
||||
* at run time.
|
||||
*
|
||||
* Revision 1.26 2002/04/21 04:59:07 steve
|
||||
* Add support for conbinational events by finding
|
||||
* the inputs to expressions and some statements.
|
||||
* Get case and assignment statements working.
|
||||
*
|
||||
* Revision 1.25 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
*
|
||||
* Revision 1.24 2001/11/22 06:20:59 steve
|
||||
* Use NetScope instead of string for scope path.
|
||||
*
|
||||
* Revision 1.23 2001/07/25 03:10:48 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*/
|
||||
|
||||
|
||||
+9
-23
@@ -20,7 +20,6 @@
|
||||
*/
|
||||
|
||||
# include <string>
|
||||
# include "ivl_target.h"
|
||||
# include "svector.h"
|
||||
# include "StringHeap.h"
|
||||
# include "PDelays.h"
|
||||
@@ -47,14 +46,16 @@ class NetScope;
|
||||
class PProcess : public LineInfo {
|
||||
|
||||
public:
|
||||
PProcess(ivl_process_type_t t, Statement*st)
|
||||
enum Type { PR_INITIAL, PR_ALWAYS };
|
||||
|
||||
PProcess(Type t, Statement*st)
|
||||
: type_(t), statement_(st) { }
|
||||
|
||||
virtual ~PProcess();
|
||||
|
||||
bool elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
ivl_process_type_t type() const { return type_; }
|
||||
Type type() const { return type_; }
|
||||
Statement*statement() { return statement_; }
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
@@ -62,7 +63,7 @@ class PProcess : public LineInfo {
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
ivl_process_type_t type_;
|
||||
Type type_;
|
||||
Statement*statement_;
|
||||
};
|
||||
|
||||
@@ -81,8 +82,6 @@ class Statement : public LineInfo {
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -92,27 +91,23 @@ class Statement : public LineInfo {
|
||||
*/
|
||||
class PAssign_ : public Statement {
|
||||
public:
|
||||
explicit PAssign_(PExpr*lval, PExpr*ex, bool is_constant);
|
||||
explicit PAssign_(PExpr*lval, PExpr*ex);
|
||||
explicit PAssign_(PExpr*lval, PExpr*de, PExpr*ex);
|
||||
explicit PAssign_(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
|
||||
explicit PAssign_(PExpr*lval, PEventStatement*de, PExpr*ex);
|
||||
virtual ~PAssign_() =0;
|
||||
|
||||
const PExpr* lval() const { return lval_; }
|
||||
PExpr* rval() const { return rval_; }
|
||||
const PExpr* rval() const { return rval_; }
|
||||
|
||||
protected:
|
||||
NetAssign_* elaborate_lval(Design*, NetScope*scope) const;
|
||||
NetExpr* elaborate_rval_(Design*, NetScope*, unsigned lv_width,
|
||||
ivl_variable_type_t type) const;
|
||||
|
||||
PExpr* delay_;
|
||||
PEventStatement*event_;
|
||||
PExpr* count_;
|
||||
|
||||
private:
|
||||
PExpr* lval_;
|
||||
PExpr* rval_;
|
||||
bool is_constant_;
|
||||
};
|
||||
|
||||
class PAssign : public PAssign_ {
|
||||
@@ -120,8 +115,7 @@ class PAssign : public PAssign_ {
|
||||
public:
|
||||
explicit PAssign(PExpr*lval, PExpr*ex);
|
||||
explicit PAssign(PExpr*lval, PExpr*de, PExpr*ex);
|
||||
explicit PAssign(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
|
||||
explicit PAssign(PExpr*lval, PExpr*ex, bool is_constant);
|
||||
explicit PAssign(PExpr*lval, PEventStatement*de, PExpr*ex);
|
||||
~PAssign();
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
@@ -135,7 +129,6 @@ class PAssignNB : public PAssign_ {
|
||||
public:
|
||||
explicit PAssignNB(PExpr*lval, PExpr*ex);
|
||||
explicit PAssignNB(PExpr*lval, PExpr*de, PExpr*ex);
|
||||
explicit PAssignNB(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
|
||||
~PAssignNB();
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
@@ -340,15 +333,10 @@ class PEventStatement : public Statement {
|
||||
void set_statement(Statement*st);
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
// Call this with a NULL statement only. It is used to print
|
||||
// the event expression for inter-assignment event controls.
|
||||
virtual void dump_inline(ostream&out) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
bool has_aa_term(Design*des, NetScope*scope);
|
||||
|
||||
// This method is used to elaborate, but attach a previously
|
||||
// elaborated statement to the event.
|
||||
NetProc* elaborate_st(Design*des, NetScope*scope, NetProc*st) const;
|
||||
@@ -360,8 +348,6 @@ class PEventStatement : public Statement {
|
||||
Statement*statement_;
|
||||
};
|
||||
|
||||
ostream& operator << (ostream&o, const PEventStatement&obj);
|
||||
|
||||
class PForce : public Statement {
|
||||
|
||||
public:
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: StringHeap.cc,v 1.6 2004/02/18 17:11:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "StringHeap.h"
|
||||
#ifdef HAVE_MALLOC_H
|
||||
@@ -176,3 +179,28 @@ bool operator < (perm_string a, perm_string b)
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: StringHeap.cc,v $
|
||||
* Revision 1.6 2004/02/18 17:11:54 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
* Revision 1.5 2003/03/01 06:25:30 steve
|
||||
* Add the lex_strings string handler, and put
|
||||
* scope names and system task/function names
|
||||
* into this table. Also, permallocate event
|
||||
* names from the beginning.
|
||||
*
|
||||
* Revision 1.4 2003/01/27 05:09:17 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.3 2003/01/16 21:44:46 steve
|
||||
* Keep some debugging status.
|
||||
*
|
||||
* Revision 1.2 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.1 2002/08/04 19:13:16 steve
|
||||
* dll uses StringHeap for named items.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: StringHeap.h,v 1.6 2005/06/14 19:13:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include <string>
|
||||
@@ -117,4 +120,28 @@ class StringHeapLex : private StringHeap {
|
||||
StringHeapLex& operator= (const StringHeapLex&);
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: StringHeap.h,v $
|
||||
* Revision 1.6 2005/06/14 19:13:43 steve
|
||||
* gcc3/4 compile errors.
|
||||
*
|
||||
* Revision 1.5 2004/02/18 17:11:54 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
* Revision 1.4 2003/03/01 06:25:30 steve
|
||||
* Add the lex_strings string handler, and put
|
||||
* scope names and system task/function names
|
||||
* into this table. Also, permallocate event
|
||||
* names from the beginning.
|
||||
*
|
||||
* Revision 1.3 2003/01/16 21:44:46 steve
|
||||
* Keep some debugging status.
|
||||
*
|
||||
* Revision 1.2 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.1 2002/08/04 19:13:16 steve
|
||||
* dll uses StringHeap for named items.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: _pli_types.h.in,v 1.8 2007/06/05 21:32:30 steve Exp $"
|
||||
#endif
|
||||
|
||||
# undef HAVE_INTTYPES_H
|
||||
|
||||
@@ -85,4 +88,42 @@ typedef char PLI_BYTE8;
|
||||
typedef unsigned char PLI_UBYTE8;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $Log: _pli_types.h.in,v $
|
||||
* Revision 1.8 2007/06/05 21:32:30 steve
|
||||
* More standard PLI_BYTE8.
|
||||
*
|
||||
* Revision 1.7 2003/11/12 02:38:44 steve
|
||||
* Clean up manual definitions of PLI_UINT64_FMT.
|
||||
*
|
||||
* Revision 1.6 2003/11/08 20:06:21 steve
|
||||
* Spelling fixes in comments.
|
||||
*
|
||||
* Revision 1.5 2003/10/29 03:28:27 steve
|
||||
* Add the PLU_UINT64_FMT string for formatting output.
|
||||
*
|
||||
* Revision 1.4 2003/10/29 03:23:12 steve
|
||||
* Portably handle time format of VCD prints.
|
||||
*
|
||||
* Revision 1.3 2003/10/02 21:30:06 steve
|
||||
* Use configured TIME_FMT in vcd dump printf.
|
||||
*
|
||||
* Revision 1.2 2003/10/02 19:33:44 steve
|
||||
* Put libraries in libdir64.
|
||||
*
|
||||
* Revision 1.1 2003/09/30 01:33:13 steve
|
||||
* Add PLI_UINT64 to _pli_types.h.
|
||||
*
|
||||
* Revision 1.2 2003/05/26 04:39:16 steve
|
||||
* Typo type name.
|
||||
*
|
||||
* Revision 1.1 2003/02/17 06:39:47 steve
|
||||
* Add at least minimal implementations for several
|
||||
* acc_ functions. Add support for standard ACC
|
||||
* string handling.
|
||||
*
|
||||
* Add the _pli_types.h header file to carry the
|
||||
* IEEE1364-2001 standard PLI type declarations.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
||||
+81
@@ -18,6 +18,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: acc_user.h,v 1.20 2003/12/17 15:45:07 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This header file contains the definitions and declarations needed
|
||||
@@ -270,4 +273,82 @@ extern char* acc_version(void);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
/*
|
||||
* $Log: acc_user.h,v $
|
||||
* Revision 1.20 2003/12/17 15:45:07 steve
|
||||
* Add acc_set_scope function.
|
||||
*
|
||||
* Revision 1.19 2003/10/10 02:57:45 steve
|
||||
* Some PLI1 stubs.
|
||||
*
|
||||
* Revision 1.18 2003/06/13 19:23:41 steve
|
||||
* Add a bunch more PLI1 routines.
|
||||
*
|
||||
* Revision 1.17 2003/06/04 01:56:20 steve
|
||||
* 1) Adds configure logic to clean up compiler warnings
|
||||
* 2) adds acc_compare_handle, acc_fetch_range, acc_next_scope and
|
||||
* tf_isetrealdelay, acc_handle_scope
|
||||
* 3) makes acc_next reentrant
|
||||
* 4) adds basic vpiWire type support
|
||||
* 5) fills in some acc_object_of_type() and acc_fetch_{full}type()
|
||||
* 6) add vpiLeftRange/RigthRange to signals
|
||||
*
|
||||
* Revision 1.16 2003/05/30 04:18:31 steve
|
||||
* Add acc_next function.
|
||||
*
|
||||
* Revision 1.15 2003/05/29 02:35:41 steve
|
||||
* acc_fetch_type supports module.
|
||||
*
|
||||
* Revision 1.14 2003/05/29 02:21:45 steve
|
||||
* Implement acc_fetch_defname and its infrastructure in vvp.
|
||||
*
|
||||
* Revision 1.13 2003/05/24 03:02:04 steve
|
||||
* Add implementation of acc_handle_by_name.
|
||||
*
|
||||
* Revision 1.12 2003/05/18 00:16:35 steve
|
||||
* Add PLI_TRACE tracing of PLI1 modules.
|
||||
*
|
||||
* Add tf_isetdelay and friends, and add
|
||||
* callback return values for acc_vcl support.
|
||||
*
|
||||
* Revision 1.11 2003/04/24 18:57:05 steve
|
||||
* Add acc_fetch_fulltype function.
|
||||
*
|
||||
* Revision 1.10 2003/04/20 02:48:39 steve
|
||||
* Support value change callbacks.
|
||||
*
|
||||
* Revision 1.9 2003/04/12 18:57:13 steve
|
||||
* More acc_ function stubs.
|
||||
*
|
||||
* Revision 1.8 2003/03/13 04:35:09 steve
|
||||
* Add a bunch of new acc_ and tf_ functions.
|
||||
*
|
||||
* Revision 1.7 2003/02/17 06:39:47 steve
|
||||
* Add at least minimal implementations for several
|
||||
* acc_ functions. Add support for standard ACC
|
||||
* string handling.
|
||||
*
|
||||
* Add the _pli_types.h header file to carry the
|
||||
* IEEE1364-2001 standard PLI type declarations.
|
||||
*
|
||||
* Revision 1.6 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.5 2002/06/11 15:19:12 steve
|
||||
* Add acc_fetch_argc/argv/version (mruff)
|
||||
*
|
||||
* Revision 1.4 2002/06/07 02:58:58 steve
|
||||
* Add a bunch of acc/tf functions. (mruff)
|
||||
*
|
||||
* Revision 1.3 2002/06/02 19:03:29 steve
|
||||
* Add acc_handle_tfarg and acc_next_topmode
|
||||
*
|
||||
* Revision 1.2 2002/05/30 02:06:05 steve
|
||||
* Implement acc_product_version.
|
||||
*
|
||||
* Revision 1.1 2002/05/23 03:46:42 steve
|
||||
* Add the acc_user.h header file.
|
||||
*
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
Vendored
+25
-17
@@ -1,21 +1,29 @@
|
||||
|
||||
# AX_ENABLE_SUFFIX
|
||||
# ----------------
|
||||
# Create the configure option --enable-suffix[=suffix] to generate suffix
|
||||
# strings for the installed commands. This allows for shared installs of
|
||||
# different builds. Remember to change the default suffix string to some
|
||||
# value appropriate for the current version.
|
||||
AC_DEFUN([AX_ENABLE_SUFFIX],
|
||||
[AC_ARG_ENABLE([suffix],[Set the installation command suffix],[true],[enable_suffix=no])
|
||||
if test X$enable_suffix = Xyes; then
|
||||
install_suffix='-0.9'
|
||||
elif test X$enable_suffix = Xno; then
|
||||
install_suffix=''
|
||||
else
|
||||
install_suffix="$enable_suffix"
|
||||
# AX_CPP_IDENT
|
||||
# ------------
|
||||
# Check if the C compiler supports #ident
|
||||
# Define and substitute ident_support if so.
|
||||
#
|
||||
# It would be simpler and more consistent with the rest of the autoconf
|
||||
# structure to AC_DEFINE(HAVE_CPP_IDENT) instead of
|
||||
# ident_support='-DHAVE_CVS_IDENT=1' and AC_SUBST(ident_support), but that
|
||||
# change would require all C files in the icarus top level directory to
|
||||
# put #include <config.h> before the #ifdef HAVE_CVS_IDENT (and change
|
||||
# HAVE_CVS_IDENT to HAVE_CPP_IDENT). That would also remove all special
|
||||
# ident_support handling from the Makefile. Manyana.
|
||||
#
|
||||
AC_DEFUN([AX_CPP_IDENT],
|
||||
[AC_CACHE_CHECK([for ident support in C compiler], ax_cv_cpp_ident,
|
||||
[AC_TRY_COMPILE([
|
||||
#ident "$Id: aclocal.m4,v 1.7 2007/05/16 23:59:12 steve Exp $"
|
||||
],[while (0) {}],
|
||||
[AS_VAR_SET(ax_cv_cpp_ident, yes)],
|
||||
[AS_VAR_SET(ax_cv_cpp_ident, no)])])
|
||||
if test $ax_cv_cpp_ident = yes; then
|
||||
ident_support='-DHAVE_CVS_IDENT=1'
|
||||
fi
|
||||
AC_SUBST(install_suffix)
|
||||
])# AX_ENABLE_SUFFIX
|
||||
AC_SUBST(ident_support)
|
||||
])# AC_CPP_IDENT
|
||||
|
||||
|
||||
# _AX_C_UNDERSCORES_MATCH_IFELSE(PATTERN, ACTION-IF-MATCH, ACTION-IF-NOMATCH)
|
||||
# ------------------------------
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2008 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2002 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,6 +16,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: async.cc,v 1.7 2004/01/18 23:26:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
@@ -84,8 +87,34 @@ bool NetProc::is_asynchronous()
|
||||
|
||||
bool NetProcTop::is_asynchronous()
|
||||
{
|
||||
if (type_ == IVL_PR_INITIAL)
|
||||
if (type_ == NetProcTop::KINITIAL)
|
||||
return false;
|
||||
|
||||
return statement_->is_asynchronous();
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: async.cc,v $
|
||||
* Revision 1.7 2004/01/18 23:26:54 steve
|
||||
* The is_combinational function really need not recurse.
|
||||
*
|
||||
* Revision 1.6 2003/12/20 00:33:39 steve
|
||||
* More thorough check that NetEvWait is asynchronous.
|
||||
*
|
||||
* Revision 1.5 2003/09/04 20:28:05 steve
|
||||
* Support time0 resolution of combinational threads.
|
||||
*
|
||||
* Revision 1.4 2002/08/18 22:07:16 steve
|
||||
* Detect temporaries in sequential block synthesis.
|
||||
*
|
||||
* Revision 1.3 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.2 2002/07/04 00:24:16 steve
|
||||
* initial statements are not asynchronous.
|
||||
*
|
||||
* Revision 1.1 2002/06/30 02:21:31 steve
|
||||
* Add structure for asynchronous logic synthesis.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
echo "Autoconf in root..."
|
||||
autoconf -f
|
||||
|
||||
for dir in vpi vvp tgt-vvp tgt-fpga tgt-stub tgt-vhdl libveriuser cadpli
|
||||
for dir in vpip vpi vvp tgt-vvp tgt-fpga tgt-stub libveriuser cadpli
|
||||
do
|
||||
echo "Autoconf in $dir..."
|
||||
( cd ./$dir ; autoconf -f --include=.. )
|
||||
|
||||
+5
-7
@@ -20,8 +20,6 @@ SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.9.devel
|
||||
|
||||
suffix = @install_suffix@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
@@ -32,14 +30,14 @@ bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
includedir = $(prefix)/include
|
||||
|
||||
vpidir = @libdir@/ivl$(suffix)
|
||||
vpidir = @libdir@/ivl
|
||||
|
||||
CC = @CC@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
CPPFLAGS = -I$(srcdir) -I$(srcdir)/.. -I.. @CPPFLAGS@ @DEFS@ @PICFLAG@
|
||||
CPPFLAGS = @ident_support@ -I$(srcdir) -I$(srcdir)/.. -I.. @CPPFLAGS@ @DEFS@ @PICFLAG@
|
||||
CFLAGS = -Wall @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
@@ -78,13 +76,13 @@ distclean: clean
|
||||
install: all installdirs $(vpidir)/cadpli.vpl $(INSTALL32)
|
||||
|
||||
$(vpidir)/cadpli.vpl: ./cadpli.vpl
|
||||
$(INSTALL_PROGRAM) ./cadpli.vpl $(DESTDIR)$(vpidir)/cadpli.vpl
|
||||
$(INSTALL_PROGRAM) ./cadpli.vpl $(vpidir)/cadpli.vpl
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs $(DESTDIR)$(vpidir)
|
||||
$(srcdir)/../mkinstalldirs $(vpidir)
|
||||
|
||||
uninstall: $(UNINSTALL32)
|
||||
rm -f $(DESTDIR)$(vpidir)/cadpli.vpl
|
||||
rm -f $(vpidir)/cadpli.vpl
|
||||
|
||||
uninstall32:
|
||||
|
||||
|
||||
+2
-2
@@ -10,8 +10,6 @@ AC_SUBST(EXEEXT)
|
||||
# Combined check for Microsoft-related bogosities; sets WIN32 if found
|
||||
AX_WIN32
|
||||
|
||||
AX_ENABLE_SUFFIX
|
||||
|
||||
AC_PROG_INSTALL
|
||||
|
||||
AC_CHECK_HEADERS(malloc.h)
|
||||
@@ -58,4 +56,6 @@ AX_C_UNDERSCORES_TRAILING
|
||||
## end of test for underscores
|
||||
#######################
|
||||
|
||||
AX_CPP_IDENT
|
||||
|
||||
AC_OUTPUT(Makefile)
|
||||
|
||||
+30
-11
@@ -18,6 +18,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: ivl_dlfcn.h,v 1.3 2004/10/04 01:10:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
# include <windows.h>
|
||||
@@ -32,16 +35,16 @@ typedef shl_t ivl_dll_t;
|
||||
#endif
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
static __inline__ ivl_dll_t ivl_dlopen(const char *name)
|
||||
static inline ivl_dll_t ivl_dlopen(const char *name)
|
||||
{ return (void *)LoadLibrary(name); }
|
||||
|
||||
static __inline__ void *ivl_dlsym(ivl_dll_t dll, const char *nm)
|
||||
static inline void *ivl_dlsym(ivl_dll_t dll, const char *nm)
|
||||
{ return (void *)GetProcAddress((HINSTANCE)dll,nm);}
|
||||
|
||||
static __inline__ void ivl_dlclose(ivl_dll_t dll)
|
||||
static inline void ivl_dlclose(ivl_dll_t dll)
|
||||
{ (void)FreeLibrary((HINSTANCE)dll);}
|
||||
|
||||
static __inline__ const char *dlerror(void)
|
||||
static inline const char *dlerror(void)
|
||||
{
|
||||
static char msg[256];
|
||||
unsigned long err = GetLastError();
|
||||
@@ -58,10 +61,10 @@ static __inline__ const char *dlerror(void)
|
||||
}
|
||||
|
||||
#elif defined(HAVE_DLFCN_H)
|
||||
static __inline__ ivl_dll_t ivl_dlopen(const char*name)
|
||||
static inline ivl_dll_t ivl_dlopen(const char*name)
|
||||
{ return dlopen(name,RTLD_LAZY); }
|
||||
|
||||
static __inline__ void* ivl_dlsym(ivl_dll_t dll, const char*nm)
|
||||
static inline void* ivl_dlsym(ivl_dll_t dll, const char*nm)
|
||||
{
|
||||
void*sym = dlsym(dll, nm);
|
||||
/* Not found? try without the leading _ */
|
||||
@@ -70,25 +73,41 @@ static __inline__ void* ivl_dlsym(ivl_dll_t dll, const char*nm)
|
||||
return sym;
|
||||
}
|
||||
|
||||
static __inline__ void ivl_dlclose(ivl_dll_t dll)
|
||||
static inline void ivl_dlclose(ivl_dll_t dll)
|
||||
{ dlclose(dll); }
|
||||
|
||||
#elif defined(HAVE_DL_H)
|
||||
static __inline__ ivl_dll_t ivl_dlopen(const char*name)
|
||||
static inline ivl_dll_t ivl_dlopen(const char*name)
|
||||
{ return shl_load(name, BIND_IMMEDIATE, 0); }
|
||||
|
||||
static __inline__ void* ivl_dlsym(ivl_dll_t dll, const char*nm)
|
||||
static inline void* ivl_dlsym(ivl_dll_t dll, const char*nm)
|
||||
{
|
||||
void*sym;
|
||||
int rc = shl_findsym(&dll, nm, TYPE_PROCEDURE, &sym);
|
||||
return (rc == 0) ? sym : 0;
|
||||
}
|
||||
|
||||
static __inline__ void ivl_dlclose(ivl_dll_t dll)
|
||||
static inline void ivl_dlclose(ivl_dll_t dll)
|
||||
{ shl_unload(dll); }
|
||||
|
||||
static __inline__ const char*dlerror(void)
|
||||
static inline const char*dlerror(void)
|
||||
{ return strerror( errno ); }
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $Log: ivl_dlfcn.h,v $
|
||||
* Revision 1.3 2004/10/04 01:10:56 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
* Revision 1.2 2003/12/12 05:43:08 steve
|
||||
* Some systems dlsym requires leading _ or not on whim.
|
||||
*
|
||||
* Revision 1.1 2003/02/17 00:01:25 steve
|
||||
* Use a variant of ivl_dlfcn to do dynamic loading
|
||||
* from within the cadpli module.
|
||||
*
|
||||
* Change the +cadpli flag to -cadpli, to keep the
|
||||
* plusargs namespace clear.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
||||
@@ -87,7 +87,6 @@ extern bool debug_eval_tree;
|
||||
extern bool debug_elaborate;
|
||||
extern bool debug_synth2;
|
||||
extern bool debug_optimizer;
|
||||
extern bool debug_automatic;
|
||||
|
||||
/* Path to a directory useful for finding subcomponents. */
|
||||
extern const char*basedir;
|
||||
|
||||
+44
-1
@@ -18,6 +18,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: config.h.in,v 1.12 2007/02/02 04:33:00 steve Exp $"
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
# if !defined(__GNUC__)
|
||||
@@ -50,4 +53,44 @@
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#endif /* __config_H */
|
||||
/*
|
||||
* $Log: config.h.in,v $
|
||||
* Revision 1.12 2007/02/02 04:33:00 steve
|
||||
* Use inttypes.h instead of stdint.h for portability.
|
||||
*
|
||||
* Revision 1.11 2004/10/04 01:10:52 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
* Revision 1.10 2003/08/26 16:26:01 steve
|
||||
* ifdef idents correctly.
|
||||
*
|
||||
* Revision 1.9 2003/07/03 16:29:55 steve
|
||||
* spemm WORDS_BIGENDIAN correctly.
|
||||
*
|
||||
* Revision 1.8 2003/03/07 02:44:33 steve
|
||||
* Implement $realtobits.
|
||||
*
|
||||
* Revision 1.7 2003/02/20 00:49:24 steve
|
||||
* detect -lz and -lbz2 libraries.
|
||||
*
|
||||
* Revision 1.6 2003/01/10 19:01:04 steve
|
||||
* Only use libiberty.h if available.
|
||||
*
|
||||
* Revision 1.5 2002/08/11 23:39:33 steve
|
||||
* Remove VVM option.
|
||||
*
|
||||
* Revision 1.4 2002/02/16 03:18:53 steve
|
||||
* Make vvm optional, normally off.
|
||||
*
|
||||
* Revision 1.3 2001/10/18 16:16:23 steve
|
||||
* Include HAVE_SYS_WAIT in config.h (PR#306)
|
||||
*
|
||||
* Revision 1.2 2001/09/15 18:27:04 steve
|
||||
* Make configure detect malloc.h
|
||||
*
|
||||
* Revision 1.1 2001/07/25 03:10:48 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
*/
|
||||
#endif // __config_H
|
||||
|
||||
+3
-3
@@ -92,8 +92,6 @@ AC_C_BIGENDIAN
|
||||
|
||||
# $host
|
||||
|
||||
AX_ENABLE_SUFFIX
|
||||
|
||||
AX_LD_EXTRALIBS
|
||||
|
||||
# Compiler option for position independent code, needed when making shared objects.
|
||||
@@ -121,7 +119,9 @@ AX_C_UNDERSCORES_TRAILING
|
||||
## end of test for underscores
|
||||
#######################
|
||||
|
||||
AX_CPP_IDENT
|
||||
|
||||
# XXX disable tgt-fpga for the moment
|
||||
AC_CONFIG_SUBDIRS(vvp vpi tgt-stub tgt-null tgt-vvp tgt-vhdl libveriuser cadpli)
|
||||
AC_CONFIG_SUBDIRS(vvp vpi tgt-stub tgt-null tgt-vvp libveriuser cadpli)
|
||||
|
||||
AC_OUTPUT(Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
`ifdef CONSTANTS_VAMS
|
||||
`else
|
||||
`define CONSTANTS_VAMS 1
|
||||
|
||||
|
||||
// M_ is a mathematical constant
|
||||
`define M_E 2.7182818284590452354
|
||||
`define M_LOG2E 1.4426950408889634074
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2008 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2005 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -739,8 +739,7 @@ v }
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void replace_with_mos(Design*des, NetMux*obj, NetLogic::TYPE type)
|
||||
static void replace_with_bufif(Design*des, NetMux*obj, NetLogic::TYPE type)
|
||||
{
|
||||
NetScope*scope = obj->scope();
|
||||
NetLogic*tmp = new NetLogic(obj->scope(),
|
||||
@@ -750,7 +749,7 @@ static void replace_with_mos(Design*des, NetMux*obj, NetLogic::TYPE type)
|
||||
des->add_node(tmp);
|
||||
|
||||
connect(obj->pin_Result(), tmp->pin(0));
|
||||
connect(obj->pin_Data(type==NetLogic::PMOS? 0 : 1), tmp->pin(1));
|
||||
connect(obj->pin_Data(type==NetLogic::BUFIF0? 0 : 1), tmp->pin(1));
|
||||
|
||||
if (obj->width() == 1) {
|
||||
/* Special case that the expression is 1 bit
|
||||
@@ -781,11 +780,10 @@ static void replace_with_mos(Design*des, NetMux*obj, NetLogic::TYPE type)
|
||||
|
||||
delete obj;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This detects the case where the mux selects between a value and
|
||||
* Vz. In this case, replace the device with a mos with the sel
|
||||
* Vz. In this case, replace the device with a bufif with the sel
|
||||
* input used to enable the output.
|
||||
*/
|
||||
void cprop_functor::lpm_mux(Design*des, NetMux*obj)
|
||||
@@ -795,34 +793,45 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
|
||||
if (obj->sel_width() != 1)
|
||||
return;
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* This is slower than the actual MUXZ so we are skipping this for now.
|
||||
* If we had a half mux functor this could be faster and more compact
|
||||
* so I'm leaving the code for future reference.
|
||||
*/
|
||||
/* If the first input is all constant Vz, then replace the
|
||||
NetMux with an array of NMOS devices, with the enable
|
||||
NetMux with an array of BUFIF1 devices, with the enable
|
||||
connected to the select input. */
|
||||
if (obj->pin_Data(0).nexus()->drivers_constant() &&
|
||||
obj->pin_Data(0).nexus()->driven_value() == verinum::Vz) {
|
||||
replace_with_mos(des, obj, NetLogic::NMOS);
|
||||
bool flag = true;
|
||||
|
||||
if (! obj->pin_Data(0).nexus()->drivers_constant()) {
|
||||
flag = false;
|
||||
}
|
||||
|
||||
if (flag && obj->pin_Data(0).nexus()->driven_value() != verinum::Vz) {
|
||||
flag = false;
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
replace_with_bufif(des, obj, NetLogic::BUFIF1);
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* If instead the second input is all constant Vz, replace the
|
||||
NetMux with an array of PMOS devices. */
|
||||
if (obj->pin_Data(1).nexus()->drivers_constant() &&
|
||||
obj->pin_Data(1).nexus()->driven_value() == verinum::Vz) {
|
||||
replace_with_mos(des, obj, NetLogic::PMOS);
|
||||
NetMux with an array of BUFIF0 devices. */
|
||||
flag = true;
|
||||
if (! obj->pin_Data(1).nexus()->drivers_constant()) {
|
||||
flag = false;
|
||||
}
|
||||
|
||||
if (flag && obj->pin_Data(1).nexus()->driven_value() != verinum::Vz) {
|
||||
flag = false;
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
replace_with_bufif(des, obj, NetLogic::BUFIF0);
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If the select input is constant, then replace with a BUFZ */
|
||||
bool flag = obj->pin_Sel().nexus()->drivers_constant();
|
||||
flag = obj->pin_Sel().nexus()->drivers_constant();
|
||||
verinum::V sel_val = flag? obj->pin_Sel().nexus()->driven_value() : verinum::Vx;
|
||||
if ((sel_val != verinum::Vz) && (sel_val != verinum::Vx)) {
|
||||
NetBUFZ*tmp = new NetBUFZ(obj->scope(), obj->name(), obj->width());
|
||||
@@ -888,7 +897,7 @@ void cprop_dc_functor::lpm_const(Design*des, NetConst*obj)
|
||||
for (Link*clnk = nex->first_nlink()
|
||||
; clnk ; clnk = clnk->next_nlink()) {
|
||||
|
||||
NetPins*cur;
|
||||
NetObj*cur;
|
||||
unsigned pin;
|
||||
clnk->cur_link(cur, pin);
|
||||
|
||||
@@ -914,7 +923,7 @@ void cprop_dc_functor::lpm_const(Design*des, NetConst*obj)
|
||||
for (Link*clnk = nex->first_nlink()
|
||||
; clnk ; clnk = clnk->next_nlink()) {
|
||||
|
||||
NetPins*cur;
|
||||
NetObj*cur;
|
||||
unsigned pin;
|
||||
clnk->cur_link(cur, pin);
|
||||
|
||||
@@ -965,3 +974,4 @@ void cprop(Design*des)
|
||||
cprop_dc_functor dc;
|
||||
des->functor(&dc);
|
||||
}
|
||||
|
||||
|
||||
+17
-157
@@ -27,7 +27,6 @@
|
||||
# include <iomanip>
|
||||
# include "netlist.h"
|
||||
# include "compiler.h"
|
||||
# include "discipline.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
static ostream& operator<< (ostream&o, NetBlock::Type t)
|
||||
@@ -136,17 +135,6 @@ ostream& operator <<(ostream&o, struct __ScopePathManip marg)
|
||||
return o;
|
||||
}
|
||||
|
||||
void NetBranch::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
static const char*pin_names[2] = {
|
||||
"terminal0",
|
||||
"terminal1" };
|
||||
|
||||
o << setw(ind) << "" << "branch island=" << get_island();
|
||||
o << " // " << get_fileline() << endl;
|
||||
dump_node_pins(o, ind+4, pin_names);
|
||||
}
|
||||
|
||||
void NetDelaySrc::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "specify delay";
|
||||
@@ -199,10 +187,6 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
|
||||
o << " inout";
|
||||
break;
|
||||
}
|
||||
|
||||
if (ivl_discipline_t dis = get_discipline())
|
||||
o << " discipline=" << dis->name();
|
||||
|
||||
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
|
||||
if (scope())
|
||||
o << " scope=" << scope_path(scope());
|
||||
@@ -252,14 +236,11 @@ void NetNode::dump_node(ostream&o, unsigned ind) const
|
||||
/* This is the generic dumping of all the signals connected to each
|
||||
pin of the object. The "this" object is not printed, only the
|
||||
signals connected to this. */
|
||||
void NetPins::dump_node_pins(ostream&o, unsigned ind, const char**pin_names) const
|
||||
void NetObj::dump_node_pins(ostream&o, unsigned ind) const
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||
o << setw(ind) << "" << idx;
|
||||
if (pin_names && pin_names[idx])
|
||||
o << " " << pin_names[idx];
|
||||
else
|
||||
o << " pin" << idx;
|
||||
o << setw(ind) << "" << idx << " " << pin(idx).get_name()
|
||||
<< "<" << pin(idx).get_inst() << ">";
|
||||
|
||||
switch (pin(idx).get_dir()) {
|
||||
case Link::PASSIVE:
|
||||
@@ -308,14 +289,7 @@ void NetAddSub::dump_node(ostream&o, unsigned ind) const
|
||||
o << setw(ind) << "" << "Adder (NetAddSub): " << name()
|
||||
<< " width=" << width() << " pin_count=" << pin_count()
|
||||
<< endl;
|
||||
static const char* pin_names[] = {
|
||||
"Cout ",
|
||||
"DataA ",
|
||||
"DataB ",
|
||||
"Result"
|
||||
};
|
||||
|
||||
dump_node_pins(o, ind+4, pin_names);
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
@@ -328,22 +302,6 @@ void NetArrayDq::dump_node(ostream&o, unsigned ind) const
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetCastInt::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Cast to int. (NetCastInt): " <<
|
||||
name() << " width=" << width() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetCastReal::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Cast to real (NetCastReal): " <<
|
||||
name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetCLShift::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Combinatorial shift (NetCLShift): " <<
|
||||
@@ -354,9 +312,7 @@ void NetCLShift::dump_node(ostream&o, unsigned ind) const
|
||||
|
||||
void NetCompare::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_COMPARE (NetCompare "
|
||||
<< (get_signed()? "signed" : "unsigned") << "): "
|
||||
<< name() << endl;
|
||||
o << setw(ind) << "" << "LPM_COMPARE (NetCompare): " << name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
@@ -590,14 +546,8 @@ void NetReplicate::dump_node(ostream&o, unsigned ind) const
|
||||
|
||||
void NetSignExtend::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NetSignExtend: " << name();
|
||||
if (rise_time())
|
||||
o << " #(" << *rise_time()
|
||||
<< "," << *fall_time()
|
||||
<< "," << *decay_time() << ")";
|
||||
else
|
||||
o << " #(.,.,.)";
|
||||
o << " output width=" << width_ << endl;
|
||||
o << setw(ind) << "" << "NetSignExtend: "
|
||||
<< name() << " output width=" << width_ << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
@@ -689,7 +639,7 @@ void NetTaskDef::dump(ostream&o, unsigned ind) const
|
||||
void NetTran::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << type_ << " " << name()
|
||||
<< " island " << get_island();
|
||||
<< " island " << island;
|
||||
if (type_ == IVL_SW_TRAN_VP) {
|
||||
o << " width=" << vector_width()
|
||||
<< " part=" << part_width()
|
||||
@@ -713,11 +663,11 @@ void NetUDP::dump_node(ostream&o, unsigned ind) const
|
||||
void NetProcTop::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
switch (type_) {
|
||||
case IVL_PR_INITIAL:
|
||||
case NetProcTop::KINITIAL:
|
||||
o << "initial /* " << get_fileline() << " in "
|
||||
<< scope_path(scope_) << " */" << endl;
|
||||
break;
|
||||
case IVL_PR_ALWAYS:
|
||||
case NetProcTop::KALWAYS:
|
||||
o << "always /* " << get_fileline() << " in "
|
||||
<< scope_path(scope_) << " */" << endl;
|
||||
break;
|
||||
@@ -731,28 +681,6 @@ void NetProcTop::dump(ostream&o, unsigned ind) const
|
||||
statement_->dump(o, ind+2);
|
||||
}
|
||||
|
||||
void NetAnalogTop::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
switch (type_) {
|
||||
case IVL_PR_INITIAL:
|
||||
o << "analog initial /* " << get_fileline() << " in "
|
||||
<< scope_path(scope_) << " */" << endl;
|
||||
break;
|
||||
|
||||
case IVL_PR_ALWAYS:
|
||||
o << "analog /* " << get_fileline() << " in "
|
||||
<< scope_path(scope_) << " */" << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
statement_->dump(o, ind+2);
|
||||
}
|
||||
|
||||
void NetAlloc::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "// allocate storage : " << scope_path(scope_) << endl;
|
||||
}
|
||||
|
||||
void NetAssign_::dump_lval(ostream&o) const
|
||||
{
|
||||
if (sig_) {
|
||||
@@ -804,11 +732,6 @@ void NetAssignNB::dump(ostream&o, unsigned ind) const
|
||||
|
||||
if (const NetExpr*de = get_delay())
|
||||
o << "#(" << *de << ") ";
|
||||
if (count_)
|
||||
o << "repeat(" << *count_ << ") ";
|
||||
if (event_) {
|
||||
o << *event_;
|
||||
}
|
||||
|
||||
o << *rval() << ";" << endl;
|
||||
|
||||
@@ -896,15 +819,6 @@ void NetCondit::dump(ostream&o, unsigned ind) const
|
||||
}
|
||||
}
|
||||
|
||||
void NetContribution::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "";
|
||||
lval_->dump(o);
|
||||
o << " <+ ";
|
||||
rval_->dump(o);
|
||||
o << ";" << endl;
|
||||
}
|
||||
|
||||
void NetDeassign::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "deassign ";
|
||||
@@ -962,25 +876,6 @@ void NetEvWait::dump(ostream&o, unsigned ind) const
|
||||
o << setw(ind+2) << "" << "/* noop */ ;" << endl;
|
||||
}
|
||||
|
||||
ostream& operator << (ostream&out, const NetEvWait&obj)
|
||||
{
|
||||
obj.dump_inline(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
void NetEvWait::dump_inline(ostream&o) const
|
||||
{
|
||||
o << "@(";
|
||||
|
||||
if (nevents() > 0)
|
||||
o << event(0)->name();
|
||||
|
||||
for (unsigned idx = 1 ; idx < nevents() ; idx += 1)
|
||||
o << " or " << event(idx)->name();
|
||||
|
||||
o << ") ";
|
||||
}
|
||||
|
||||
void NetForce::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "force ";
|
||||
@@ -994,11 +889,6 @@ void NetForever::dump(ostream&o, unsigned ind) const
|
||||
statement_->dump(o, ind+2);
|
||||
}
|
||||
|
||||
void NetFree::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "// free storage : " << scope_path(scope_) << endl;
|
||||
}
|
||||
|
||||
void NetFuncDef::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "function definition for " << scope_path(scope_) << endl;
|
||||
@@ -1092,7 +982,6 @@ void NetScope::dump(ostream&o) const
|
||||
o << " generate block";
|
||||
break;
|
||||
}
|
||||
if (is_auto()) o << " (automatic)";
|
||||
o << endl;
|
||||
|
||||
for (unsigned idx = 0 ; idx < attr_cnt() ; idx += 1)
|
||||
@@ -1109,8 +998,6 @@ void NetScope::dump(ostream&o) const
|
||||
; pp != parameters.end() ; pp ++) {
|
||||
o << " parameter ";
|
||||
|
||||
o << pp->second.type << " ";
|
||||
|
||||
if ((*pp).second.signed_flag)
|
||||
o << "signed ";
|
||||
|
||||
@@ -1160,7 +1047,7 @@ void NetScope::dump(ostream&o) const
|
||||
|
||||
/* Dump the saved defparam assignments here. */
|
||||
{
|
||||
list<pair<pform_name_t,NetExpr*> >::const_iterator pp;
|
||||
map<pform_name_t,NetExpr*>::const_iterator pp;
|
||||
for (pp = defparams.begin()
|
||||
; pp != defparams.end() ; pp ++ ) {
|
||||
o << " defparam " << (*pp).first << " = " <<
|
||||
@@ -1168,15 +1055,6 @@ void NetScope::dump(ostream&o) const
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
list<pair<list<hname_t>,NetExpr*> >::const_iterator pp;
|
||||
for (pp = defparams_later.begin()
|
||||
; pp != defparams_later.end() ; pp ++ ) {
|
||||
o << " defparam(later) " << pp->first << " = " <<
|
||||
*(pp->second) << ";" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dump the events in this scope. */
|
||||
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_) {
|
||||
o << " event " << cur->name() << "; nprobe="
|
||||
@@ -1185,9 +1063,12 @@ void NetScope::dump(ostream&o) const
|
||||
}
|
||||
|
||||
// Dump the signals,
|
||||
for (signals_map_iter_t cur = signals_map_.begin()
|
||||
; cur != signals_map_.end() ; cur ++) {
|
||||
cur->second->dump_net(o, 4);
|
||||
if (signals_) {
|
||||
NetNet*cur = signals_->sig_next_;
|
||||
do {
|
||||
cur->dump_net(o, 4);
|
||||
cur = cur->sig_next_;
|
||||
} while (cur != signals_->sig_next_);
|
||||
}
|
||||
|
||||
// Dump specparams
|
||||
@@ -1276,18 +1157,6 @@ void NetExpr::dump(ostream&o) const
|
||||
o << "(?" << typeid(*this).name() << "?)";
|
||||
}
|
||||
|
||||
void NetEAccess::dump(ostream&o) const
|
||||
{
|
||||
o << nature_->name() << "." << nature_->access() << "(";
|
||||
assert(branch_);
|
||||
if (branch_->pin(0).is_linked())
|
||||
o << branch_->pin(0).nexus()->name();
|
||||
o << ", ";
|
||||
if (branch_->pin(1).is_linked())
|
||||
o << branch_->pin(1).nexus()->name();
|
||||
o << ")";
|
||||
}
|
||||
|
||||
void NetEBinary::dump(ostream&o) const
|
||||
{
|
||||
if (op_ == 'm' || op_ == 'M') {
|
||||
@@ -1522,19 +1391,10 @@ void Design::dump(ostream&o) const
|
||||
} while (cur != nodes_->node_next_);
|
||||
}
|
||||
|
||||
o << "ELABORATED BRANCHES:" << endl;
|
||||
|
||||
if (branches_) {
|
||||
for (NetBranch*cur = branches_ ; cur ; cur = cur->next_)
|
||||
cur->dump(o, 0);
|
||||
}
|
||||
|
||||
o << "ELABORATED PROCESSES:" << endl;
|
||||
|
||||
// Dump the processes.
|
||||
for (const NetProcTop*idx = procs_ ; idx ; idx = idx->next_)
|
||||
idx->dump(o, 0);
|
||||
|
||||
for (const NetAnalogTop*idx = aprocs_ ; idx ; idx = idx->next_)
|
||||
idx->dump(o, 0);
|
||||
}
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
|
||||
Developer Quick Start for Icarus Verilog
|
||||
|
||||
The documentation for getting, building and installing Icarus Verilog
|
||||
is kept and maintained at the iverilog documentation wiki at
|
||||
<http://iverilog.wikia.com>. See the Installation Guide for getting
|
||||
the current source from the git repository (and how to use the git
|
||||
repository) and see the Developer Guide for instructions on
|
||||
participating in the Icarus Verilog development process. That
|
||||
information will not be repeated here.
|
||||
|
||||
What this documentation *will* cover is the gross structure of the
|
||||
Icarus Verilog compiler source. This will help orient you to the
|
||||
source code itself, so that you can find the global parts where you
|
||||
can look for even better detail.
|
||||
|
||||
|
||||
* Compiler Components
|
||||
|
||||
- The compiler driver (driver/)
|
||||
|
||||
This is the binary that is installed as "iverilog". This program takes
|
||||
the command line arguments and assembles invocations of all the other
|
||||
subcommands to perform the steps of compilation.
|
||||
|
||||
- The preprocessor (ivlpp/)
|
||||
|
||||
This implements the Verilog pre-processor. In Icarus Verilog, the
|
||||
compiler directives `define, `include, `ifdef and etc. are implemented
|
||||
in an external program. The ivlpp/ directory contains the source for
|
||||
this program.
|
||||
|
||||
- The core compiler (this directory)
|
||||
|
||||
The "ivl" program is the core that does all the Verilog compiler
|
||||
processing that is not handled elsewhere. This is the main core of the
|
||||
Icarus Verilog compiler, not the runtime. See below for more details
|
||||
on the core itself.
|
||||
|
||||
- The loadable code generators (tgt-*/)
|
||||
|
||||
This core compiler, after it is finished with parsing and semantic
|
||||
analysis, uses loadable code generators to emit code for supported
|
||||
targets. The tgt-*/ directories contains the source for the target
|
||||
code generators that are bundled with Icarus Verilog. The tgt-vvp/
|
||||
directory in particular contains the code generator for the vvp
|
||||
runtime.
|
||||
|
||||
|
||||
* Runtime Components
|
||||
|
||||
- The vvp runtime (vvp/)
|
||||
|
||||
This program implements the runtime environment for Icarus
|
||||
Verilog. It implements the "vvp" command described in the user
|
||||
documentation. See the vvp/ subdirectory for further developer
|
||||
documentation.
|
||||
|
||||
- The system tasks implementations (vpi/)
|
||||
|
||||
The standard Verilog system tasks are implemented using VPI (PLI-2)
|
||||
and the source is in this subdirectory.
|
||||
|
||||
- The PLI-1 compatibility library (libveriuser/)
|
||||
|
||||
The Icarus Verilog support for the deprecated PLI-1 is in this
|
||||
subdirectory. The vvp runtime does not directly support the
|
||||
PLI-1. Instead, the libveriuser library emulates it using the builtin
|
||||
PLI-2 support.
|
||||
|
||||
- The Cadence PLI module compatibility module (cadpli/)
|
||||
|
||||
It is possible in some specialized situations to load and execute
|
||||
PLI-1 code written for Verilog-XL. This directory contains the source
|
||||
for the module that provides the Cadence PLI interface.
|
||||
|
||||
|
||||
* The Core Compiler
|
||||
|
||||
The "ivl" binary is the core compiler that does the heavy lifting of
|
||||
compiling the Verilog source (including libraries) and generating the
|
||||
output. This is the most complex component of the Icarus Verilog
|
||||
compilation system.
|
||||
|
||||
The process in the abstract starts with the Verilog lexical analysis
|
||||
and parsing to generate an internal "pform". The pform is then
|
||||
translated by elaboration into the "netlist" form. The netlist is
|
||||
processed by some functors (which include some optimizations and
|
||||
optional synthesis) then is translated into the ivl_target internal
|
||||
form. And finally, the ivl_target form is passed via the ivl_target.h
|
||||
API to the code generators.
|
||||
|
||||
- Lexical Analysis
|
||||
|
||||
Lexical analysis and parsing use the tools "flex", "gperf", and
|
||||
"bison". The "flex" input file "lexor.lex" recognizes the tokens in
|
||||
the input stream. This is called "lexical analysis". The lexical
|
||||
analyzer also does some processing of compiler directives that are not
|
||||
otherwise taken care of by the external preprocessor. The lexical
|
||||
analyzer uses a table of keywords that is generated using the "gperf"
|
||||
program and the input file "lexor_keywords.gperf". This table allows
|
||||
the lexical analyzer to efficiently check input words with the rather
|
||||
large set of potential keywords.
|
||||
|
||||
- Parsing
|
||||
|
||||
The parser input file "parse.y" is passed to the "bison" program to
|
||||
generate the parser. The parser uses the functions in parse*.h,
|
||||
parse*.cc, pform.h, and pform*.cc to generate the pform from the
|
||||
stream of input tokens. The pform is what compiler writers call a
|
||||
"decorated parse tree".
|
||||
|
||||
The pform itself is described by the classes in the header files
|
||||
"PScope.h", "Module.h", "PGenerate.h", "Statement.h", and
|
||||
"PExpr.h". The implementations of the classes in those header files
|
||||
are in the similarly named C++ files.
|
||||
|
||||
- Elaboration
|
||||
|
||||
Elaboration transforms the pform to the netlist form. Elaboration is
|
||||
conceptually divided into several major steps: Scope elaboration,
|
||||
parameter overrides and defparam propagation, signal elaboration, and
|
||||
statement and expression elaboration.
|
||||
|
||||
The elaboration of scopes and parameter overrides and defparam
|
||||
propagation are conceptually separate, but are in practice
|
||||
intermingled. The elaboration of scopes scans the pform to find and
|
||||
instantiate all the scopes of the design. New scopes are created by
|
||||
instantiation of modules (starting with the root instances) by user
|
||||
defined tasks and functions, named blocks, and generate schemes. The
|
||||
elaborate_scope methods implement scope elaboration, and the
|
||||
elab_scope.cc source file has the implementations of those
|
||||
methods.
|
||||
|
||||
The elaborate.cc source file contains the initial calls to the
|
||||
elaborate_scope for the root scopes to get the process started. In
|
||||
particular, see the "elaborate" function near the bottom of the
|
||||
elaborate.cc source file. The calls to Design::make_root_scope create
|
||||
the initial root scopes, and the creation and enqueue of the
|
||||
elaborate_root_scope_t work items primes the scope elaboration work
|
||||
list.
|
||||
|
||||
Intermingled in the work list are defparms work items that call the
|
||||
Design::run_defparams and Design::evaluate_parameters methods that
|
||||
override and evaluate parameters. The override and evaluation of
|
||||
parameters must be intermingled with the elaboration of scopes because
|
||||
the exact values of parameters may impact the scopes created (imagine
|
||||
generate schemes and instance arrays) and the created scopes in turn
|
||||
create new parameters that need override and evaluation.
|
||||
+7
-7
@@ -19,21 +19,21 @@
|
||||
|
||||
# include "discipline.h"
|
||||
|
||||
ivl_nature_s::ivl_nature_s(perm_string name__, perm_string access__)
|
||||
: name_(name__), access_(access__)
|
||||
nature_t::nature_t(perm_string name, perm_string access)
|
||||
: name_(name), access_(access)
|
||||
{
|
||||
}
|
||||
|
||||
ivl_nature_s::~ivl_nature_s()
|
||||
nature_t::~nature_t()
|
||||
{
|
||||
}
|
||||
|
||||
ivl_discipline_s::ivl_discipline_s(perm_string name__, ivl_dis_domain_t domain__,
|
||||
ivl_nature_t pot, ivl_nature_t flow__)
|
||||
: name_(name__), domain_(domain__), potential_(pot), flow_(flow__)
|
||||
discipline_t::discipline_t(perm_string name, ddomain_t domain,
|
||||
nature_t*pot, nature_t*flow)
|
||||
: name_(name), domain_(domain), potential_(pot), flow_(flow)
|
||||
{
|
||||
}
|
||||
|
||||
ivl_discipline_s::~ivl_discipline_s()
|
||||
discipline_t::~discipline_t()
|
||||
{
|
||||
}
|
||||
|
||||
+19
-21
@@ -28,15 +28,15 @@
|
||||
# include "StringHeap.h"
|
||||
# include <iostream>
|
||||
# include <map>
|
||||
# include "ivl_target.h"
|
||||
# include "LineInfo.h"
|
||||
|
||||
extern std::ostream& operator << (std::ostream&, ivl_dis_domain_t);
|
||||
typedef enum { DD_NONE, DD_DISCRETE, DD_CONTINUOUS } ddomain_t;
|
||||
extern std::ostream& operator << (std::ostream&, ddomain_t);
|
||||
|
||||
class ivl_nature_s : public LineInfo {
|
||||
class nature_t : public LineInfo {
|
||||
public:
|
||||
explicit ivl_nature_s(perm_string name, perm_string access);
|
||||
~ivl_nature_s();
|
||||
explicit nature_t(perm_string name, perm_string access);
|
||||
~nature_t();
|
||||
|
||||
perm_string name() const { return name_; }
|
||||
// Identifier for the access function for this nature
|
||||
@@ -47,31 +47,29 @@ class ivl_nature_s : public LineInfo {
|
||||
perm_string access_;
|
||||
};
|
||||
|
||||
class ivl_discipline_s : public LineInfo {
|
||||
class discipline_t : public LineInfo {
|
||||
public:
|
||||
explicit ivl_discipline_s (perm_string name, ivl_dis_domain_t dom,
|
||||
ivl_nature_t pot, ivl_nature_t flow);
|
||||
~ivl_discipline_s();
|
||||
explicit discipline_t (perm_string name, ddomain_t dom,
|
||||
nature_t*pot, nature_t*flow);
|
||||
~discipline_t();
|
||||
|
||||
perm_string name() const { return name_; }
|
||||
ivl_dis_domain_t domain() const { return domain_; }
|
||||
const ivl_nature_t potential() const { return potential_; }
|
||||
const ivl_nature_t flow() const { return flow_; }
|
||||
ddomain_t domain() const { return domain_; }
|
||||
const nature_t*potential() const { return potential_; }
|
||||
const nature_t*flow() const { return flow_; }
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
ivl_dis_domain_t domain_;
|
||||
ivl_nature_t potential_;
|
||||
ivl_nature_t flow_;
|
||||
ddomain_t domain_;
|
||||
nature_t*potential_;
|
||||
nature_t*flow_;
|
||||
|
||||
private: // not implemented
|
||||
ivl_discipline_s(const ivl_discipline_s&);
|
||||
ivl_discipline_s& operator = (const ivl_discipline_s&);
|
||||
discipline_t(const discipline_t&);
|
||||
discipline_t& operator = (const discipline_t&);
|
||||
};
|
||||
|
||||
extern map<perm_string,ivl_nature_t> natures;
|
||||
extern map<perm_string,ivl_discipline_t> disciplines;
|
||||
// Map access function name to the nature that it accesses.
|
||||
extern map<perm_string,ivl_nature_t> access_function_nature;
|
||||
extern map<perm_string,nature_t*> natures;
|
||||
extern map<perm_string,discipline_t*> disciplines;
|
||||
|
||||
#endif
|
||||
|
||||
+5
-10
@@ -20,8 +20,6 @@ SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.9.devel
|
||||
|
||||
suffix = @install_suffix@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
@@ -29,8 +27,6 @@ datarootdir = @datarootdir@
|
||||
|
||||
VPATH = $(srcdir)
|
||||
|
||||
suffix = @install_suffix@
|
||||
|
||||
bindir = $(exec_prefix)/bin
|
||||
libdir = $(exec_prefix)/lib
|
||||
includedir = $(prefix)/include
|
||||
@@ -43,7 +39,7 @@ INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
CPPFLAGS = -I. -I$(srcdir)/.. -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@
|
||||
CPPFLAGS = @ident_support@ -I. -I$(srcdir)/.. -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = -Wall @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
@@ -69,7 +65,6 @@ main.o: main.c config.h
|
||||
|
||||
config.h: config.h.in
|
||||
sed -e 's;@IVLCC@;@CC@;' -e 's;@IVLCXX@;@CXX@;' \
|
||||
-e 's;@SUFFIX@;$(suffix);g' \
|
||||
-e 's;@IVLCFLAGS@;@CXXFLAGS@;' \
|
||||
-e 's;@SHARED@;@shared@;' $< > $@
|
||||
|
||||
@@ -78,13 +73,13 @@ res.o: res.rc
|
||||
windres -i res.rc -o res.o
|
||||
#
|
||||
|
||||
install: all installdirs $(bindir)/iverilog-vpi$(suffix)@EXEEXT@
|
||||
install: all installdirs $(bindir)/iverilog-vpi@EXEEXT@
|
||||
|
||||
$(bindir)/iverilog-vpi$(suffix)@EXEEXT@: ./iverilog-vpi@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./iverilog-vpi@EXEEXT@ $(bindir)/iverilog-vpi$(suffix)@EXEEXT@
|
||||
$(bindir)/iverilog-vpi@EXEEXT@: ./iverilog-vpi@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./iverilog-vpi@EXEEXT@ $(bindir)/iverilog-vpi@EXEEXT@
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs $(bindir)
|
||||
|
||||
uninstall:
|
||||
rm -f $(bindir)/iverilog-vpi$(suffix)@EXEEXT@
|
||||
rm -f $(bindir)/iverilog-vpi@EXEEXT@
|
||||
|
||||
@@ -5,5 +5,4 @@
|
||||
#define IVERILOG_VPI_CXX "@IVLCXX@"
|
||||
#define IVERILOG_VPI_CFLAGS " @IVLCFLAGS@"
|
||||
#define IVERILOG_VPI_LDFLAGS "@SHARED@"
|
||||
#define IVERILOG_VPI_LDLIBS "-lveriuser@SUFFIX@ -lvpi@SUFFIX@"
|
||||
#define IVERILOG_SUFFIX "@SUFFIX@"
|
||||
#define IVERILOG_VPI_LDLIBS "-lveriuser -lvpi"
|
||||
|
||||
+14
-10
@@ -87,9 +87,9 @@ static void myExit(int exitVal)
|
||||
|
||||
static void usage()
|
||||
{
|
||||
fprintf(stderr,"usage: iverilog-vpi" IVERILOG_SUFFIX " [src and obj files]...\n");
|
||||
fprintf(stderr," or iverilog-vpi" IVERILOG_SUFFIX " -mingw=dir\n");
|
||||
fprintf(stderr," or iverilog-vpi" IVERILOG_SUFFIX " -ivl=dir\n");
|
||||
fprintf(stderr,"usage: iverilog-vpi [src and obj files]...\n");
|
||||
fprintf(stderr," or iverilog-vpi -mingw=dir\n");
|
||||
fprintf(stderr," or iverilog-vpi -ivl=dir\n");
|
||||
myExit(1);
|
||||
}
|
||||
|
||||
@@ -384,7 +384,7 @@ static int parse(int argc, char *argv[])
|
||||
/* Check for the --install-dir option */
|
||||
else if (stricmp("--install-dir", argv[idx]) == 0) {
|
||||
setup_ivl_environment();
|
||||
printf("%s\\\\lib\\\\ivl" IVERILOG_SUFFIX "\\\\.\n", gstr.pIVL);
|
||||
printf("%s\\\\lib\\\\ivl\\\\.\n", gstr.pIVL);
|
||||
myExit(0);
|
||||
}
|
||||
/* This is different than iverilog-vpi.sh, we don't
|
||||
@@ -444,14 +444,14 @@ static void checkIvlDir(char *root)
|
||||
initDynString(&path);
|
||||
assign(&path,gstr.pIVL);
|
||||
appendBackSlash(&path);
|
||||
append(&path,"bin\\vvp" IVERILOG_SUFFIX ".exe");
|
||||
append(&path,"bin\\vvp.exe");
|
||||
|
||||
irv = _stat(path,&stat_buf);
|
||||
deInitDynString(path);
|
||||
|
||||
if (irv) {
|
||||
fprintf(stderr,"error: %s does not appear to be the valid root directory of\n",root);
|
||||
fprintf(stderr," Icarus Verilog. Use the -ivl option of iverilog-vpi" IVERILOG_SUFFIX " to\n");
|
||||
fprintf(stderr," Icarus Verilog. Use the -ivl option of iverilog-vpi.exe to\n");
|
||||
fprintf(stderr," point to the Icarus Verilog root directory. For a Windows\n");
|
||||
fprintf(stderr," command shell the option would be something like -ivl=c:\\iverilog\n");
|
||||
fprintf(stderr," For a Cygwin shell the option would be something like\n");
|
||||
@@ -503,7 +503,7 @@ static void setup_ivl_environment()
|
||||
SetRegistryKey(IVL_REGKEY_IVL,gstr.pIVL);
|
||||
} else if (!GetRegistryKey(IVL_REGKEY_IVL,&gstr.pIVL)) {
|
||||
fprintf(stderr,"error: can not locate the Icarus Verilog root directory, use the -ivl option\n");
|
||||
fprintf(stderr," of iverilog-vpi" IVERILOG_SUFFIX " to point to the Icarus Verilog root directory.\n");
|
||||
fprintf(stderr," of iverilog-vpi.exe to point to the Icarus Verilog root directory.\n");
|
||||
fprintf(stderr," For a Windows command shell the option would be something like\n");
|
||||
fprintf(stderr," -ivl=c:\\iverilog For a Cygwin shell the option would be something\n");
|
||||
fprintf(stderr," like -ivl=c:\\\\iverilog\n");
|
||||
@@ -511,16 +511,20 @@ static void setup_ivl_environment()
|
||||
}
|
||||
|
||||
/* Build up the CFLAGS option string */
|
||||
assign(&gstr.pCFLAGS,IVERILOG_VPI_CFLAGS " -I");
|
||||
assign(&gstr.pCFLAGS,IVERILOG_VPI_CFLAGS);
|
||||
append(&gstr.pCFLAGS," -I");
|
||||
append(&gstr.pCFLAGS,gstr.pIVL);
|
||||
appendBackSlash(&gstr.pCFLAGS);
|
||||
append(&gstr.pCFLAGS,"\\include\\\\iverilog" IVERILOG_SUFFIX);
|
||||
append(&gstr.pCFLAGS, "\\");
|
||||
append(&gstr.pCFLAGS,"include");
|
||||
|
||||
/* Build up the LDFLAGS option string */
|
||||
assign(&gstr.pLDLIBS,"-L");
|
||||
append(&gstr.pLDLIBS,gstr.pIVL);
|
||||
appendBackSlash(&gstr.pLDLIBS);
|
||||
append(&gstr.pLDLIBS,"\\lib " IVERILOG_VPI_LDLIBS);
|
||||
append(&gstr.pLDLIBS, "\\");
|
||||
append(&gstr.pLDLIBS,"lib ");
|
||||
append(&gstr.pLDLIBS,IVERILOG_VPI_LDLIBS);
|
||||
}
|
||||
|
||||
/* compile source modules */
|
||||
|
||||
+16
-18
@@ -20,8 +20,6 @@ SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.9.devel
|
||||
|
||||
suffix = @install_suffix@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
@@ -43,7 +41,7 @@ INSTALL_DATA = @INSTALL_DATA@
|
||||
MAN = @MAN@
|
||||
PS2PDF = @PS2PDF@
|
||||
|
||||
CPPFLAGS = -I. -I.. -I$(srcdir)/.. -I$(srcdir) -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@
|
||||
CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir)/.. -I$(srcdir) -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = -Wall @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
@@ -70,7 +68,7 @@ cfparse.h cfparse.c: cfparse.y
|
||||
|
||||
|
||||
main.o: main.c globals.h ../version.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -c -DIVL_ROOT='"@libdir@/ivl$(suffix)"' -DIVL_INC='"@includedir@"' -DIVL_LIB='"@libdir@"' -DDLLIB='"@DLLIB@"' $(srcdir)/main.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -c -DIVL_ROOT='"@libdir@/ivl"' -DIVL_INC='"@includedir@"' -DIVL_LIB='"@libdir@"' -DDLLIB='"@DLLIB@"' $(srcdir)/main.c
|
||||
|
||||
build_string.o: build_string.c globals.h
|
||||
cflexor.o: cflexor.c cfparse.h cfparse_misc.h globals.h
|
||||
@@ -84,35 +82,35 @@ iverilog.pdf: iverilog.ps
|
||||
|
||||
ifeq (@MINGW32@,yes)
|
||||
ifeq ($(MAN),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog$(suffix).1
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog.1
|
||||
else
|
||||
ifeq ($(PS2PDF),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog$(suffix).1
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog.1
|
||||
else
|
||||
INSTALL_DOC = $(prefix)/iverilog$(suffix).pdf $(mandir)/man1/iverilog$(suffix).1
|
||||
INSTALL_DOC = $(prefix)/iverilog.pdf $(mandir)/man1/iverilog.1
|
||||
all: iverilog.pdf
|
||||
endif
|
||||
endif
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
else
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog$(suffix).1
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog.1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
endif
|
||||
|
||||
install: all installdirs $(bindir)/iverilog$(suffix)@EXEEXT@ $(INSTALL_DOC)
|
||||
install: all installdirs $(bindir)/iverilog@EXEEXT@ $(INSTALL_DOC)
|
||||
|
||||
$(bindir)/iverilog$(suffix)@EXEEXT@: ./iverilog@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./iverilog@EXEEXT@ $(DESTDIR)$(bindir)/iverilog$(suffix)@EXEEXT@
|
||||
$(bindir)/iverilog@EXEEXT@: ./iverilog@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./iverilog@EXEEXT@ $(bindir)/iverilog@EXEEXT@
|
||||
|
||||
$(mandir)/man1/iverilog$(suffix).1: $(srcdir)/iverilog.man
|
||||
$(INSTALL_DATA) $(srcdir)/iverilog.man $(DESTDIR)$(mandir)/man1/iverilog$(suffix).1
|
||||
$(mandir)/man1/iverilog.1: $(srcdir)/iverilog.man
|
||||
$(INSTALL_DATA) $(srcdir)/iverilog.man $(mandir)/man1/iverilog.1
|
||||
|
||||
$(prefix)/iverilog$(suffix).pdf: iverilog.pdf
|
||||
$(INSTALL_DATA) iverilog.pdf $(prefix)/iverilog$(suffix).pdf
|
||||
$(prefix)/iverilog.pdf: iverilog.pdf
|
||||
$(INSTALL_DATA) iverilog.pdf $(prefix)/iverilog.pdf
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs $(DESTDIR)$(bindir) $(DESTDIR)$(INSTALL_DOCDIR)
|
||||
$(srcdir)/../mkinstalldirs $(bindir) $(INSTALL_DOCDIR)
|
||||
|
||||
uninstall:
|
||||
rm -f $(DESTDIR)$(bindir)/iverilog$(suffix)@EXEEXT@
|
||||
rm -f $(DESTDIR)$(mandir)/man1/iverilog$(suffix).1 $(DESTDIR)$(prefix)/iverilog$(suffix).pdf
|
||||
rm -f $(bindir)/iverilog@EXEEXT@
|
||||
rm -f $(mandir)/man1/iverilog.1 $(prefix)/iverilog.pdf
|
||||
|
||||
+1
-1
@@ -149,7 +149,7 @@ int cmdfile_stack_ptr = 0;
|
||||
cflval.text = trim_trailing_white(yytext, 0);
|
||||
BEGIN(0);
|
||||
return TOK_STRING; }
|
||||
|
||||
|
||||
/* Fallback match. */
|
||||
. { return yytext[0]; }
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: globals.h,v 1.21 2007/04/19 02:52:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stddef.h>
|
||||
|
||||
@@ -75,4 +78,36 @@ extern char warning_flags[];
|
||||
extern char* library_flags;
|
||||
extern char* library_flags2;
|
||||
|
||||
/*
|
||||
* $Log: globals.h,v $
|
||||
* Revision 1.21 2007/04/19 02:52:53 steve
|
||||
* Add support for -v flag in command file.
|
||||
*
|
||||
* Revision 1.20 2007/03/07 04:24:59 steve
|
||||
* Make integer width controllable.
|
||||
*
|
||||
* Revision 1.19 2003/11/18 06:31:46 steve
|
||||
* Remove the iverilog.conf file.
|
||||
*
|
||||
* Revision 1.18 2003/11/13 04:09:49 steve
|
||||
* Pass flags through the temporary config file.
|
||||
*
|
||||
* Revision 1.17 2003/11/01 04:21:57 steve
|
||||
* Add support for a target static config file.
|
||||
*
|
||||
* Revision 1.16 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.15 2002/06/23 20:10:51 steve
|
||||
* Variable substitution in command files.
|
||||
*
|
||||
* Revision 1.14 2002/05/28 20:40:37 steve
|
||||
* ivl indexes the search path for libraries, and
|
||||
* supports case insensitive module-to-file lookup.
|
||||
*
|
||||
* Revision 1.13 2002/05/28 00:50:40 steve
|
||||
* Add the ivl -C flag for bulk configuration
|
||||
* from the driver, and use that to run library
|
||||
* modules through the preprocessor.
|
||||
*/
|
||||
#endif
|
||||
|
||||
+13
-9
@@ -1,4 +1,4 @@
|
||||
.TH iverilog 1 "April 22nd, 2008" "" "Version 0.9.devel"
|
||||
.TH iverilog 1 "April 22nd, 2008" Version "0.9.devel"
|
||||
.SH NAME
|
||||
iverilog - Icarus Verilog compiler
|
||||
|
||||
@@ -14,7 +14,7 @@ iverilog - Icarus Verilog compiler
|
||||
\fIiverilog\fP is a compiler that translates Verilog source code into
|
||||
executable programs for simulation, or other netlist formats for
|
||||
further processing. The currently supported targets are \fIvvp\fP for
|
||||
simulation, and \fIfpga\fP for synthesis. Other target
|
||||
simulation, and \fIxnf\fP and \fIfpga\fP for synthesis. Other target
|
||||
types are added as code generators are implemented.
|
||||
|
||||
.SH OPTIONS
|
||||
@@ -68,7 +68,7 @@ other tools.
|
||||
Enable or disable (default) support for Verilog-AMS.
|
||||
.TP 8
|
||||
.B -gspecify\fI|\fP-gno-specify
|
||||
Enable or disable (default) specify block support. When enabled,
|
||||
Enable (default) or disable specify block support. When enabled,
|
||||
specify block code is elaborated. When disabled, specify blocks are
|
||||
parsed but ignored. Specify blocks are commonly not needed for RTL
|
||||
simulation, and in fact can hurt performance of the
|
||||
@@ -212,18 +212,17 @@ This is the default. The vvp target generates code for the vvp
|
||||
runtime. The output is a complete program that simulates the design
|
||||
but must be run by the \fBvvp\fP command.
|
||||
.TP 8
|
||||
.B xnf
|
||||
This is the Xilinx Netlist Format used by many tools for placing
|
||||
devices in FPGAs or other programmable devices. This target is
|
||||
obsolete, use the \fBfpga\fP target instead.
|
||||
.TP 8
|
||||
.B fpga
|
||||
This is a synthesis target that supports a variety of fpga devices,
|
||||
mostly by EDIF format output. The Icarus Verilog fpga code generator
|
||||
can generate complete designs or EDIF macros that can in turn be
|
||||
imported into larger designs by other tools. The \fBfpga\fP target
|
||||
implies the synthesis \fB-S\fP flag.
|
||||
.TP 8
|
||||
.B vhdl
|
||||
This target produces a VHDL translation of the Verilog netlist. The
|
||||
output is a single file containing VHDL entities corresponding to
|
||||
the modules in the Verilog source code. Note that only a subset of
|
||||
the Verilog language is supported. See the wiki for more information.
|
||||
|
||||
.SH "WARNING TYPES"
|
||||
These are the types of warnings that can be selected by the \fB-W\fP
|
||||
@@ -413,6 +412,11 @@ To compile and run explicitly using the vvp runtime:
|
||||
|
||||
iverilog -ohello.vvp -tvvp hello.v
|
||||
|
||||
To compile hello.v to a file in XNF-format called hello.xnf
|
||||
|
||||
iverilog -txnf -ohello.xnf hello.v
|
||||
|
||||
|
||||
.SH "AUTHOR"
|
||||
.nf
|
||||
Steve Williams ([email protected])
|
||||
|
||||
+82
-154
@@ -31,9 +31,9 @@ const char NOTICE[] =
|
||||
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
||||
" GNU General Public License for more details.\n"
|
||||
"\n"
|
||||
" You should have received a copy of the GNU General Public License along\n"
|
||||
" with this program; if not, write to the Free Software Foundation, Inc.,\n"
|
||||
" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n"
|
||||
" You should have received a copy of the GNU General Public License\n"
|
||||
" along with this program; if not, write to the Free Software\n"
|
||||
" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\n"
|
||||
;
|
||||
|
||||
const char HELP[] =
|
||||
@@ -51,7 +51,6 @@ const char HELP[] =
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
@@ -107,8 +106,8 @@ const char*npath = 0;
|
||||
const char*targ = "vvp";
|
||||
const char*depfile = 0;
|
||||
|
||||
const char*generation = "2005";
|
||||
const char*gen_specify = "no-specify";
|
||||
const char*generation = "2x";
|
||||
const char*gen_specify = "specify";
|
||||
const char*gen_xtypes = "xtypes";
|
||||
const char*gen_icarus = "icarus-misc";
|
||||
const char*gen_io_range_error = "io-range-error";
|
||||
@@ -260,120 +259,18 @@ static const char*my_tempfile(const char*str, FILE**fout)
|
||||
return pathbuf;
|
||||
}
|
||||
|
||||
static int t_version_only(void)
|
||||
{
|
||||
int rc;
|
||||
remove(source_path);
|
||||
free(source_path);
|
||||
|
||||
fflush(0);
|
||||
snprintf(tmp, sizeof tmp, "%s%civlpp -V", pbase, sep);
|
||||
rc = system(tmp);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "Unable to get version from \"%s\"\n", tmp);
|
||||
}
|
||||
|
||||
fflush(0);
|
||||
snprintf(tmp, sizeof tmp, "%s%civl -V -C%s -C%s", pbase, sep,
|
||||
iconfig_path, iconfig_common_path);
|
||||
rc = system(tmp);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "Unable to get version from \"%s\"\n", tmp);
|
||||
}
|
||||
|
||||
if ( ! getenv("IVERILOG_ICONFIG")) {
|
||||
remove(iconfig_path);
|
||||
free(iconfig_path);
|
||||
remove(defines_path);
|
||||
free(defines_path);
|
||||
remove(compiled_defines_path);
|
||||
free(compiled_defines_path);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void build_preprocess_command(int e_flag)
|
||||
{
|
||||
snprintf(tmp, sizeof tmp, "%s%civlpp %s%s -F%s -f%s -p%s ",
|
||||
pbase,sep, verbose_flag?" -v":"",
|
||||
e_flag?"":" -L", defines_path, source_path,
|
||||
compiled_defines_path);
|
||||
}
|
||||
|
||||
static int t_preprocess_only(void)
|
||||
{
|
||||
int rc;
|
||||
char*cmd;
|
||||
unsigned ncmd;
|
||||
|
||||
build_preprocess_command(1);
|
||||
|
||||
ncmd = strlen(tmp);
|
||||
cmd = malloc(ncmd+1);
|
||||
strcpy(cmd, tmp);
|
||||
|
||||
if (strcmp(opath,"-") != 0) {
|
||||
snprintf(tmp, sizeof tmp, " > %s", opath);
|
||||
cmd = realloc(cmd, ncmd+strlen(tmp)+1);
|
||||
strcpy(cmd+ncmd, tmp);
|
||||
ncmd += strlen(tmp);
|
||||
}
|
||||
|
||||
if (verbose_flag)
|
||||
printf("preprocess: %s\n", cmd);
|
||||
|
||||
rc = system(cmd);
|
||||
remove(source_path);
|
||||
free(source_path);
|
||||
|
||||
if ( ! getenv("IVERILOG_ICONFIG")) {
|
||||
remove(iconfig_path);
|
||||
free(iconfig_path);
|
||||
remove(defines_path);
|
||||
free(defines_path);
|
||||
remove(compiled_defines_path);
|
||||
free(compiled_defines_path);
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
if (WIFEXITED(rc)) {
|
||||
fprintf(stderr, "errors preprocessing Verilog program.\n");
|
||||
return WEXITSTATUS(rc);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Command signaled: %s\n", cmd);
|
||||
free(cmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the default target type. It looks up the bits that are
|
||||
* needed to run the command from the configuration file (which is
|
||||
* already parsed for us) so we can handle must of the generic cases.
|
||||
*/
|
||||
static int t_compile()
|
||||
static int t_default(char*cmd, unsigned ncmd)
|
||||
{
|
||||
unsigned rc;
|
||||
|
||||
/* Start by building the preprocess command line. */
|
||||
build_preprocess_command(0);
|
||||
|
||||
size_t ncmd = strlen(tmp);
|
||||
char*cmd = malloc(ncmd + 1);
|
||||
strcpy(cmd, tmp);
|
||||
|
||||
#ifdef __MINGW32__
|
||||
unsigned ncmd_start = ncmd;
|
||||
#else
|
||||
int rtn;
|
||||
#endif
|
||||
|
||||
/* Build the ivl command and pipe it to the preprocessor. */
|
||||
snprintf(tmp, sizeof tmp, " | %s/ivl", base);
|
||||
rc = strlen(tmp);
|
||||
cmd = realloc(cmd, ncmd+rc+1);
|
||||
@@ -426,33 +323,28 @@ static int t_compile()
|
||||
rc = system(cmd);
|
||||
if ( ! getenv("IVERILOG_ICONFIG")) {
|
||||
remove(source_path);
|
||||
free(source_path);
|
||||
remove(iconfig_path);
|
||||
free(iconfig_path);
|
||||
remove(defines_path);
|
||||
free(defines_path);
|
||||
remove(compiled_defines_path);
|
||||
free(compiled_defines_path);
|
||||
}
|
||||
#ifdef __MINGW32__ /* MinGW just returns the exit status, so return it! */
|
||||
free(cmd);
|
||||
return rc;
|
||||
#else
|
||||
rtn = 0;
|
||||
|
||||
if (rc != 0) {
|
||||
if (rc == 127) {
|
||||
fprintf(stderr, "Failed to execute: %s\n", cmd);
|
||||
rtn = 1;
|
||||
} else if (WIFEXITED(rc)) {
|
||||
rtn = WEXITSTATUS(rc);
|
||||
} else {
|
||||
fprintf(stderr, "Command signaled: %s\n", cmd);
|
||||
rtn = -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (WIFEXITED(rc))
|
||||
return WEXITSTATUS(rc);
|
||||
|
||||
fprintf(stderr, "Command signaled: %s\n", cmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(cmd);
|
||||
return rtn;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -613,7 +505,7 @@ int process_generation(const char*name)
|
||||
" 2005 -- IEEE1364-2005\n"
|
||||
"Other generation flags:\n"
|
||||
" specify | no-specify\n"
|
||||
" verilog-ams | no-verilog-ams\n"
|
||||
" verilog-ams | no-verinlog-ams\n"
|
||||
" std-include | no-std-include\n"
|
||||
" xtypes | no-xtypes\n"
|
||||
" icarus-misc | no-icarus-misc\n"
|
||||
@@ -630,7 +522,7 @@ int process_generation(const char*name)
|
||||
void add_sft_file(const char *module)
|
||||
{
|
||||
char *file;
|
||||
|
||||
|
||||
file = (char *) malloc(strlen(base)+1+strlen(module)+4+1);
|
||||
sprintf(file, "%s%c%s.sft", base, sep, module);
|
||||
if (access(file, R_OK) == 0)
|
||||
@@ -640,6 +532,8 @@ void add_sft_file(const char *module)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char*cmd;
|
||||
unsigned ncmd;
|
||||
int e_flag = 0;
|
||||
int version_flag = 0;
|
||||
int opt, idx, rc;
|
||||
@@ -759,7 +653,7 @@ int main(int argc, char **argv)
|
||||
case 'c':
|
||||
case 'f':
|
||||
add_cmd_file(optarg);
|
||||
break;
|
||||
break;
|
||||
case 'D':
|
||||
process_define(optarg);
|
||||
break;
|
||||
@@ -778,9 +672,9 @@ int main(int argc, char **argv)
|
||||
if (rc != 0)
|
||||
return -1;
|
||||
break;
|
||||
case 'h':
|
||||
fprintf(stderr, "%s\n", HELP);
|
||||
return 1;
|
||||
case 'h':
|
||||
fprintf(stderr, "%s\n", HELP);
|
||||
return 1;
|
||||
|
||||
case 'I':
|
||||
process_include_dir(optarg);
|
||||
@@ -851,8 +745,11 @@ int main(int argc, char **argv)
|
||||
|
||||
if (version_flag || verbose_flag) {
|
||||
printf("Icarus Verilog version " VERSION " (" VERSION_TAG ")\n\n");
|
||||
printf("Copyright 1998-2008 Stephen Williams\n\n");
|
||||
printf("Copyright 1998-2008 Stephen Williams\n");
|
||||
puts(NOTICE);
|
||||
|
||||
if (version_flag)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make a common conf file path to reflect the target. */
|
||||
@@ -867,18 +764,9 @@ int main(int argc, char **argv)
|
||||
how to handle them. */
|
||||
fprintf(iconfig_file, "sys_func:%s%csystem.sft\n", base, sep);
|
||||
|
||||
/* If verilog-2005 is enabled or icarus-misc or verilog-ams,
|
||||
* then include the v2005_math library. */
|
||||
if (strcmp(generation, "2005") == 0 ||
|
||||
strcmp(gen_icarus, "icarus-misc") == 0 ||
|
||||
strcmp(gen_verilog_ams, "verilog-ams") == 0) {
|
||||
fprintf(iconfig_file, "sys_func:%s%cv2005_math.sft\n", base, sep);
|
||||
fprintf(iconfig_file, "module:v2005_math\n");
|
||||
}
|
||||
/* If verilog-ams or icarus_misc is enabled, then include the
|
||||
* va_math module as well. */
|
||||
if (strcmp(gen_verilog_ams,"verilog-ams") == 0 ||
|
||||
strcmp(gen_icarus, "icarus-misc") == 0) {
|
||||
/* If verilog-ams is enabled, then include the va_math module
|
||||
as well. */
|
||||
if (strcmp(gen_verilog_ams,"verilog-ams") == 0) {
|
||||
fprintf(iconfig_file, "sys_func:%s%cva_math.sft\n", base, sep);
|
||||
fprintf(iconfig_file, "module:va_math\n");
|
||||
}
|
||||
@@ -935,11 +823,60 @@ int main(int argc, char **argv)
|
||||
fclose(defines_file);
|
||||
defines_file = 0;
|
||||
|
||||
if (source_count == 0 && !version_flag) {
|
||||
if (source_count == 0) {
|
||||
fprintf(stderr, "%s: no source files.\n\n%s\n", argv[0], HELP);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Start building the preprocess command line. */
|
||||
|
||||
sprintf(tmp, "%s%civlpp %s%s -F%s -f%s -p%s ", pbase,sep,
|
||||
verbose_flag?" -v":"",
|
||||
e_flag?"":" -L", defines_path, source_path,
|
||||
compiled_defines_path);
|
||||
|
||||
ncmd = strlen(tmp);
|
||||
cmd = malloc(ncmd + 1);
|
||||
strcpy(cmd, tmp);
|
||||
|
||||
/* If the -E flag was given on the command line, then all we
|
||||
do is run the preprocessor and put the output where the
|
||||
user wants it. */
|
||||
if (e_flag) {
|
||||
int rc;
|
||||
if (strcmp(opath,"-") != 0) {
|
||||
sprintf(tmp, " > %s", opath);
|
||||
cmd = realloc(cmd, ncmd+strlen(tmp)+1);
|
||||
strcpy(cmd+ncmd, tmp);
|
||||
ncmd += strlen(tmp);
|
||||
}
|
||||
|
||||
if (verbose_flag)
|
||||
printf("preprocess: %s\n", cmd);
|
||||
|
||||
rc = system(cmd);
|
||||
remove(source_path);
|
||||
fclose(iconfig_file);
|
||||
if ( ! getenv("IVERILOG_ICONFIG")) {
|
||||
remove(iconfig_path);
|
||||
remove(defines_path);
|
||||
remove(compiled_defines_path);
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
if (WIFEXITED(rc)) {
|
||||
fprintf(stderr, "errors preprocessing Verilog program.\n");
|
||||
return WEXITSTATUS(rc);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Command signaled: %s\n", cmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(iconfig_file, "iwidth:%u\n", integer_width);
|
||||
|
||||
/* Write the preprocessor command needed to preprocess a
|
||||
@@ -951,16 +888,7 @@ int main(int argc, char **argv)
|
||||
/* Done writing to the iconfig file. Close it now. */
|
||||
fclose(iconfig_file);
|
||||
|
||||
/* If we're only here for the version output, then we're done. */
|
||||
if (version_flag)
|
||||
return t_version_only();
|
||||
return t_default(cmd, ncmd);
|
||||
|
||||
/* If the -E flag was given on the command line, then all we
|
||||
do is run the preprocessor and put the output where the
|
||||
user wants it. */
|
||||
if (e_flag)
|
||||
return t_preprocess_only();
|
||||
|
||||
/* Otherwise, this is a full compile. */
|
||||
return t_compile();
|
||||
return 0;
|
||||
}
|
||||
|
||||
+2
-20
@@ -21,16 +21,6 @@
|
||||
|
||||
# include "netlist.h"
|
||||
# include <cassert>
|
||||
# include <stdlib.h>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
NetEAccess* NetEAccess::dup_expr() const
|
||||
{
|
||||
NetEAccess*tmp = new NetEAccess(branch_, nature_);
|
||||
ivl_assert(*this, tmp);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetEBComp* NetEBComp::dup_expr() const
|
||||
{
|
||||
@@ -94,8 +84,8 @@ NetESFunc* NetESFunc::dup_expr() const
|
||||
|
||||
tmp->cast_signed(has_sign());
|
||||
for (unsigned idx = 0 ; idx < nparms() ; idx += 1) {
|
||||
assert(parm(idx));
|
||||
tmp->parm(idx, parm(idx)->dup_expr());
|
||||
assert(tmp->parm(idx));
|
||||
tmp->parm(idx, tmp->parm(idx)->dup_expr());
|
||||
}
|
||||
|
||||
tmp->set_line(*this);
|
||||
@@ -138,14 +128,6 @@ NetEUFunc* NetEUFunc::dup_expr() const
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetEUBits* NetEUBits::dup_expr() const
|
||||
{
|
||||
NetEUBits*tmp = new NetEUBits(op_, expr_->dup_expr());
|
||||
assert(tmp);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetEUnary* NetEUnary::dup_expr() const
|
||||
{
|
||||
NetEUnary*tmp = new NetEUnary(op_, expr_->dup_expr());
|
||||
|
||||
+49
-1
@@ -16,6 +16,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_anet.cc,v 1.13 2007/03/22 16:08:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
@@ -112,7 +115,7 @@ NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
symbol_search(this, des, scope, path_, sig, mem, par, eve);
|
||||
symbol_search(des, scope, path_, sig, mem, par, eve);
|
||||
|
||||
|
||||
if (mem != 0) {
|
||||
@@ -164,3 +167,48 @@ NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
|
||||
return sig;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: elab_anet.cc,v $
|
||||
* Revision 1.13 2007/03/22 16:08:14 steve
|
||||
* Spelling fixes from Larry
|
||||
*
|
||||
* Revision 1.12 2006/05/01 20:47:58 steve
|
||||
* More explicit datatype setup.
|
||||
*
|
||||
* Revision 1.11 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.10 2004/10/04 01:10:52 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
* Revision 1.9 2003/09/19 03:50:12 steve
|
||||
* Remove find_memory method from Design class.
|
||||
*
|
||||
* Revision 1.8 2003/06/21 01:21:43 steve
|
||||
* Harmless fixup of warnings.
|
||||
*
|
||||
* Revision 1.7 2003/03/06 00:28:41 steve
|
||||
* All NetObj objects have lex_string base names.
|
||||
*
|
||||
* Revision 1.6 2003/01/27 05:09:17 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.5 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.4 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
*
|
||||
* Revision 1.3 2001/07/25 03:10:48 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.2 2001/01/06 02:29:36 steve
|
||||
* Support arrays of integers.
|
||||
*
|
||||
* Revision 1.1 2000/12/06 06:31:09 steve
|
||||
* Check lvalue of procedural continuous assign (PR#29)
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
+339
-1440
File diff suppressed because it is too large
Load Diff
+103
-72
@@ -152,7 +152,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
symbol_search(this, des, scope, path_, reg, par, eve);
|
||||
symbol_search(des, scope, path_, reg, par, eve);
|
||||
if (reg == 0) {
|
||||
cerr << get_fileline() << ": error: Could not find variable ``"
|
||||
<< path_ << "'' in ``" << scope_path(scope) <<
|
||||
@@ -208,18 +208,101 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
return 0;
|
||||
}
|
||||
|
||||
long msb, lsb;
|
||||
NetExpr*mux;
|
||||
|
||||
if (use_sel == index_component_t::SEL_BIT) {
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
elaborate_lval_net_bit_(des, scope, lv);
|
||||
return lv;
|
||||
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
ivl_assert(*this, index_tail.msb != 0);
|
||||
ivl_assert(*this, index_tail.lsb == 0);
|
||||
|
||||
/* If there is only a single select expression, it is a
|
||||
bit select. Evaluate the constant value and treat it
|
||||
as a part select with a bit width of 1. If the
|
||||
expression it not constant, then return the
|
||||
expression as a mux. */
|
||||
|
||||
NetExpr*index_expr = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
|
||||
if (NetEConst*index_con = dynamic_cast<NetEConst*> (index_expr)) {
|
||||
msb = index_con->value().as_long();
|
||||
lsb = index_con->value().as_long();
|
||||
mux = 0;
|
||||
|
||||
} else {
|
||||
msb = 0;
|
||||
lsb = 0;
|
||||
mux = index_expr;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* No select expressions, so presume a part select the
|
||||
width of the register. */
|
||||
|
||||
msb = reg->msb();
|
||||
lsb = reg->lsb();
|
||||
mux = 0;
|
||||
}
|
||||
|
||||
ivl_assert(*this, use_sel == index_component_t::SEL_NONE);
|
||||
|
||||
/* No select expressions. */
|
||||
NetAssign_*lv;
|
||||
if (mux) {
|
||||
|
||||
/* If there is a non-constant bit select, make a
|
||||
NetAssign_ to the target reg and attach a
|
||||
bmux to select the target bit. */
|
||||
lv = new NetAssign_(reg);
|
||||
|
||||
/* Correct the mux for the range of the vector. */
|
||||
if (reg->msb() < reg->lsb())
|
||||
mux = make_sub_expr(reg->lsb(), mux);
|
||||
else if (reg->lsb() != 0)
|
||||
mux = make_add_expr(mux, - reg->lsb());
|
||||
|
||||
lv->set_part(mux, 1);
|
||||
|
||||
} else if (msb == reg->msb() && lsb == reg->lsb()) {
|
||||
|
||||
/* No bit select, and part select covers the entire
|
||||
vector. Simplest case. */
|
||||
lv = new NetAssign_(reg);
|
||||
|
||||
} else {
|
||||
|
||||
/* If the bit/part select is constant, then make the
|
||||
NetAssign_ only as wide as it needs to be and connect
|
||||
only to the selected bits of the reg. */
|
||||
unsigned loff = reg->sb_to_idx(lsb);
|
||||
unsigned moff = reg->sb_to_idx(msb);
|
||||
unsigned wid = moff - loff + 1;
|
||||
|
||||
if (moff < loff) {
|
||||
cerr << get_fileline() << ": error: part select "
|
||||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is reversed." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If the part select extends beyond the extreme of the
|
||||
variable, then report an error. Note that loff is
|
||||
converted to normalized form so is relative the
|
||||
variable pins. */
|
||||
|
||||
if ((wid + loff) > reg->vector_width()) {
|
||||
cerr << get_fileline() << ": error: bit/part select "
|
||||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is out of range." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
lv = new NetAssign_(reg);
|
||||
lv->set_part(new NetEConst(verinum(loff)), wid);
|
||||
}
|
||||
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
|
||||
return lv;
|
||||
}
|
||||
@@ -291,67 +374,10 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
|
||||
return lv;
|
||||
}
|
||||
|
||||
bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
||||
NetScope*scope,
|
||||
NetAssign_*lv) const
|
||||
{
|
||||
const name_component_t&name_tail = path_.back();
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
ivl_assert(*this, index_tail.msb != 0);
|
||||
ivl_assert(*this, index_tail.lsb == 0);
|
||||
|
||||
NetNet*reg = lv->sig();
|
||||
|
||||
// Bit selects have a single select expression. Evaluate the
|
||||
// constant value and treat it as a part select with a bit
|
||||
// width of 1.
|
||||
NetExpr*mux = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
long lsb = 0;
|
||||
|
||||
if (NetEConst*index_con = dynamic_cast<NetEConst*> (mux)) {
|
||||
lsb = index_con->value().as_long();
|
||||
mux = 0;
|
||||
}
|
||||
|
||||
if (mux) {
|
||||
// Non-constant bit mux. Correct the mux for the range
|
||||
// of the vector, then set the l-value part select expression.
|
||||
if (reg->msb() < reg->lsb())
|
||||
mux = make_sub_expr(reg->lsb(), mux);
|
||||
else if (reg->lsb() != 0)
|
||||
mux = make_add_expr(mux, - reg->lsb());
|
||||
|
||||
lv->set_part(mux, 1);
|
||||
|
||||
} else if (lsb == reg->msb() && lsb == reg->lsb()) {
|
||||
// Constant bit mux that happens to select the only bit
|
||||
// of the l-value. Don't bother with any select at all.
|
||||
|
||||
} else {
|
||||
// Constant bit select that does something useful.
|
||||
long loff = reg->sb_to_idx(lsb);
|
||||
|
||||
if (loff < 0 || loff >= (long)reg->vector_width()) {
|
||||
cerr << get_fileline() << ": error: bit select "
|
||||
<< reg->name() << "[" <<lsb<<"]"
|
||||
<< " is out of range." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
lv->set_part(new NetEConst(verinum(loff)), 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PEIdent::elaborate_lval_net_part_(Design*des,
|
||||
NetScope*scope,
|
||||
NetAssign_*lv) const
|
||||
{
|
||||
// The range expressions of a part select must be
|
||||
// constant. The calculate_parts_ function calculates the
|
||||
// values into msb and lsb.
|
||||
long msb, lsb;
|
||||
bool flag = calculate_parts_(des, scope, msb, lsb);
|
||||
if (!flag)
|
||||
@@ -362,14 +388,17 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
|
||||
|
||||
if (msb == reg->msb() && lsb == reg->lsb()) {
|
||||
|
||||
/* Part select covers the entire vector. Simplest case. */
|
||||
/* No bit select, and part select covers the entire
|
||||
vector. Simplest case. */
|
||||
|
||||
} else {
|
||||
|
||||
/* Get the canonical offsets into the vector. */
|
||||
long loff = reg->sb_to_idx(lsb);
|
||||
long moff = reg->sb_to_idx(msb);
|
||||
long wid = moff - loff + 1;
|
||||
/* If the bit/part select is constant, then make the
|
||||
NetAssign_ only as wide as it needs to be and connect
|
||||
only to the selected bits of the reg. */
|
||||
unsigned loff = reg->sb_to_idx(lsb);
|
||||
unsigned moff = reg->sb_to_idx(msb);
|
||||
unsigned wid = moff - loff + 1;
|
||||
|
||||
if (moff < loff) {
|
||||
cerr << get_fileline() << ": error: part select "
|
||||
@@ -379,15 +408,17 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If the part select extends beyond the extremes of the
|
||||
/* If the part select extends beyond the extreme of the
|
||||
variable, then report an error. Note that loff is
|
||||
converted to normalized form so is relative the
|
||||
variable pins. */
|
||||
|
||||
if (loff < 0 || moff >= (signed)reg->vector_width()) {
|
||||
cerr << get_fileline() << ": warning: Part select "
|
||||
if ((wid + loff) > reg->vector_width()) {
|
||||
cerr << get_fileline() << ": error: bit/part select "
|
||||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is out of range." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
lv->set_part(new NetEConst(verinum(loff)), wid);
|
||||
|
||||
+3097
-52
File diff suppressed because it is too large
Load Diff
+3
-188
@@ -57,66 +57,6 @@ NetExpr*PEBinary::elaborate_pexpr (Design*des, NetScope*scope) const
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr*PEBComp::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetExpr*lp = left_->elaborate_pexpr(des, scope);
|
||||
NetExpr*rp = right_->elaborate_pexpr(des, scope);
|
||||
if ((lp == 0) || (rp == 0)) {
|
||||
delete lp;
|
||||
delete rp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
suppress_binary_operand_sign_if_needed_(lp, rp);
|
||||
|
||||
NetEBComp*tmp = new NetEBComp(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
bool flag = tmp->set_width(1);
|
||||
if (flag == false) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
"expression bit width of comparison != 1." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr*PEBLeftWidth::elaborate_pexpr (Design*des, NetScope*scope) const
|
||||
{
|
||||
NetExpr*lp = left_->elaborate_pexpr(des, scope);
|
||||
NetExpr*rp = right_->elaborate_pexpr(des, scope);
|
||||
if ((lp == 0) || (rp == 0)) {
|
||||
delete lp;
|
||||
delete rp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr*tmp = elaborate_expr_leaf(des, lp, rp, -2);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr*PEBLogic::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetExpr*lp = left_->elaborate_pexpr(des, scope);
|
||||
NetExpr*rp = right_->elaborate_pexpr(des, scope);
|
||||
if ((lp == 0) || (rp == 0)) {
|
||||
delete lp;
|
||||
delete rp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEBLogic*tmp = new NetEBLogic(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
bool flag = tmp->set_width(1);
|
||||
if (flag == false) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
"expression bit width of comparison != 1." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Event though parameters are not generally sized, parameter
|
||||
* expressions can include concatenation expressions. This requires
|
||||
@@ -192,13 +132,13 @@ NetExpr*PEFNumber::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
*/
|
||||
NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
{
|
||||
pform_name_t oldpath = path_;
|
||||
pform_name_t path = path_;
|
||||
name_component_t name_tail = path_.back();
|
||||
oldpath.pop_back();
|
||||
path.pop_back();
|
||||
|
||||
NetScope*pscope = scope;
|
||||
if (path_.size() > 0) {
|
||||
list<hname_t> tmp = eval_scope_path(des, scope, oldpath);
|
||||
list<hname_t> tmp = eval_scope_path(des, scope, path);
|
||||
pscope = des->find_scope(scope, tmp);
|
||||
}
|
||||
|
||||
@@ -327,128 +267,3 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr* PECallFunction::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
{
|
||||
/* Only $clog2 and the builtin mathematical functions can
|
||||
* be a constant system function. */
|
||||
perm_string nm = peek_tail_name(path_);
|
||||
if (nm[0] == '$' && (generation_flag >= GN_VER2005 ||
|
||||
gn_icarus_misc_flag || gn_verilog_ams_flag)) {
|
||||
if (nm == "$clog2" ||
|
||||
nm == "$ln" ||
|
||||
nm == "$log10" ||
|
||||
nm == "$exp" ||
|
||||
nm == "$sqrt" ||
|
||||
nm == "$floor" ||
|
||||
nm == "$ceil" ||
|
||||
nm == "$sin" ||
|
||||
nm == "$cos" ||
|
||||
nm == "$tan" ||
|
||||
nm == "$asin" ||
|
||||
nm == "$acos" ||
|
||||
nm == "$atan" ||
|
||||
nm == "$sinh" ||
|
||||
nm == "$cosh" ||
|
||||
nm == "$tanh" ||
|
||||
nm == "$asinh" ||
|
||||
nm == "$acosh" ||
|
||||
nm == "$atanh") {
|
||||
if (parms_.size() != 1 || parms_[0] == 0) {
|
||||
cerr << get_fileline() << ": error: " << nm
|
||||
<< " takes a single argument." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
NetExpr*arg = parms_[0]->elaborate_pexpr(des, scope);
|
||||
if (arg == 0) return 0;
|
||||
NetESFunc*rtn;
|
||||
if (nm == "$clog2") {
|
||||
rtn = new NetESFunc(nm, IVL_VT_BOOL, integer_width, 1);
|
||||
} else {
|
||||
rtn = new NetESFunc(nm, IVL_VT_REAL, 1, 1);
|
||||
}
|
||||
rtn->set_line(*this);
|
||||
rtn->cast_signed(true);
|
||||
rtn->parm(0, arg);
|
||||
return rtn;
|
||||
}
|
||||
|
||||
if (nm == "$pow" ||
|
||||
nm == "$atan2" ||
|
||||
nm == "$hypot") {
|
||||
if (parms_.size() != 2 || parms_[0] == 0 || parms_[1] == 0) {
|
||||
cerr << get_fileline() << ": error: " << nm
|
||||
<< " takes two arguments." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
NetExpr*arg0 = parms_[0]->elaborate_pexpr(des, scope);
|
||||
NetExpr*arg1 = parms_[1]->elaborate_pexpr(des, scope);
|
||||
if (arg0 == 0 || arg1 == 0) return 0;
|
||||
NetESFunc*rtn = new NetESFunc(nm, IVL_VT_REAL, 1, 2);
|
||||
rtn->set_line(*this);
|
||||
rtn->cast_signed(true);
|
||||
rtn->parm(0, arg0);
|
||||
rtn->parm(1, arg1);
|
||||
return rtn;
|
||||
}
|
||||
|
||||
/* These are only available with verilog-ams or icarus-misc. */
|
||||
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
|
||||
(nm == "$log" || nm == "$abs")) {
|
||||
if (parms_.size() != 1 || parms_[0] == 0) {
|
||||
cerr << get_fileline() << ": error: " << nm
|
||||
<< " takes a single argument." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
NetExpr*arg = parms_[0]->elaborate_pexpr(des, scope);
|
||||
if (arg == 0) return 0;
|
||||
NetESFunc*rtn;
|
||||
if (nm == "$log") {
|
||||
rtn = new NetESFunc(nm, IVL_VT_REAL, 1, 1);
|
||||
} else {
|
||||
/* This can return either a real or an arbitrary
|
||||
* width vector, so set things to fail if this
|
||||
* does not get replaced with a constant during
|
||||
* elaboration. */
|
||||
rtn = new NetESFunc(nm, IVL_VT_NO_TYPE, 0, 1);
|
||||
}
|
||||
rtn->set_line(*this);
|
||||
rtn->cast_signed(true);
|
||||
rtn->parm(0, arg);
|
||||
return rtn;
|
||||
}
|
||||
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
|
||||
(nm == "$min" || nm == "$max")) {
|
||||
if (parms_.size() != 2 || parms_[0] == 0 || parms_[1] == 0) {
|
||||
cerr << get_fileline() << ": error: " << nm
|
||||
<< " takes two arguments." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
NetExpr*arg0 = parms_[0]->elaborate_pexpr(des, scope);
|
||||
NetExpr*arg1 = parms_[1]->elaborate_pexpr(des, scope);
|
||||
if (arg0 == 0 || arg1 == 0) return 0;
|
||||
/* See $log above for why this has no type or width. */
|
||||
NetESFunc*rtn = new NetESFunc(nm, IVL_VT_NO_TYPE, 0, 2);
|
||||
rtn->set_line(*this);
|
||||
rtn->cast_signed(true);
|
||||
rtn->parm(0, arg0);
|
||||
rtn->parm(1, arg1);
|
||||
return rtn;
|
||||
}
|
||||
|
||||
cerr << get_fileline() << ": error: this is not a constant "
|
||||
"system function (" << *this << ")." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Constant user function code goes here. */
|
||||
cerr << get_fileline() << ": sorry: constant user functions are not "
|
||||
"currently supported." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
+170
-516
@@ -40,55 +40,20 @@
|
||||
# include "PTask.h"
|
||||
# include "PWire.h"
|
||||
# include "Statement.h"
|
||||
# include "AStatement.h"
|
||||
# include "netlist.h"
|
||||
# include "util.h"
|
||||
# include <typeinfo>
|
||||
# include <assert.h>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
typedef map<perm_string,LexicalScope::param_expr_t>::const_iterator mparm_it_t;
|
||||
|
||||
static void collect_scope_parameters_(NetScope*scope,
|
||||
const map<perm_string,LexicalScope::param_expr_t>¶meters)
|
||||
{
|
||||
for (mparm_it_t cur = parameters.begin()
|
||||
; cur != parameters.end() ; cur ++) {
|
||||
|
||||
NetEParam*tmp = new NetEParam;
|
||||
tmp->set_line(*((*cur).second.expr));
|
||||
tmp->cast_signed( (*cur).second.signed_flag );
|
||||
|
||||
scope->set_parameter((*cur).first, tmp, (*cur).second.type,
|
||||
0, 0, false, 0, (*cur).second);
|
||||
}
|
||||
}
|
||||
|
||||
static void collect_scope_localparams_(NetScope*scope,
|
||||
const map<perm_string,LexicalScope::param_expr_t>&localparams)
|
||||
{
|
||||
for (mparm_it_t cur = localparams.begin()
|
||||
; cur != localparams.end() ; cur ++) {
|
||||
|
||||
NetEParam*tmp = new NetEParam;
|
||||
tmp->set_line(*((*cur).second.expr));
|
||||
if ((*cur).second.msb)
|
||||
tmp->cast_signed( (*cur).second.signed_flag );
|
||||
|
||||
scope->set_parameter((*cur).first, tmp, (*cur).second.type,
|
||||
0, 0, false, 0, (*cur).second);
|
||||
}
|
||||
}
|
||||
|
||||
static void elaborate_parm_item_(perm_string name,
|
||||
const LexicalScope::param_expr_t&cur,
|
||||
Design*des, NetScope*scope)
|
||||
void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur,
|
||||
Design*des, NetScope*scope)
|
||||
{
|
||||
PExpr*ex = cur.expr;
|
||||
assert(ex);
|
||||
|
||||
NetExpr*val = ex->elaborate_pexpr(des, scope);
|
||||
|
||||
if (val == 0) return;
|
||||
NetExpr*msb = 0;
|
||||
NetExpr*lsb = 0;
|
||||
bool signed_flag = cur.signed_flag;
|
||||
@@ -106,15 +71,27 @@ static void elaborate_parm_item_(perm_string name,
|
||||
assert(lsb);
|
||||
}
|
||||
|
||||
if (signed_flag) {
|
||||
/* If explicitly signed, then say so. */
|
||||
val->cast_signed(true);
|
||||
} else if (cur.msb) {
|
||||
/* If there is a range, then the signedness comes
|
||||
from the type and not the expression. */
|
||||
val->cast_signed(signed_flag);
|
||||
} else {
|
||||
/* otherwise, let the expression describe
|
||||
itself. */
|
||||
signed_flag = val->has_sign();
|
||||
}
|
||||
|
||||
NetScope::range_t*range_list = 0;
|
||||
for (LexicalScope::range_t*range = cur.range ; range ; range = range->next) {
|
||||
for (Module::range_t*range = cur.range ; range ; range = range->next) {
|
||||
NetScope::range_t*tmp = new NetScope::range_t;
|
||||
tmp->exclude_flag = range->exclude_flag;
|
||||
tmp->low_open_flag = range->low_open_flag;
|
||||
tmp->high_open_flag = range->high_open_flag;
|
||||
|
||||
if (range->low_expr) {
|
||||
probe_expr_width(des, scope, range->low_expr);
|
||||
tmp->low_expr = elab_and_eval(des, scope, range->low_expr, -1);
|
||||
ivl_assert(*range->low_expr, tmp->low_expr);
|
||||
} else {
|
||||
@@ -131,7 +108,6 @@ static void elaborate_parm_item_(perm_string name,
|
||||
tmp->high_expr = tmp->low_expr;
|
||||
|
||||
} else if (range->high_expr) {
|
||||
probe_expr_width(des, scope, range->high_expr);
|
||||
tmp->high_expr = elab_and_eval(des, scope, range->high_expr, -1);
|
||||
ivl_assert(*range->high_expr, tmp->high_expr);
|
||||
} else {
|
||||
@@ -142,186 +118,13 @@ static void elaborate_parm_item_(perm_string name,
|
||||
range_list = tmp;
|
||||
}
|
||||
|
||||
/* Set the parameter expression to 0 if the evaluation failed. */
|
||||
if (val == 0) {
|
||||
val = scope->set_parameter(name, val, cur.type, msb, lsb,
|
||||
signed_flag, range_list, cur);
|
||||
delete val;
|
||||
return;
|
||||
}
|
||||
|
||||
if (signed_flag) {
|
||||
/* If explicitly signed, then say so. */
|
||||
val->cast_signed(true);
|
||||
} else if (cur.msb) {
|
||||
/* If there is a range, then the signedness comes
|
||||
from the type and not the expression. */
|
||||
val->cast_signed(signed_flag);
|
||||
} else {
|
||||
/* otherwise, let the expression describe
|
||||
itself. */
|
||||
signed_flag = val->has_sign();
|
||||
}
|
||||
|
||||
val = scope->set_parameter(name, val, cur.type, msb, lsb, signed_flag,
|
||||
range_list, cur);
|
||||
val = scope->set_parameter(name, val, cur.type, msb, lsb, signed_flag, range_list, cur);
|
||||
assert(val);
|
||||
delete val;
|
||||
}
|
||||
|
||||
static void elaborate_scope_parameters_(Design*des, NetScope*scope,
|
||||
const map<perm_string,LexicalScope::param_expr_t>¶meters)
|
||||
{
|
||||
for (mparm_it_t cur = parameters.begin()
|
||||
; cur != parameters.end() ; cur ++) {
|
||||
|
||||
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
|
||||
}
|
||||
}
|
||||
|
||||
static void elaborate_scope_localparams_(Design*des, NetScope*scope,
|
||||
const map<perm_string,LexicalScope::param_expr_t>&localparams)
|
||||
{
|
||||
for (mparm_it_t cur = localparams.begin()
|
||||
; cur != localparams.end() ; cur ++) {
|
||||
|
||||
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
|
||||
}
|
||||
}
|
||||
|
||||
static void replace_scope_parameters_(NetScope*scope, const LineInfo&loc,
|
||||
const Module::replace_t&replacements)
|
||||
{
|
||||
for (Module::replace_t::const_iterator cur = replacements.begin()
|
||||
; cur != replacements.end() ; cur ++) {
|
||||
|
||||
NetExpr*val = (*cur).second;
|
||||
if (val == 0) {
|
||||
cerr << loc.get_fileline() << ": internal error: "
|
||||
<< "Missing expression in parameter replacement for "
|
||||
<< (*cur).first;
|
||||
}
|
||||
assert(val);
|
||||
if (debug_scopes) {
|
||||
cerr << loc.get_fileline() << ": debug: "
|
||||
<< "Replace " << (*cur).first
|
||||
<< " with expression " << *val
|
||||
<< " from " << val->get_fileline() << "." << endl;
|
||||
cerr << loc.get_fileline() << ": : "
|
||||
<< "Type=" << val->expr_type() << endl;
|
||||
}
|
||||
bool flag = scope->replace_parameter((*cur).first, val);
|
||||
if (! flag) {
|
||||
cerr << val->get_fileline() << ": warning: parameter "
|
||||
<< (*cur).first << " not found in "
|
||||
<< scope_path(scope) << "." << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void elaborate_scope_events_(Design*des, NetScope*scope,
|
||||
const map<perm_string,PEvent*>&events)
|
||||
{
|
||||
for (map<perm_string,PEvent*>::const_iterator et = events.begin()
|
||||
; et != events.end() ; et ++ ) {
|
||||
|
||||
(*et).second->elaborate_scope(des, scope);
|
||||
}
|
||||
}
|
||||
|
||||
static void elaborate_scope_tasks(Design*des, NetScope*scope,
|
||||
const LineInfo&loc,
|
||||
const map<perm_string,PTask*>&tasks)
|
||||
{
|
||||
typedef map<perm_string,PTask*>::const_iterator tasks_it_t;
|
||||
|
||||
for (tasks_it_t cur = tasks.begin()
|
||||
; cur != tasks.end() ; cur ++ ) {
|
||||
|
||||
hname_t use_name( (*cur).first );
|
||||
if (scope->child(use_name)) {
|
||||
cerr << loc.get_fileline() << ": error: task/scope name "
|
||||
<< use_name << " already used in this context."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
NetScope*task_scope = new NetScope(scope, use_name,
|
||||
NetScope::TASK);
|
||||
task_scope->is_auto((*cur).second->is_auto());
|
||||
task_scope->set_line((*cur).second);
|
||||
|
||||
if (debug_scopes)
|
||||
cerr << cur->second->get_fileline() << ": debug: "
|
||||
<< "Elaborate task scope " << scope_path(task_scope) << endl;
|
||||
(*cur).second->elaborate_scope(des, task_scope);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void elaborate_scope_funcs(Design*des, NetScope*scope,
|
||||
const LineInfo&loc,
|
||||
const map<perm_string,PFunction*>&funcs)
|
||||
{
|
||||
typedef map<perm_string,PFunction*>::const_iterator funcs_it_t;
|
||||
|
||||
for (funcs_it_t cur = funcs.begin()
|
||||
; cur != funcs.end() ; cur ++ ) {
|
||||
|
||||
hname_t use_name( (*cur).first );
|
||||
if (scope->child(use_name)) {
|
||||
cerr << loc.get_fileline() << ": error: function/scope name "
|
||||
<< use_name << " already used in this context."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
NetScope*func_scope = new NetScope(scope, use_name,
|
||||
NetScope::FUNC);
|
||||
func_scope->is_auto((*cur).second->is_auto());
|
||||
func_scope->set_line((*cur).second);
|
||||
|
||||
if (debug_scopes)
|
||||
cerr << cur->second->get_fileline() << ": debug: "
|
||||
<< "Elaborate function scope " << scope_path(func_scope) << endl;
|
||||
(*cur).second->elaborate_scope(des, func_scope);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class generate_schemes_work_item_t : public elaborator_work_item_t {
|
||||
public:
|
||||
generate_schemes_work_item_t(Design*des__, NetScope*scope, Module*mod)
|
||||
: elaborator_work_item_t(des__), scope_(scope), mod_(mod)
|
||||
{ }
|
||||
|
||||
void elaborate_runrun()
|
||||
{
|
||||
if (debug_scopes)
|
||||
cerr << mod_->get_fileline() << ": debug: "
|
||||
<< "Processing generate schemes for "
|
||||
<< scope_path(scope_) << endl;
|
||||
|
||||
// Generate schemes can create new scopes in the form of
|
||||
// generated code. Scan the generate schemes, and *generate*
|
||||
// new scopes, which is slightly different from simple
|
||||
// elaboration.
|
||||
typedef list<PGenerate*>::const_iterator generate_it_t;
|
||||
for (generate_it_t cur = mod_->generate_schemes.begin()
|
||||
; cur != mod_->generate_schemes.end() ; cur ++ ) {
|
||||
(*cur) -> generate_scope(des, scope_);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// The scope_ is the scope that contains the generate scheme
|
||||
// we are to work on. the mod_ is the Module definition for
|
||||
// that scope, and contains the parsed generate schemes.
|
||||
NetScope*scope_;
|
||||
Module*mod_;
|
||||
};
|
||||
|
||||
bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
const replace_t&replacements)
|
||||
const replace_t&replacements) const
|
||||
{
|
||||
if (debug_scopes) {
|
||||
cerr << get_fileline() << ": debug: Elaborate scope "
|
||||
@@ -339,25 +142,81 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
// the pform and just place a NetEParam placeholder in the
|
||||
// place of the elaborated expression.
|
||||
|
||||
// Scan the parameters in the module, and create stub parameter
|
||||
// entries in the scope for the parameter names.
|
||||
typedef map<perm_string,param_expr_t>::const_iterator mparm_it_t;
|
||||
typedef map<pform_name_t,PExpr*>::const_iterator pform_parm_it_t;
|
||||
|
||||
collect_scope_parameters_(scope, parameters);
|
||||
|
||||
collect_scope_localparams_(scope, localparams);
|
||||
// This loop scans the parameters in the module, and creates
|
||||
// stub parameter entries in the scope for the parameter name.
|
||||
|
||||
for (mparm_it_t cur = parameters.begin()
|
||||
; cur != parameters.end() ; cur ++) {
|
||||
|
||||
NetEParam*tmp = new NetEParam;
|
||||
tmp->set_line(*((*cur).second.expr));
|
||||
tmp->cast_signed( (*cur).second.signed_flag );
|
||||
|
||||
scope->set_parameter((*cur).first, tmp, (*cur).second.type,
|
||||
0, 0, false, 0, (*cur).second);
|
||||
}
|
||||
|
||||
for (mparm_it_t cur = localparams.begin()
|
||||
; cur != localparams.end() ; cur ++) {
|
||||
|
||||
NetEParam*tmp = new NetEParam;
|
||||
tmp->set_line(*((*cur).second.expr));
|
||||
if ((*cur).second.msb)
|
||||
tmp->cast_signed( (*cur).second.signed_flag );
|
||||
|
||||
scope->set_parameter((*cur).first, tmp, (*cur).second.type,
|
||||
0, 0, false, 0, (*cur).second);
|
||||
}
|
||||
|
||||
|
||||
// Now scan the parameters again, this time elaborating them
|
||||
// for use as parameter values. This is after the previous
|
||||
// scan so that local parameter names can be used in the
|
||||
// r-value expressions.
|
||||
|
||||
elaborate_scope_parameters_(des, scope, parameters);
|
||||
for (mparm_it_t cur = parameters.begin()
|
||||
; cur != parameters.end() ; cur ++) {
|
||||
|
||||
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
|
||||
}
|
||||
|
||||
/* run parameter replacements that were collected from the
|
||||
containing scope and meant for me. */
|
||||
replace_scope_parameters_(scope, *this, replacements);
|
||||
for (replace_t::const_iterator cur = replacements.begin()
|
||||
; cur != replacements.end() ; cur ++) {
|
||||
|
||||
elaborate_scope_localparams_(des, scope, localparams);
|
||||
NetExpr*val = (*cur).second;
|
||||
if (val == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Missing expression in parameter replacement for "
|
||||
<< (*cur).first;
|
||||
}
|
||||
assert(val);
|
||||
if (debug_scopes) {
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Replace " << (*cur).first
|
||||
<< " with expression " << *val
|
||||
<< " from " << val->get_fileline() << "." << endl;
|
||||
cerr << get_fileline() << ": : "
|
||||
<< "Type=" << val->expr_type() << endl;
|
||||
}
|
||||
bool flag = scope->replace_parameter((*cur).first, val);
|
||||
if (! flag) {
|
||||
cerr << val->get_fileline() << ": warning: parameter "
|
||||
<< (*cur).first << " not found in "
|
||||
<< scope_path(scope) << "." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
for (mparm_it_t cur = localparams.begin()
|
||||
; cur != localparams.end() ; cur ++) {
|
||||
|
||||
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
|
||||
}
|
||||
|
||||
// Run through the defparams for this module, elaborate the
|
||||
// expressions in this context and save the result is a table
|
||||
@@ -369,17 +228,15 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
// here because the parameter receiving the assignment may be
|
||||
// in a scope not discovered by this pass.
|
||||
|
||||
typedef list<Module::named_expr_t>::const_iterator defparms_iter_t;
|
||||
for (defparms_iter_t cur = defparms.begin()
|
||||
; cur != defparms.end() ; cur ++) {
|
||||
for (pform_parm_it_t cur = defparms.begin()
|
||||
; cur != defparms.end() ; cur ++ ) {
|
||||
|
||||
PExpr*ex = cur->second;
|
||||
PExpr*ex = (*cur).second;
|
||||
assert(ex);
|
||||
|
||||
NetExpr*val = ex->elaborate_pexpr(des, scope);
|
||||
if (val == 0) continue;
|
||||
|
||||
scope->defparams.push_back(make_pair(cur->first, val));
|
||||
scope->defparams[(*cur).first] = val;
|
||||
}
|
||||
|
||||
// Evaluate the attributes. Evaluate them in the scope of the
|
||||
@@ -392,29 +249,66 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
|
||||
delete[]attr;
|
||||
|
||||
// Generate schemes need to have their scopes elaborated, but
|
||||
// we cannot do that until defparams are run, so push it off
|
||||
// into an elaborate work item.
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Schedule generates within " << scope_path(scope)
|
||||
<< " for elaboration after defparams." << endl;
|
||||
// Generate schemes can create new scopes in the form of
|
||||
// generated code. Scan the generate schemes, and *generate*
|
||||
// new scopes, which is slightly different from simple
|
||||
// elaboration.
|
||||
|
||||
typedef list<PGenerate*>::const_iterator generate_it_t;
|
||||
for (generate_it_t cur = generate_schemes.begin()
|
||||
; cur != generate_schemes.end() ; cur ++ ) {
|
||||
(*cur) -> generate_scope(des, scope);
|
||||
}
|
||||
|
||||
des->elaboration_work_list.push_back(new generate_schemes_work_item_t(des, scope, this));
|
||||
|
||||
// Tasks introduce new scopes, so scan the tasks in this
|
||||
// module. Create a scope for the task and pass that to the
|
||||
// elaborate_scope method of the PTask for detailed
|
||||
// processing.
|
||||
|
||||
elaborate_scope_tasks(des, scope, *this, tasks);
|
||||
typedef map<perm_string,PTask*>::const_iterator tasks_it_t;
|
||||
|
||||
for (tasks_it_t cur = tasks_.begin()
|
||||
; cur != tasks_.end() ; cur ++ ) {
|
||||
|
||||
hname_t use_name( (*cur).first );
|
||||
if (scope->child(use_name)) {
|
||||
cerr << get_fileline() << ": error: task/scope name "
|
||||
<< use_name << " already used in this context."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
NetScope*task_scope = new NetScope(scope, use_name,
|
||||
NetScope::TASK);
|
||||
task_scope->set_line((*cur).second);
|
||||
(*cur).second->elaborate_scope(des, task_scope);
|
||||
}
|
||||
|
||||
|
||||
// Functions are very similar to tasks, at least from the
|
||||
// perspective of scopes. So handle them exactly the same
|
||||
// way.
|
||||
|
||||
elaborate_scope_funcs(des, scope, *this, funcs);
|
||||
typedef map<perm_string,PFunction*>::const_iterator funcs_it_t;
|
||||
|
||||
for (funcs_it_t cur = funcs_.begin()
|
||||
; cur != funcs_.end() ; cur ++ ) {
|
||||
|
||||
hname_t use_name( (*cur).first );
|
||||
if (scope->child(use_name)) {
|
||||
cerr << get_fileline() << ": error: function/scope name "
|
||||
<< use_name << " already used in this context."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
NetScope*func_scope = new NetScope(scope, use_name,
|
||||
NetScope::FUNC);
|
||||
func_scope->set_line((*cur).second);
|
||||
(*cur).second->elaborate_scope(des, func_scope);
|
||||
}
|
||||
|
||||
|
||||
// Gates include modules, which might introduce new scopes, so
|
||||
// scan all of them to create those scopes.
|
||||
@@ -444,7 +338,11 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
// elaboration, so do it now. This allows for normal
|
||||
// elaboration to reference these events.
|
||||
|
||||
elaborate_scope_events_(des, scope, events);
|
||||
for (map<perm_string,PEvent*>::const_iterator et = events.begin()
|
||||
; et != events.end() ; et ++ ) {
|
||||
|
||||
(*et).second->elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
return des->errors == 0;
|
||||
}
|
||||
@@ -463,9 +361,7 @@ bool PGenerate::generate_scope(Design*des, NetScope*container)
|
||||
|
||||
case GS_CASE:
|
||||
return generate_scope_case_(des, container);
|
||||
|
||||
case GS_NBLOCK:
|
||||
return generate_scope_nblock_(des, container);
|
||||
return true;
|
||||
|
||||
case GS_CASE_ITEM:
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
@@ -495,7 +391,6 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
// The initial value for the genvar does not need (nor can it
|
||||
// use) the genvar itself, so we can evaluate this expression
|
||||
// the same way any other parameter value is evaluated.
|
||||
probe_expr_width(des, container, loop_init);
|
||||
NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1);
|
||||
NetEConst*init = dynamic_cast<NetEConst*> (init_ex);
|
||||
if (init == 0) {
|
||||
@@ -525,15 +420,9 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
cerr << get_fileline() << ": debug: genvar init = " << genvar << endl;
|
||||
container->genvar_tmp = loop_index;
|
||||
container->genvar_tmp_val = genvar;
|
||||
probe_expr_width(des, container, loop_test);
|
||||
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
|
||||
NetEConst*test = dynamic_cast<NetEConst*>(test_ex);
|
||||
if (test == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
||||
<< " conditional expression: " << *loop_test << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
assert(test);
|
||||
while (test->value().as_long()) {
|
||||
|
||||
// The actual name of the scope includes the genvar so
|
||||
@@ -578,15 +467,9 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
elaborate_subscope_(des, scope);
|
||||
|
||||
// Calculate the step for the loop variable.
|
||||
probe_expr_width(des, container, loop_step);
|
||||
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1);
|
||||
NetEConst*step = dynamic_cast<NetEConst*>(step_ex);
|
||||
if (step == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
||||
<< " step expression: " << *loop_step << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
assert(step);
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: genvar step from "
|
||||
<< genvar << " to " << step->value().as_long() << endl;
|
||||
@@ -595,7 +478,6 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
container->genvar_tmp_val = genvar;
|
||||
delete step;
|
||||
delete test_ex;
|
||||
probe_expr_width(des, container, loop_test);
|
||||
test_ex = elab_and_eval(des, container, loop_test, -1);
|
||||
test = dynamic_cast<NetEConst*>(test_ex);
|
||||
assert(test);
|
||||
@@ -610,15 +492,9 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
|
||||
bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else_flag)
|
||||
{
|
||||
probe_expr_width(des, container, loop_test);
|
||||
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
|
||||
NetEConst*test = dynamic_cast<NetEConst*> (test_ex);
|
||||
if (test == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
||||
<< " conditional expression: " << *loop_test << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
assert(test);
|
||||
|
||||
// If the condition evaluates as false, then do not create the
|
||||
// scope.
|
||||
@@ -641,26 +517,14 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: Generate condition "
|
||||
<< (else_flag? "(else)" : "(if)")
|
||||
<< " value=" << test->value() << ": Generate scope="
|
||||
<< use_name << endl;
|
||||
|
||||
probe_for_direct_nesting_();
|
||||
if (direct_nested_) {
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: Generate condition "
|
||||
<< (else_flag? "(else)" : "(if)")
|
||||
<< " detected direct nesting." << endl;
|
||||
elaborate_subscope_direct_(des, container);
|
||||
return true;
|
||||
}
|
||||
|
||||
// If this is not directly nested, then generate a scope
|
||||
// for myself. That is what I will pass to the subscope.
|
||||
NetScope*scope = new NetScope(container, use_name, NetScope::GENBLOCK);
|
||||
NetScope*scope = new NetScope(container, use_name,
|
||||
NetScope::GENBLOCK);
|
||||
scope->set_line(get_file(), get_lineno());
|
||||
|
||||
elaborate_subscope_(des, scope);
|
||||
@@ -670,15 +534,12 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
|
||||
|
||||
bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
||||
{
|
||||
probe_expr_width(des, container, loop_test);
|
||||
NetExpr*case_value_ex = elab_and_eval(des, container, loop_test, -1);
|
||||
NetEConst*case_value_co = dynamic_cast<NetEConst*>(case_value_ex);
|
||||
if (case_value_co == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot evaluate genvar case"
|
||||
<< " expression: " << *loop_test << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
assert(case_value_co);
|
||||
|
||||
// The name of the scope to generate, whatever that item is.
|
||||
hname_t use_name (scope_name);
|
||||
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: Generate case "
|
||||
@@ -687,45 +548,37 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
||||
PGenerate*default_item = 0;
|
||||
|
||||
typedef list<PGenerate*>::const_iterator generator_it_t;
|
||||
generator_it_t cur = generate_schemes.begin();
|
||||
while (cur != generate_schemes.end()) {
|
||||
generator_it_t cur = generates.begin();
|
||||
while (cur != generates.end()) {
|
||||
PGenerate*item = *cur;
|
||||
assert( item->scheme_type == PGenerate::GS_CASE_ITEM );
|
||||
|
||||
// Detect that the item is a default.
|
||||
if (item->item_test.size() == 0) {
|
||||
if (item->loop_test == 0) {
|
||||
default_item = item;
|
||||
cur ++;
|
||||
continue;
|
||||
}
|
||||
|
||||
bool match_flag = false;
|
||||
for (unsigned idx = 0 ; idx < item->item_test.size() && !match_flag ; idx +=1 ) {
|
||||
probe_expr_width(des, container, item->item_test[idx]);
|
||||
NetExpr*item_value_ex = elab_and_eval(des, container, item->item_test[idx], -1);
|
||||
NetEConst*item_value_co = dynamic_cast<NetEConst*>(item_value_ex);
|
||||
assert(item_value_co);
|
||||
NetExpr*item_value_ex = elab_and_eval(des, container, item->loop_test, -1);
|
||||
NetEConst*item_value_co = dynamic_cast<NetEConst*>(item_value_ex);
|
||||
assert(item_value_co);
|
||||
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: Generate case "
|
||||
<< "item value=" << item_value_co->value() << endl;
|
||||
|
||||
if (case_value_co->value() == item_value_co->value())
|
||||
match_flag = true;
|
||||
// If we stumble on the item that matches, then break
|
||||
// out now.
|
||||
if (case_value_co->value() == item_value_co->value()) {
|
||||
delete item_value_co;
|
||||
break;
|
||||
}
|
||||
|
||||
// If we stumble on the item that matches, then break out now.
|
||||
if (match_flag)
|
||||
break;
|
||||
|
||||
delete item_value_co;
|
||||
cur ++;
|
||||
}
|
||||
|
||||
delete case_value_co;
|
||||
case_value_co = 0;
|
||||
|
||||
PGenerate*item = (cur == generate_schemes.end())? default_item : *cur;
|
||||
PGenerate*item = (cur == generates.end())? default_item : *cur;
|
||||
if (item == 0) {
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "No generate items found" << endl;
|
||||
@@ -737,18 +590,6 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
||||
<< "Generate case matches item at "
|
||||
<< item->get_fileline() << endl;
|
||||
|
||||
// The name of the scope to generate, whatever that item is.
|
||||
hname_t use_name (item->scope_name);
|
||||
|
||||
item->probe_for_direct_nesting_();
|
||||
if (item->direct_nested_) {
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: Generate case item " << scope_name
|
||||
<< " detected direct nesting." << endl;
|
||||
item->elaborate_subscope_direct_(des, container);
|
||||
return true;
|
||||
}
|
||||
|
||||
NetScope*scope = new NetScope(container, use_name,
|
||||
NetScope::GENBLOCK);
|
||||
scope->set_line(get_file(), get_lineno());
|
||||
@@ -757,38 +598,6 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PGenerate::generate_scope_nblock_(Design*des, NetScope*container)
|
||||
{
|
||||
hname_t use_name (scope_name);
|
||||
if (container->child(use_name)) {
|
||||
cerr << get_fileline() << ": error: block/scope name "
|
||||
<< scope_name << " already used in this context."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: Generate named block "
|
||||
<< ": Generate scope=" << use_name << endl;
|
||||
|
||||
NetScope*scope = new NetScope(container, use_name,
|
||||
NetScope::GENBLOCK);
|
||||
scope->set_line(get_file(), get_lineno());
|
||||
|
||||
elaborate_subscope_(des, scope);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PGenerate::elaborate_subscope_direct_(Design*des, NetScope*scope)
|
||||
{
|
||||
typedef list<PGenerate*>::const_iterator generate_it_t;
|
||||
for (generate_it_t cur = generate_schemes.begin()
|
||||
; cur != generate_schemes.end() ; cur ++ ) {
|
||||
(*cur) -> generate_scope(des, scope);
|
||||
}
|
||||
}
|
||||
|
||||
void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
|
||||
{
|
||||
// Scan the generated scope for nested generate schemes,
|
||||
@@ -796,24 +605,11 @@ void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
|
||||
// from simple elaboration.
|
||||
|
||||
typedef list<PGenerate*>::const_iterator generate_it_t;
|
||||
for (generate_it_t cur = generate_schemes.begin()
|
||||
; cur != generate_schemes.end() ; cur ++ ) {
|
||||
for (generate_it_t cur = generates.begin()
|
||||
; cur != generates.end() ; cur ++ ) {
|
||||
(*cur) -> generate_scope(des, scope);
|
||||
}
|
||||
|
||||
// Scan the localparams in this scope, and create stub parameter
|
||||
// entries in the scope for the parameter names.
|
||||
collect_scope_localparams_(scope, localparams);
|
||||
|
||||
// Now scan the localparams again, this time elaborating them
|
||||
// for use as parameter values.
|
||||
elaborate_scope_localparams_(des, scope, localparams);
|
||||
|
||||
// Scan through all the task and function declarations in this
|
||||
// scope.
|
||||
elaborate_scope_tasks(des, scope, *this, tasks);
|
||||
elaborate_scope_funcs(des, scope, *this, funcs);
|
||||
|
||||
// Scan the generated scope for gates that may create
|
||||
// their own scopes.
|
||||
typedef list<PGate*>::const_iterator pgate_list_it_t;
|
||||
@@ -822,58 +618,10 @@ void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
|
||||
(*cur) ->elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
typedef list<PProcess*>::const_iterator proc_it_t;
|
||||
for (proc_it_t cur = behaviors.begin()
|
||||
; cur != behaviors.end() ; cur ++ ) {
|
||||
(*cur) -> statement() -> elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
// Scan through all the named events in this scope.
|
||||
elaborate_scope_events_(des, scope, events);
|
||||
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: Generated scope " << scope_path(scope)
|
||||
<< " by generate block " << scope_name << endl;
|
||||
|
||||
// Save the scope that we created, for future use.
|
||||
scope_list_.push_back(scope);
|
||||
}
|
||||
|
||||
class delayed_elaborate_scope_mod_instances : public elaborator_work_item_t {
|
||||
|
||||
public:
|
||||
delayed_elaborate_scope_mod_instances(Design*des__,
|
||||
const PGModule*obj,
|
||||
Module*mod,
|
||||
NetScope*sc)
|
||||
: elaborator_work_item_t(des__), obj_(obj), mod_(mod), sc_(sc)
|
||||
{ }
|
||||
~delayed_elaborate_scope_mod_instances() { }
|
||||
|
||||
virtual void elaborate_runrun();
|
||||
|
||||
private:
|
||||
const PGModule*obj_;
|
||||
Module*mod_;
|
||||
NetScope*sc_;
|
||||
};
|
||||
|
||||
void delayed_elaborate_scope_mod_instances::elaborate_runrun()
|
||||
{
|
||||
if (debug_scopes)
|
||||
cerr << obj_->get_fileline() << ": debug: "
|
||||
<< "Resume scope elaboration of instances of "
|
||||
<< mod_->mod_name() << "." << endl;
|
||||
|
||||
obj_->elaborate_scope_mod_instances_(des, mod_, sc_);
|
||||
}
|
||||
|
||||
/*
|
||||
* Here we handle the elaborate scope of a module instance. The caller
|
||||
* has already figured out that this "gate" is a module, and has found
|
||||
* the module definition. The "sc" argument is the scope that will
|
||||
* contain this instance.
|
||||
*/
|
||||
void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
{
|
||||
if (get_name() == "") {
|
||||
@@ -920,38 +668,6 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
return;
|
||||
}
|
||||
|
||||
if (msb_ || lsb_) {
|
||||
// If there are expressions to evaluate in order to know
|
||||
// the actual number of instances that will be
|
||||
// instantiated, then we have to delay further scope
|
||||
// elaboration until after defparams (above me) are
|
||||
// run. Do that by appending a work item to the
|
||||
// elaboration work list.
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: delay elaborate_scope"
|
||||
<< " of array of " << get_name()
|
||||
<< " in scope " << scope_path(sc) << "." << endl;
|
||||
|
||||
elaborator_work_item_t*tmp
|
||||
= new delayed_elaborate_scope_mod_instances(des, this, mod, sc);
|
||||
des->elaboration_work_list.push_back(tmp);
|
||||
|
||||
} else {
|
||||
// If there are no expressions that need to be evaluated
|
||||
// to elaborate the scope of this next instances, then
|
||||
// get right to it.
|
||||
elaborate_scope_mod_instances_(des, mod, sc);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This method is called to process a module instantiation after basic
|
||||
* sanity testing is already complete.
|
||||
*/
|
||||
void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*sc) const
|
||||
{
|
||||
if (msb_) probe_expr_width(des, sc, msb_);
|
||||
if (lsb_) probe_expr_width(des, sc, lsb_);
|
||||
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_, -1) : 0;
|
||||
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1) : 0;
|
||||
NetEConst*msb = dynamic_cast<NetEConst*> (mse);
|
||||
@@ -1039,16 +755,16 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
|
||||
assert(parms_ == 0);
|
||||
list<perm_string>::const_iterator cur
|
||||
= mod->param_names.begin();
|
||||
unsigned jdx = 0;
|
||||
unsigned idx = 0;
|
||||
for (;;) {
|
||||
if (jdx >= overrides_->count())
|
||||
if (idx >= overrides_->count())
|
||||
break;
|
||||
if (cur == mod->param_names.end())
|
||||
break;
|
||||
|
||||
replace[*cur] = (*overrides_)[jdx];
|
||||
replace[*cur] = (*overrides_)[idx];
|
||||
|
||||
jdx += 1;
|
||||
idx += 1;
|
||||
cur ++;
|
||||
}
|
||||
}
|
||||
@@ -1057,8 +773,8 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
|
||||
// so the mapping into the replace list is much easier.
|
||||
if (parms_) {
|
||||
assert(overrides_ == 0);
|
||||
for (unsigned jdx = 0 ; jdx < nparms_ ; jdx += 1)
|
||||
replace[parms_[jdx].name] = parms_[jdx].parm;
|
||||
for (unsigned idx = 0 ; idx < nparms_ ; idx += 1)
|
||||
replace[parms_[idx].name] = parms_[idx].parm;
|
||||
|
||||
}
|
||||
|
||||
@@ -1118,25 +834,6 @@ void PFunction::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope->type() == NetScope::FUNC);
|
||||
|
||||
// Scan the parameters in the function, and create stub parameter
|
||||
// entries in the scope for the parameter names.
|
||||
|
||||
collect_scope_parameters_(scope, parameters);
|
||||
|
||||
collect_scope_localparams_(scope, localparams);
|
||||
|
||||
// Now scan the parameters again, this time elaborating them
|
||||
// for use as parameter values. This is after the previous
|
||||
// scan so that local parameter names can be used in the
|
||||
// r-value expressions.
|
||||
|
||||
elaborate_scope_parameters_(des, scope, parameters);
|
||||
|
||||
elaborate_scope_localparams_(des, scope, localparams);
|
||||
|
||||
// Scan through all the named events in this scope.
|
||||
elaborate_scope_events_(des, scope, events);
|
||||
|
||||
if (statement_)
|
||||
statement_->elaborate_scope(des, scope);
|
||||
}
|
||||
@@ -1145,25 +842,6 @@ void PTask::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope->type() == NetScope::TASK);
|
||||
|
||||
// Scan the parameters in the task, and create stub parameter
|
||||
// entries in the scope for the parameter names.
|
||||
|
||||
collect_scope_parameters_(scope, parameters);
|
||||
|
||||
collect_scope_localparams_(scope, localparams);
|
||||
|
||||
// Now scan the parameters again, this time elaborating them
|
||||
// for use as parameter values. This is after the previous
|
||||
// scan so that local parameter names can be used in the
|
||||
// r-value expressions.
|
||||
|
||||
elaborate_scope_parameters_(des, scope, parameters);
|
||||
|
||||
elaborate_scope_localparams_(des, scope, localparams);
|
||||
|
||||
// Scan through all the named events in this scope.
|
||||
elaborate_scope_events_(des, scope, events);
|
||||
|
||||
if (statement_)
|
||||
statement_->elaborate_scope(des, scope);
|
||||
}
|
||||
@@ -1196,39 +874,15 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Elaborate block scope " << use_name
|
||||
<< " within " << scope_path(scope) << endl;
|
||||
|
||||
my_scope = new NetScope(scope, use_name, bl_type_==BL_PAR
|
||||
? NetScope::FORK_JOIN
|
||||
: NetScope::BEGIN_END);
|
||||
my_scope->set_line(get_file(), get_lineno());
|
||||
my_scope->is_auto(scope->is_auto());
|
||||
|
||||
// Scan the parameters in the scope, and create stub parameter
|
||||
// entries in the scope for the parameter names.
|
||||
|
||||
collect_scope_parameters_(my_scope, parameters);
|
||||
|
||||
collect_scope_localparams_(my_scope, localparams);
|
||||
|
||||
// Now scan the parameters again, this time elaborating them
|
||||
// for use as parameter values. This is after the previous
|
||||
// scan so that local parameter names can be used in the
|
||||
// r-value expressions.
|
||||
|
||||
elaborate_scope_parameters_(des, my_scope, parameters);
|
||||
|
||||
elaborate_scope_localparams_(des, my_scope, localparams);
|
||||
|
||||
// Scan through all the named events in this scope.
|
||||
elaborate_scope_events_(des, my_scope, events);
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < list_.count() ; idx += 1)
|
||||
list_[idx] -> elaborate_scope(des, my_scope);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+62
-151
@@ -108,49 +108,13 @@ bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const
|
||||
return flag;
|
||||
}
|
||||
|
||||
static void elaborate_sig_funcs(Design*des, NetScope*scope,
|
||||
const map<perm_string,PFunction*>&funcs)
|
||||
{
|
||||
typedef map<perm_string,PFunction*>::const_iterator mfunc_it_t;
|
||||
|
||||
for (mfunc_it_t cur = funcs.begin()
|
||||
; cur != funcs.end() ; cur ++) {
|
||||
|
||||
hname_t use_name ( (*cur).first );
|
||||
NetScope*fscope = scope->child(use_name);
|
||||
if (scope == 0) {
|
||||
cerr << (*cur).second->get_fileline() << ": internal error: "
|
||||
<< "Child scope for function " << (*cur).first
|
||||
<< " missing in " << scope_path(scope) << "." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
(*cur).second->elaborate_sig(des, fscope);
|
||||
}
|
||||
}
|
||||
|
||||
static void elaborate_sig_tasks(Design*des, NetScope*scope,
|
||||
const map<perm_string,PTask*>&tasks)
|
||||
{
|
||||
typedef map<perm_string,PTask*>::const_iterator mtask_it_t;
|
||||
|
||||
for (mtask_it_t cur = tasks.begin()
|
||||
; cur != tasks.end() ; cur ++) {
|
||||
NetScope*tscope = scope->child( hname_t((*cur).first) );
|
||||
assert(tscope);
|
||||
(*cur).second->elaborate_sig(des, tscope);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
// Scan all the ports of the module, and make sure that each
|
||||
// is connected to wires that have port declarations.
|
||||
for (unsigned idx = 0 ; idx < ports.size() ; idx += 1) {
|
||||
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
|
||||
Module::port_t*pp = ports[idx];
|
||||
if (pp == 0)
|
||||
continue;
|
||||
@@ -159,7 +123,7 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
// expression are all identifiers that should reference
|
||||
// wires within the scope.
|
||||
map<perm_string,PWire*>::const_iterator wt;
|
||||
for (unsigned cc = 0 ; cc < pp->expr.size() ; cc += 1) {
|
||||
for (unsigned cc = 0 ; cc < pp->expr.count() ; cc += 1) {
|
||||
pform_name_t port_path (pp->expr[cc]->path());
|
||||
// A concatenated wire of a port really should not
|
||||
// have any hierarchy.
|
||||
@@ -218,12 +182,38 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
flag &= (*gt)->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
|
||||
typedef map<perm_string,PFunction*>::const_iterator mfunc_it_t;
|
||||
|
||||
for (mfunc_it_t cur = funcs_.begin()
|
||||
; cur != funcs_.end() ; cur ++) {
|
||||
|
||||
hname_t use_name ( (*cur).first );
|
||||
NetScope*fscope = scope->child(use_name);
|
||||
if (scope == 0) {
|
||||
cerr << (*cur).second->get_fileline() << ": internal error: "
|
||||
<< "Child scope for function " << (*cur).first
|
||||
<< " missing in " << scope_path(scope) << "." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
(*cur).second->elaborate_sig(des, fscope);
|
||||
}
|
||||
|
||||
|
||||
// After all the wires are elaborated, we are free to
|
||||
// elaborate the ports of the tasks defined within this
|
||||
// module. Run through them now.
|
||||
|
||||
elaborate_sig_funcs(des, scope, funcs);
|
||||
elaborate_sig_tasks(des, scope, tasks);
|
||||
typedef map<perm_string,PTask*>::const_iterator mtask_it_t;
|
||||
|
||||
for (mtask_it_t cur = tasks_.begin()
|
||||
; cur != tasks_.end() ; cur ++) {
|
||||
NetScope*tscope = scope->child( hname_t((*cur).first) );
|
||||
assert(tscope);
|
||||
(*cur).second->elaborate_sig(des, tscope);
|
||||
}
|
||||
|
||||
// initial and always blocks may contain begin-end and
|
||||
// fork-join blocks that can introduce scopes. Therefore, I
|
||||
@@ -266,7 +256,7 @@ bool PEIdent::elaborate_sig(Design*des, NetScope*scope) const
|
||||
if (error_implicit)
|
||||
return true;
|
||||
|
||||
symbol_search(this, des, scope, path_, sig, par, eve);
|
||||
symbol_search(des, scope, path_, sig, par, eve);
|
||||
|
||||
if (eve != 0)
|
||||
return false;
|
||||
@@ -361,11 +351,11 @@ bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
|
||||
continue;
|
||||
flag = tmp->elaborate_sig(des, scope) && flag;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NetScope::scope_vec_t instance = scope->instance_arrays[get_name()];
|
||||
|
||||
for (unsigned idx = 0 ; idx < instance.size() ; idx += 1) {
|
||||
for (unsigned idx = 0 ; idx < instance.count() ; idx += 1) {
|
||||
// I know a priori that the elaborate_scope created the scope
|
||||
// already, so just look it up as a child of the current scope.
|
||||
NetScope*my_scope = instance[idx];
|
||||
@@ -412,9 +402,6 @@ bool PGModule::elaborate_sig_udp_(Design*des, NetScope*scope, PUdp*udp) const
|
||||
|
||||
bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
|
||||
{
|
||||
if (direct_nested_)
|
||||
return elaborate_sig_direct_(des, container);
|
||||
|
||||
bool flag = true;
|
||||
|
||||
// Handle the special case that this is a CASE scheme. In this
|
||||
@@ -428,10 +415,10 @@ bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
|
||||
<< scope_path(container) << "." << endl;
|
||||
|
||||
typedef list<PGenerate*>::const_iterator generate_it_t;
|
||||
for (generate_it_t cur = generate_schemes.begin()
|
||||
; cur != generate_schemes.end() ; cur ++) {
|
||||
for (generate_it_t cur = generates.begin()
|
||||
; cur != generates.end() ; cur ++) {
|
||||
PGenerate*item = *cur;
|
||||
if (item->direct_nested_ || !item->scope_list_.empty()) {
|
||||
if (! item->scope_list_.empty()) {
|
||||
flag &= item->elaborate_sig(des, container);
|
||||
}
|
||||
}
|
||||
@@ -457,32 +444,6 @@ bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool PGenerate::elaborate_sig_direct_(Design*des, NetScope*container) const
|
||||
{
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Direct nesting " << scope_name
|
||||
<< " (scheme_type=" << scheme_type << ")"
|
||||
<< " elaborate_sig in scope "
|
||||
<< scope_path(container) << "." << endl;
|
||||
|
||||
// Elaborate_sig for a direct nested generated scheme knows
|
||||
// that there are only sub_schemes to be elaborated. There
|
||||
// should be exactly 1 active generate scheme, search for it
|
||||
// using this loop.
|
||||
bool flag = true;
|
||||
typedef list<PGenerate*>::const_iterator generate_it_t;
|
||||
for (generate_it_t cur = generate_schemes.begin()
|
||||
; cur != generate_schemes.end() ; cur ++) {
|
||||
PGenerate*item = *cur;
|
||||
if (item->direct_nested_ || !item->scope_list_.empty()) {
|
||||
// Found the item, and it is direct nested.
|
||||
flag &= item->elaborate_sig(des, container);
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
|
||||
{
|
||||
// Scan the declared PWires to elaborate the obvious signals
|
||||
@@ -500,12 +461,9 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
|
||||
cur->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
elaborate_sig_funcs(des, scope, funcs);
|
||||
elaborate_sig_tasks(des, scope, tasks);
|
||||
|
||||
typedef list<PGenerate*>::const_iterator generate_it_t;
|
||||
for (generate_it_t cur = generate_schemes.begin()
|
||||
; cur != generate_schemes.end() ; cur ++ ) {
|
||||
for (generate_it_t cur = generates.begin()
|
||||
; cur != generates.end() ; cur ++ ) {
|
||||
(*cur) -> elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
@@ -515,13 +473,6 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
|
||||
(*cur) ->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
typedef list<PProcess*>::const_iterator proc_it_t;
|
||||
for (proc_it_t cur = behaviors.begin()
|
||||
; cur != behaviors.end() ; cur ++ ) {
|
||||
(*cur) -> statement() -> elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -559,9 +510,6 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
case PTF_REG:
|
||||
case PTF_REG_S:
|
||||
if (return_type_.range) {
|
||||
probe_expr_width(des, scope, (*return_type_.range)[0]);
|
||||
probe_expr_width(des, scope, (*return_type_.range)[1]);
|
||||
|
||||
NetExpr*me = elab_and_eval(des, scope,
|
||||
(*return_type_.range)[0], -1);
|
||||
assert(me);
|
||||
@@ -628,17 +576,9 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
break;
|
||||
|
||||
default:
|
||||
if (ports_) {
|
||||
cerr << get_fileline() << ": internal error: I don't know "
|
||||
<< "how to deal with return type of function "
|
||||
<< scope->basename() << "." << endl;
|
||||
} else {
|
||||
/* If we do not have any ports or a return type this
|
||||
* is probably a bad function definition. */
|
||||
cerr << get_fileline() << ": error: Bad definition for "
|
||||
<< "function " << scope->basename() << "?" << endl;
|
||||
return;
|
||||
}
|
||||
cerr << get_fileline() << ": internal error: I don't know how "
|
||||
<< "to deal with return type of function "
|
||||
<< scope->basename() << "." << endl;
|
||||
}
|
||||
|
||||
svector<NetNet*>ports (ports_? ports_->count() : 0);
|
||||
@@ -852,35 +792,28 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
if (port_set_ || net_set_) {
|
||||
long pmsb = 0, plsb = 0, nmsb = 0, nlsb = 0;
|
||||
bool bad_lsb = false, bad_msb = false;
|
||||
/* If they exist get the port definition MSB and LSB */
|
||||
if (port_set_ && port_msb_ != 0) {
|
||||
probe_expr_width(des, scope, port_msb_);
|
||||
NetExpr*texpr = elab_and_eval(des, scope, port_msb_, -1);
|
||||
|
||||
if (! eval_as_long(pmsb, texpr)) {
|
||||
cerr << port_msb_->get_fileline() << ": error: "
|
||||
"Range expressions must be constant." << endl;
|
||||
cerr << port_msb_->get_fileline() << " : "
|
||||
"This MSB expression violates the rule: "
|
||||
<< *port_msb_ << endl;
|
||||
"Unable to evaluate MSB constant expression ``"
|
||||
<< *port_msb_ << "''." << endl;
|
||||
des->errors += 1;
|
||||
bad_msb = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
delete texpr;
|
||||
|
||||
probe_expr_width(des, scope, port_lsb_);
|
||||
texpr = elab_and_eval(des, scope, port_lsb_, -1);
|
||||
|
||||
if (! eval_as_long(plsb, texpr)) {
|
||||
cerr << port_lsb_->get_fileline() << ": error: "
|
||||
"Range expressions must be constant." << endl;
|
||||
cerr << port_lsb_->get_fileline() << " : "
|
||||
"This LSB expression violates the rule: "
|
||||
<< *port_lsb_ << endl;
|
||||
"Unable to evaluate LSB constant expression ``"
|
||||
<< *port_lsb_ << "''." << endl;
|
||||
des->errors += 1;
|
||||
bad_lsb = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
delete texpr;
|
||||
@@ -892,33 +825,27 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
if (port_lsb_ == 0) assert(port_msb_ == 0);
|
||||
|
||||
/* If they exist get the net/etc. definition MSB and LSB */
|
||||
if (net_set_ && net_msb_ != 0 && !bad_msb && !bad_lsb) {
|
||||
probe_expr_width(des, scope, net_msb_);
|
||||
if (net_set_ && net_msb_ != 0) {
|
||||
NetExpr*texpr = elab_and_eval(des, scope, net_msb_, -1);
|
||||
|
||||
if (! eval_as_long(nmsb, texpr)) {
|
||||
cerr << net_msb_->get_fileline() << ": error: "
|
||||
"Range expressions must be constant." << endl;
|
||||
cerr << net_msb_->get_fileline() << " : "
|
||||
"This MSB expression violates the rule: "
|
||||
<< *net_msb_ << endl;
|
||||
"Unable to evaluate MSB constant expression ``"
|
||||
<< *net_msb_ << "''." << endl;
|
||||
des->errors += 1;
|
||||
bad_msb = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
delete texpr;
|
||||
|
||||
probe_expr_width(des, scope, net_lsb_);
|
||||
texpr = elab_and_eval(des, scope, net_lsb_, -1);
|
||||
|
||||
if (! eval_as_long(nlsb, texpr)) {
|
||||
cerr << net_lsb_->get_fileline() << ": error: "
|
||||
"Range expressions must be constant." << endl;
|
||||
cerr << net_lsb_->get_fileline() << " : "
|
||||
"This LSB expression violates the rule: "
|
||||
<< *net_lsb_ << endl;
|
||||
"Unable to evaluate LSB constant expression ``"
|
||||
<< *net_lsb_ << "''." << endl;
|
||||
des->errors += 1;
|
||||
bad_lsb = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
delete texpr;
|
||||
@@ -971,10 +898,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
}
|
||||
}
|
||||
|
||||
/* Attempt to recover from errors. */
|
||||
if (bad_lsb) nlsb = 0;
|
||||
if (bad_msb) nmsb = nlsb;
|
||||
|
||||
lsb = nlsb;
|
||||
msb = nmsb;
|
||||
if (nmsb > nlsb)
|
||||
@@ -1000,9 +923,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
if (lidx_ || ridx_) {
|
||||
assert(lidx_ && ridx_);
|
||||
|
||||
probe_expr_width(des, scope, lidx_);
|
||||
probe_expr_width(des, scope, ridx_);
|
||||
|
||||
NetExpr*lexp = elab_and_eval(des, scope, lidx_, -1);
|
||||
NetExpr*rexp = elab_and_eval(des, scope, ridx_, -1);
|
||||
|
||||
@@ -1022,18 +942,16 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
delete lexp;
|
||||
|
||||
if (!const_flag) {
|
||||
cerr << get_fileline() << ": error: The indices "
|
||||
cerr << get_fileline() << ": internal error: The indices "
|
||||
<< "are not constant for array ``"
|
||||
<< name_ << "''." << endl;
|
||||
des->errors += 1;
|
||||
/* Attempt to recover from error, */
|
||||
array_s0 = 0;
|
||||
array_e0 = 0;
|
||||
} else {
|
||||
array_s0 = lval.as_long();
|
||||
array_e0 = rval.as_long();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
array_dimensions = 1;
|
||||
array_s0 = lval.as_long();
|
||||
array_e0 = rval.as_long();
|
||||
}
|
||||
|
||||
/* If the net type is supply0 or supply1, replace it
|
||||
@@ -1072,11 +990,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Create signal "
|
||||
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name_;
|
||||
if (array_dimensions > 0) {
|
||||
cerr << " [" << array_s0 << ":" << array_e0 << "]" << endl;
|
||||
}
|
||||
cerr << " in scope " << scope_path(scope) << endl;
|
||||
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name_
|
||||
<< " in scope " << scope_path(scope) << endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -1101,10 +1016,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
sig->set_signed(get_signed());
|
||||
sig->set_isint(get_isint());
|
||||
|
||||
if (ivl_discipline_t dis = get_discipline()) {
|
||||
sig->set_discipline(dis);
|
||||
}
|
||||
|
||||
if (pull)
|
||||
connect(sig->pin(0), pull->pin(0));
|
||||
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "AStatement.h"
|
||||
|
||||
# include <cstdlib>
|
||||
# include <iostream>
|
||||
|
||||
+744
-1242
File diff suppressed because it is too large
Load Diff
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "AStatement.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "util.h"
|
||||
|
||||
# include <typeinfo>
|
||||
|
||||
NetProc* AContrib::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
probe_expr_width(des, scope, lval_);
|
||||
probe_expr_width(des, scope, rval_);
|
||||
NetExpr*lval = elab_and_eval(des, scope, lval_, -1);
|
||||
NetExpr*rval = elab_and_eval(des, scope, rval_, -1);
|
||||
|
||||
NetEAccess*lacc = dynamic_cast<NetEAccess*> (lval);
|
||||
if (lacc == 0) {
|
||||
cerr << get_fileline() << ": error: The l-value of a contribution"
|
||||
<< " statement must be a branch probe access function." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetContribution*st = new NetContribution(lacc, rval);
|
||||
st->set_line(*this);
|
||||
return st;
|
||||
}
|
||||
|
||||
bool AProcess::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetProc*statement = statement_->elaborate(des, scope);
|
||||
if (statement == 0)
|
||||
return false;
|
||||
|
||||
NetAnalogTop*top = new NetAnalogTop(scope, type_, statement);
|
||||
|
||||
// Evaluate the attributes for this process, if there
|
||||
// are any. These attributes are to be attached to the
|
||||
// NetProcTop object.
|
||||
struct attrib_list_t*attrib_list = 0;
|
||||
unsigned attrib_list_n = 0;
|
||||
attrib_list = evaluate_attributes(attributes, attrib_list_n, des, scope);
|
||||
|
||||
for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1)
|
||||
top->attribute(attrib_list[adx].key,
|
||||
attrib_list[adx].val);
|
||||
|
||||
delete[]attrib_list;
|
||||
|
||||
top->set_line(*this);
|
||||
des->add_process(top);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -72,16 +72,6 @@ bool NetCaseCmp::emit_node(struct target_t*tgt) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetCastInt::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->lpm_cast_int(this);
|
||||
}
|
||||
|
||||
bool NetCastReal::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->lpm_cast_real(this);
|
||||
}
|
||||
|
||||
bool NetCLShift::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_clshift(this);
|
||||
@@ -190,26 +180,16 @@ bool NetProcTop::emit(struct target_t*tgt) const
|
||||
return tgt->process(this);
|
||||
}
|
||||
|
||||
bool NetAnalogTop::emit(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->process(this);
|
||||
}
|
||||
|
||||
bool NetProc::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
cerr << "EMIT: Proc type? " << typeid(*this).name() << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetAlloc::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_alloc(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetAssign::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->proc_assign(this);
|
||||
tgt->proc_assign(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetAssignNB::emit_proc(struct target_t*tgt) const
|
||||
@@ -239,11 +219,6 @@ bool NetCondit::emit_proc(struct target_t*tgt) const
|
||||
return tgt->proc_condit(this);
|
||||
}
|
||||
|
||||
bool NetContribution::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->proc_contribution(this);
|
||||
}
|
||||
|
||||
bool NetDeassign::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->proc_deassign(this);
|
||||
@@ -265,12 +240,6 @@ bool NetForever::emit_proc(struct target_t*tgt) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetFree::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_free(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetPDelay::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->proc_delay(this);
|
||||
@@ -383,20 +352,23 @@ void NetScope::emit_scope(struct target_t*tgt) const
|
||||
for (NetScope*cur = sub_ ; cur ; cur = cur->sib_)
|
||||
cur->emit_scope(tgt);
|
||||
|
||||
for (signals_map_iter_t cur = signals_map_.begin()
|
||||
; cur != signals_map_.end() ; cur ++) {
|
||||
tgt->signal(cur->second);
|
||||
}
|
||||
if (signals_) {
|
||||
NetNet*cur = signals_->sig_next_;
|
||||
do {
|
||||
tgt->signal(cur);
|
||||
cur = cur->sig_next_;
|
||||
} while (cur != signals_->sig_next_);
|
||||
|
||||
// Run the signals again, but this time to connect the
|
||||
// delay paths. This is done as a second pass because
|
||||
// the paths reference other signals that may be later
|
||||
// in the list. We can do it here because delay paths are
|
||||
// always connected within the scope.
|
||||
for (signals_map_iter_t cur = signals_map_.begin()
|
||||
; cur != signals_map_.end() ; cur ++) {
|
||||
|
||||
tgt->signal_paths(cur->second);
|
||||
/* Run the signals again, but this time to connect the
|
||||
delay paths. This is done as a second pass because
|
||||
the paths reference other signals that may be later
|
||||
in the list. We can do it here becase delay paths are
|
||||
always connected within the scope. */
|
||||
cur = signals_->sig_next_;
|
||||
do {
|
||||
tgt->signal_paths(cur);
|
||||
cur = cur->sig_next_;
|
||||
} while (cur != signals_->sig_next_);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -455,11 +427,6 @@ int Design::emit(struct target_t*tgt) const
|
||||
}
|
||||
|
||||
|
||||
bool branches_rc = true;
|
||||
for (NetBranch*cur = branches_ ; cur ; cur = cur->next_) {
|
||||
branches_rc = tgt->branch(cur) && branches_rc;
|
||||
}
|
||||
|
||||
// emit task and function definitions
|
||||
bool tasks_rc = true;
|
||||
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
|
||||
@@ -471,8 +438,6 @@ int Design::emit(struct target_t*tgt) const
|
||||
bool proc_rc = true;
|
||||
for (const NetProcTop*idx = procs_ ; idx ; idx = idx->next_)
|
||||
proc_rc &= idx->emit(tgt);
|
||||
for (const NetAnalogTop*idx = aprocs_ ; idx ; idx = idx->next_)
|
||||
proc_rc &= idx->emit(tgt);
|
||||
|
||||
rc = tgt->end_design(this);
|
||||
|
||||
@@ -482,17 +447,10 @@ int Design::emit(struct target_t*tgt) const
|
||||
return -2;
|
||||
if (proc_rc == false)
|
||||
return -3;
|
||||
if (branches_rc == false)
|
||||
return -4;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void NetEAccess::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_access_func(this);
|
||||
}
|
||||
|
||||
void NetEBinary::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_binary(this);
|
||||
@@ -568,3 +526,17 @@ void NetEUnary::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_unary(this);
|
||||
}
|
||||
|
||||
int emit(const Design*des, const char*type)
|
||||
{
|
||||
for (unsigned idx = 0 ; target_table[idx] ; idx += 1) {
|
||||
const struct target*tgt = target_table[idx];
|
||||
if (strcmp(tgt->name, type) == 0)
|
||||
return des->emit(tgt->meth);
|
||||
|
||||
}
|
||||
|
||||
cerr << "error: Code generator type " << type
|
||||
<< " not found." << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ verinum* PEIdent::eval_const(Design*des, NetScope*scope) const
|
||||
return new verinum(scope->genvar_tmp_val);
|
||||
}
|
||||
|
||||
symbol_search(this, des, scope, path_, net, expr, eve);
|
||||
symbol_search(des, scope, path_, net, expr, eve);
|
||||
|
||||
if (expr == 0)
|
||||
return 0;
|
||||
|
||||
+44
-10
@@ -16,6 +16,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval_attrib.cc,v 1.9 2007/06/04 19:14:06 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "util.h"
|
||||
@@ -50,19 +53,14 @@ attrib_list_t* evaluate_attributes(const map<perm_string,PExpr*>&att,
|
||||
/* If the attribute value is given in the source, then
|
||||
evaluate it as a constant. If the value is not
|
||||
given, then assume the value is 1. */
|
||||
verinum*tmp = 0;
|
||||
if (exp) {
|
||||
verinum*tmp;
|
||||
if (exp)
|
||||
tmp = exp->eval_const(des, scope);
|
||||
if (tmp == 0) {
|
||||
cerr << exp->get_fileline() << ": error: ``"
|
||||
<< *exp << "'' is not a constant expression."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
if (tmp == 0)
|
||||
else
|
||||
tmp = new verinum(1);
|
||||
|
||||
if (tmp == 0)
|
||||
cerr << "internal error: no result for " << *exp << endl;
|
||||
assert(tmp);
|
||||
|
||||
table[idx].val = *tmp;
|
||||
@@ -73,3 +71,39 @@ attrib_list_t* evaluate_attributes(const map<perm_string,PExpr*>&att,
|
||||
return table;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: eval_attrib.cc,v $
|
||||
* Revision 1.9 2007/06/04 19:14:06 steve
|
||||
* Build errors in picky GCC compilers.
|
||||
*
|
||||
* Revision 1.8 2005/11/27 17:01:57 steve
|
||||
* Fix for stubborn compiler.
|
||||
*
|
||||
* Revision 1.7 2004/02/20 18:53:35 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
* Revision 1.6 2003/01/27 05:09:17 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.5 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.4 2002/08/10 21:59:39 steve
|
||||
* The default attribute value is 1.
|
||||
*
|
||||
* Revision 1.3 2002/06/06 18:57:18 steve
|
||||
* Use standard name for iostream.
|
||||
*
|
||||
* Revision 1.2 2002/06/03 03:55:14 steve
|
||||
* compile warnings.
|
||||
*
|
||||
* Revision 1.1 2002/05/23 03:08:51 steve
|
||||
* Add language support for Verilog-2001 attribute
|
||||
* syntax. Hook this support into existing $attribute
|
||||
* handling, and add number and void value types.
|
||||
*
|
||||
* Add to the ivl_target API new functions for access
|
||||
* of complex attributes attached to gates.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
+55
-434
@@ -22,8 +22,6 @@
|
||||
|
||||
# include <iostream>
|
||||
# include <cstdlib>
|
||||
# include <cstring>
|
||||
# include <math.h>
|
||||
|
||||
# include "netlist.h"
|
||||
# include "ivl_assert.h"
|
||||
@@ -133,19 +131,6 @@ NetExpr* NetEBAdd::eval_tree(int prune_to_width)
|
||||
verinum lval = lc->value();
|
||||
verinum rval = rc->value();
|
||||
|
||||
if (lval.len() < expr_width())
|
||||
lval = pad_to_width(lval, expr_width());
|
||||
if (rval.len() < expr_width())
|
||||
rval = pad_to_width(rval, expr_width());
|
||||
|
||||
if (se->expr_width() > this->expr_width()) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "expr_width()=" << expr_width()
|
||||
<< ", sub expr_width()=" << se->expr_width()
|
||||
<< ", sub expression=" << *se << endl;
|
||||
}
|
||||
ivl_assert(*this, se->expr_width() <= this->expr_width());
|
||||
|
||||
verinum val;
|
||||
if (op_ == se->op_) {
|
||||
/* (a + lval) + rval --> a + (rval+lval) */
|
||||
@@ -157,15 +142,6 @@ NetExpr* NetEBAdd::eval_tree(int prune_to_width)
|
||||
val = rval - lval;
|
||||
}
|
||||
|
||||
// Since we padded the operands above to be the minimum
|
||||
// width, the val should also be at least expr_width().
|
||||
ivl_assert(*this, val.len() >= expr_width());
|
||||
if (val.len() > expr_width()) {
|
||||
verinum tmp (val, expr_width());
|
||||
tmp.has_sign(val.has_sign());
|
||||
val = tmp;
|
||||
}
|
||||
|
||||
NetEConst*tmp = new NetEConst(val);
|
||||
left_ = se->left_->dup_expr();
|
||||
delete se;
|
||||
@@ -362,15 +338,19 @@ NetEConst* NetEBComp::eval_leeq_real_(NetExpr*le, NetExpr*ri, bool eq_flag)
|
||||
switch (le->expr_type()) {
|
||||
case IVL_VT_REAL:
|
||||
rtmp = dynamic_cast<NetECReal*> (le);
|
||||
if (rtmp == 0) return 0;
|
||||
if (rtmp == 0)
|
||||
return 0;
|
||||
|
||||
lv = rtmp->value().as_double();
|
||||
break;
|
||||
|
||||
case IVL_VT_LOGIC:
|
||||
case IVL_VT_BOOL:
|
||||
vtmp = dynamic_cast<NetEConst*> (le);
|
||||
if (vtmp == 0) return 0;
|
||||
lv = vtmp->value().as_double();
|
||||
if (vtmp == 0)
|
||||
return 0;
|
||||
|
||||
lv = vtmp->value().as_long();
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -379,18 +359,23 @@ NetEConst* NetEBComp::eval_leeq_real_(NetExpr*le, NetExpr*ri, bool eq_flag)
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
switch (ri->expr_type()) {
|
||||
case IVL_VT_REAL:
|
||||
rtmp = dynamic_cast<NetECReal*> (ri);
|
||||
if (rtmp == 0) return 0;
|
||||
if (rtmp == 0)
|
||||
return 0;
|
||||
|
||||
rv = rtmp->value().as_double();
|
||||
break;
|
||||
|
||||
case IVL_VT_LOGIC:
|
||||
case IVL_VT_BOOL:
|
||||
vtmp = dynamic_cast<NetEConst*> (ri);
|
||||
if (vtmp == 0) return 0;
|
||||
rv = vtmp->value().as_double();
|
||||
if (vtmp == 0)
|
||||
return 0;
|
||||
|
||||
rv = vtmp->value().as_long();
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -494,6 +479,19 @@ NetEConst* NetEBComp::eval_gt_()
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* Compare with a real value. Do it as double precision. */
|
||||
if (right_->expr_type() == IVL_VT_REAL) {
|
||||
NetECReal*tmp = dynamic_cast<NetECReal*>(right_);
|
||||
if (tmp == 0)
|
||||
return 0;
|
||||
|
||||
double rr = tmp->value().as_double();
|
||||
double ll = lv.has_sign()? lv.as_long() : lv.as_ulong();
|
||||
|
||||
verinum result ((ll > rr)? verinum::V1 : verinum::V0, 1, true);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
/* Now go on to the normal test of the values. */
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
@@ -532,6 +530,19 @@ NetEConst* NetEBComp::eval_gteq_()
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* Compare with a real value. Do it as double precision. */
|
||||
if (right_->expr_type() == IVL_VT_REAL) {
|
||||
NetECReal*tmp = dynamic_cast<NetECReal*>(right_);
|
||||
if (tmp == 0)
|
||||
return 0;
|
||||
|
||||
double rr = tmp->value().as_double();
|
||||
double ll = lv.has_sign()? lv.as_long() : lv.as_ulong();
|
||||
|
||||
verinum result ((ll >= rr)? verinum::V1 : verinum::V0, 1, true);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
/* Now go on to the normal test of the values. */
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
@@ -550,73 +561,8 @@ NetEConst* NetEBComp::eval_gteq_()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Evaluate <A>==<B> or <A>!=<B>. The equality operator checks all the
|
||||
* bits and returns true(false) if there are any bits in the vector
|
||||
* that are defined (0 or 1) and different. If all the defined bits
|
||||
* are equal, but there are are x/z bits, then the situation is
|
||||
* ambiguous so the result is x.
|
||||
*/
|
||||
NetEConst* NetEBComp::eval_eqeq_real_(NetExpr*le, NetExpr*ri, bool ne_flag)
|
||||
{
|
||||
NetEConst*vtmp;
|
||||
NetECReal*rtmp;
|
||||
double lv, rv;
|
||||
|
||||
switch (le->expr_type()) {
|
||||
case IVL_VT_REAL:
|
||||
rtmp = dynamic_cast<NetECReal*> (le);
|
||||
if (rtmp == 0) return 0;
|
||||
lv = rtmp->value().as_double();
|
||||
break;
|
||||
|
||||
case IVL_VT_LOGIC:
|
||||
case IVL_VT_BOOL:
|
||||
vtmp = dynamic_cast<NetEConst*> (le);
|
||||
if (vtmp == 0) return 0;
|
||||
lv = vtmp->value().as_double();
|
||||
break;
|
||||
|
||||
default:
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Unexpected expression type? " << le->expr_type() << endl;
|
||||
assert(0);
|
||||
}
|
||||
|
||||
switch (ri->expr_type()) {
|
||||
case IVL_VT_REAL:
|
||||
rtmp = dynamic_cast<NetECReal*> (ri);
|
||||
if (rtmp == 0) return 0;
|
||||
rv = rtmp->value().as_double();
|
||||
break;
|
||||
|
||||
case IVL_VT_LOGIC:
|
||||
case IVL_VT_BOOL:
|
||||
vtmp = dynamic_cast<NetEConst*> (ri);
|
||||
if (vtmp == 0) return 0;
|
||||
rv = vtmp->value().as_double();
|
||||
break;
|
||||
|
||||
default:
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Unexpected expression type? " << ri->expr_type() << endl;
|
||||
assert(0);
|
||||
}
|
||||
|
||||
verinum result(((lv == rv) ^ ne_flag) ? verinum::V1 : verinum::V0, 1);
|
||||
vtmp = new NetEConst(result);
|
||||
vtmp->set_line(*this);
|
||||
|
||||
return vtmp;
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
|
||||
{
|
||||
if (right_->expr_type() == IVL_VT_REAL)
|
||||
return eval_eqeq_real_(right_, left_, ne_flag);
|
||||
if (left_->expr_type() == IVL_VT_REAL)
|
||||
return eval_eqeq_real_(right_, left_, ne_flag);
|
||||
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
@@ -635,14 +581,11 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
|
||||
|
||||
for (unsigned idx = 0 ; idx < top ; idx += 1) {
|
||||
|
||||
bool x_bit_present = false;
|
||||
|
||||
switch (lv.get(idx)) {
|
||||
|
||||
case verinum::Vx:
|
||||
case verinum::Vz:
|
||||
res = verinum::Vx;
|
||||
x_bit_present = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -654,20 +597,17 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
|
||||
case verinum::Vx:
|
||||
case verinum::Vz:
|
||||
res = verinum::Vx;
|
||||
x_bit_present = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (x_bit_present)
|
||||
continue;
|
||||
|
||||
if (rv.get(idx) != lv.get(idx)) {
|
||||
res = ne_res;
|
||||
if (res == verinum::Vx)
|
||||
break;
|
||||
}
|
||||
|
||||
if (rv.get(idx) != lv.get(idx))
|
||||
res = ne_res;
|
||||
}
|
||||
|
||||
if (res != verinum::Vx) {
|
||||
@@ -826,9 +766,9 @@ NetExpr* NetEBDiv::eval_tree(int prune_to_width)
|
||||
|
||||
verireal lval = lc->value();
|
||||
|
||||
if (NetECReal*rcr = dynamic_cast<NetECReal*>(right_)) {
|
||||
if (NetECReal*rc = dynamic_cast<NetECReal*>(right_)) {
|
||||
NetECReal*tmp = 0;
|
||||
verireal rval = rcr->value();
|
||||
verireal rval = rc->value();
|
||||
|
||||
switch (op_) {
|
||||
case '/':
|
||||
@@ -871,10 +811,8 @@ NetExpr* NetEBDiv::eval_tree(int prune_to_width)
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
if (rc == 0) return 0;
|
||||
|
||||
// Make sure the expression is evaluated at the
|
||||
// expression width.
|
||||
verinum lval = pad_to_width(lc->value(), expr_width());
|
||||
verinum rval = pad_to_width(rc->value(), expr_width());
|
||||
verinum lval = lc->value();
|
||||
verinum rval = rc->value();
|
||||
|
||||
NetExpr*tmp = 0;
|
||||
switch (op_) {
|
||||
@@ -1215,11 +1153,6 @@ NetEConst* NetEConcat::eval_tree(int prune_to_width)
|
||||
val = verinum(val.as_string());
|
||||
}
|
||||
|
||||
// Normally, concatenations are unsigned. However, the
|
||||
// $signed() function works by marking the expression as
|
||||
// signed, so we really have to check.
|
||||
val.has_sign( this->has_sign() );
|
||||
|
||||
NetEConst*res = new NetEConst(val);
|
||||
res->set_width(val.len());
|
||||
return res;
|
||||
@@ -1406,7 +1339,7 @@ NetExpr* NetETernary::eval_tree(int prune_to_width)
|
||||
case C_0:
|
||||
eval_expr(false_val_);
|
||||
if (debug_eval_tree) {
|
||||
|
||||
|
||||
cerr << get_fileline() << ": debug: Evaluate ternary with "
|
||||
<< "constant condition value: ";
|
||||
print_ternary_cond(cond_);
|
||||
@@ -1604,7 +1537,6 @@ NetEConst* NetEUReduce::eval_tree(int prune_to_width)
|
||||
|
||||
verinum val = rval->value();
|
||||
verinum::V res;
|
||||
bool invert = false;
|
||||
|
||||
switch (op_) {
|
||||
|
||||
@@ -1633,8 +1565,6 @@ NetEConst* NetEUReduce::eval_tree(int prune_to_width)
|
||||
break;
|
||||
}
|
||||
|
||||
case 'A':
|
||||
invert = true;
|
||||
case '&': {
|
||||
res = verinum::V1;
|
||||
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
|
||||
@@ -1642,8 +1572,6 @@ NetEConst* NetEUReduce::eval_tree(int prune_to_width)
|
||||
break;
|
||||
}
|
||||
|
||||
case 'N':
|
||||
invert = true;
|
||||
case '|': {
|
||||
res = verinum::V0;
|
||||
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
|
||||
@@ -1651,8 +1579,6 @@ NetEConst* NetEUReduce::eval_tree(int prune_to_width)
|
||||
break;
|
||||
}
|
||||
|
||||
case 'X':
|
||||
invert = true;
|
||||
case '^': {
|
||||
/* Reduction XOR. */
|
||||
unsigned ones = 0, unknown = 0;
|
||||
@@ -1668,321 +1594,16 @@ NetEConst* NetEUReduce::eval_tree(int prune_to_width)
|
||||
break;
|
||||
}
|
||||
|
||||
if (unknown) res = verinum::Vx;
|
||||
else if (ones%2) res = verinum::V1;
|
||||
else res = verinum::V0;
|
||||
break;
|
||||
if (unknown)
|
||||
return new NetEConst(verinum(verinum::Vx,1,true));
|
||||
if (ones%2)
|
||||
return new NetEConst(verinum(verinum::V1,1,true));
|
||||
return new NetEConst(verinum(verinum::V0,1,true));
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (invert) res = ~res;
|
||||
return new NetEConst(verinum(res, 1));
|
||||
}
|
||||
|
||||
NetExpr* evaluate_clog2(NetExpr*&arg_)
|
||||
{
|
||||
eval_expr(arg_);
|
||||
NetEConst*tmpi = dynamic_cast<NetEConst *>(arg_);
|
||||
NetECReal*tmpr = dynamic_cast<NetECReal *>(arg_);
|
||||
if (tmpi || tmpr) {
|
||||
verinum arg;
|
||||
if (tmpi) {
|
||||
arg = tmpi->value();
|
||||
} else {
|
||||
arg = verinum(tmpr->value().as_double(), true);
|
||||
}
|
||||
|
||||
/* If we have an x in the verinum we return 'bx. */
|
||||
if (!arg.is_defined()) {
|
||||
verinum tmp (verinum::Vx, integer_width);
|
||||
tmp.has_sign(true);
|
||||
NetEConst*rtn = new NetEConst(tmp);
|
||||
return rtn;
|
||||
}
|
||||
|
||||
bool is_neg = false;
|
||||
uint64_t res = 0;
|
||||
if (arg.is_negative()) {
|
||||
is_neg = true;
|
||||
// If the length is not defined, then work with
|
||||
// the trimmed version of the number.
|
||||
if (! arg.has_len())
|
||||
arg = trim_vnum(arg);
|
||||
}
|
||||
arg.has_sign(false); // $unsigned()
|
||||
|
||||
if (!arg.is_zero()) {
|
||||
arg = arg - verinum((uint64_t)1, 1);
|
||||
while (!arg.is_zero()) {
|
||||
res += 1;
|
||||
arg = arg >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_neg && res < integer_width)
|
||||
res = integer_width;
|
||||
|
||||
verinum tmp (res, integer_width);
|
||||
NetEConst*rtn = new NetEConst(tmp);
|
||||
return rtn;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr* evaluate_math_one_arg(NetExpr*&arg_, const char*name)
|
||||
{
|
||||
eval_expr(arg_);
|
||||
NetEConst*tmpi = dynamic_cast<NetEConst *>(arg_);
|
||||
NetECReal*tmpr = dynamic_cast<NetECReal *>(arg_);
|
||||
if (tmpi || tmpr) {
|
||||
double arg;
|
||||
if (tmpi) {
|
||||
arg = tmpi->value().as_double();
|
||||
} else {
|
||||
arg = tmpr->value().as_double();
|
||||
}
|
||||
|
||||
if (strcmp(name, "$ln") == 0) {
|
||||
return new NetECReal(verireal(log(arg)));
|
||||
} else if (strcmp(name, "$log") == 0) {
|
||||
return new NetECReal(verireal(log10(arg)));
|
||||
} else if (strcmp(name, "$log10") == 0) {
|
||||
return new NetECReal(verireal(log10(arg)));
|
||||
} else if (strcmp(name, "$exp") == 0) {
|
||||
return new NetECReal(verireal(exp(arg)));
|
||||
} else if (strcmp(name, "$sqrt") == 0) {
|
||||
return new NetECReal(verireal(sqrt(arg)));
|
||||
} else if (strcmp(name, "$floor") == 0) {
|
||||
return new NetECReal(verireal(floor(arg)));
|
||||
} else if (strcmp(name, "$ceil") == 0) {
|
||||
return new NetECReal(verireal(ceil(arg)));
|
||||
} else if (strcmp(name, "$sin") == 0) {
|
||||
return new NetECReal(verireal(sin(arg)));
|
||||
} else if (strcmp(name, "$cos") == 0) {
|
||||
return new NetECReal(verireal(cos(arg)));
|
||||
} else if (strcmp(name, "$tan") == 0) {
|
||||
return new NetECReal(verireal(tan(arg)));
|
||||
} else if (strcmp(name, "$asin") == 0) {
|
||||
return new NetECReal(verireal(asin(arg)));
|
||||
} else if (strcmp(name, "$acos") == 0) {
|
||||
return new NetECReal(verireal(acos(arg)));
|
||||
} else if (strcmp(name, "$atan") == 0) {
|
||||
return new NetECReal(verireal(atan(arg)));
|
||||
} else if (strcmp(name, "$sinh") == 0) {
|
||||
return new NetECReal(verireal(sinh(arg)));
|
||||
} else if (strcmp(name, "$cosh") == 0) {
|
||||
return new NetECReal(verireal(cosh(arg)));
|
||||
} else if (strcmp(name, "$tanh") == 0) {
|
||||
return new NetECReal(verireal(tanh(arg)));
|
||||
} else if (strcmp(name, "$asinh") == 0) {
|
||||
return new NetECReal(verireal(asinh(arg)));
|
||||
} else if (strcmp(name, "$acosh") == 0) {
|
||||
return new NetECReal(verireal(acosh(arg)));
|
||||
} else if (strcmp(name, "$atanh") == 0) {
|
||||
return new NetECReal(verireal(atanh(arg)));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr* evaluate_math_two_args(NetExpr*&arg0_, NetExpr*&arg1_, const char*name)
|
||||
{
|
||||
eval_expr(arg0_);
|
||||
eval_expr(arg1_);
|
||||
NetEConst*tmpi0 = dynamic_cast<NetEConst *>(arg0_);
|
||||
NetECReal*tmpr0 = dynamic_cast<NetECReal *>(arg0_);
|
||||
NetEConst*tmpi1 = dynamic_cast<NetEConst *>(arg1_);
|
||||
NetECReal*tmpr1 = dynamic_cast<NetECReal *>(arg1_);
|
||||
if ((tmpi0 || tmpr0) && (tmpi1 || tmpr1)) {
|
||||
double arg0, arg1;
|
||||
if (tmpi0) {
|
||||
arg0 = tmpi0->value().as_double();
|
||||
} else {
|
||||
arg0 = tmpr0->value().as_double();
|
||||
}
|
||||
if (tmpi1) {
|
||||
arg1 = tmpi1->value().as_double();
|
||||
} else {
|
||||
arg1 = tmpr1->value().as_double();
|
||||
}
|
||||
|
||||
if (strcmp(name, "$pow") == 0) {
|
||||
return new NetECReal(verireal(pow(arg0, arg1)));
|
||||
} else if (strcmp(name, "$atan2") == 0) {
|
||||
return new NetECReal(verireal(atan2(arg0, arg1)));
|
||||
} else if (strcmp(name, "$hypot") == 0) {
|
||||
return new NetECReal(verireal(hypot(arg0, arg1)));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr* evaluate_abs(NetExpr*&arg_)
|
||||
{
|
||||
eval_expr(arg_);
|
||||
NetEConst*tmpi = dynamic_cast<NetEConst *>(arg_);
|
||||
if (tmpi) {
|
||||
verinum arg = tmpi->value();
|
||||
if (arg.is_negative()) {
|
||||
arg = v_not(arg) + verinum(1);
|
||||
}
|
||||
return new NetEConst(arg);
|
||||
}
|
||||
|
||||
NetECReal*tmpr = dynamic_cast<NetECReal *>(arg_);
|
||||
if (tmpr) {
|
||||
double arg = tmpr->value().as_double();
|
||||
return new NetECReal(verireal(fabs(arg)));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr* evaluate_min_max(NetExpr*&arg0_, NetExpr*&arg1_, const char*name)
|
||||
{
|
||||
eval_expr(arg0_);
|
||||
eval_expr(arg1_);
|
||||
NetEConst*tmpi0 = dynamic_cast<NetEConst *>(arg0_);
|
||||
NetECReal*tmpr0 = dynamic_cast<NetECReal *>(arg0_);
|
||||
NetEConst*tmpi1 = dynamic_cast<NetEConst *>(arg1_);
|
||||
NetECReal*tmpr1 = dynamic_cast<NetECReal *>(arg1_);
|
||||
if (tmpi0 && tmpi1) {
|
||||
verinum arg0 = tmpi0->value();
|
||||
verinum arg1 = tmpi1->value();
|
||||
if (strcmp(name, "$min") == 0) {
|
||||
return new NetEConst( arg0 < arg1 ? arg0 : arg1);
|
||||
} else if (strcmp(name, "$max") == 0) {
|
||||
return new NetEConst( arg0 < arg1 ? arg1 : arg0);
|
||||
}
|
||||
}
|
||||
|
||||
if ((tmpi0 || tmpr0) && (tmpi1 || tmpr1)) {
|
||||
double arg0, arg1;
|
||||
if (tmpi0) {
|
||||
arg0 = tmpi0->value().as_double();
|
||||
} else {
|
||||
arg0 = tmpr0->value().as_double();
|
||||
}
|
||||
if (tmpi1) {
|
||||
arg1 = tmpi1->value().as_double();
|
||||
} else {
|
||||
arg1 = tmpr1->value().as_double();
|
||||
}
|
||||
if (strcmp(name, "$min") == 0) {
|
||||
return new NetECReal(verireal(arg0 < arg1 ? arg0 : arg1));
|
||||
} else if (strcmp(name, "$max") == 0) {
|
||||
return new NetECReal(verireal(arg0 < arg1 ? arg1 : arg0));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr* NetESFunc::eval_tree(int prune_to_width)
|
||||
{
|
||||
/* If we are not targeting at least Verilog-2005, Verilog-AMS
|
||||
* or using the Icarus misc flag then we do not support these
|
||||
* functions as constant. */
|
||||
if (generation_flag < GN_VER2005 &&
|
||||
!gn_icarus_misc_flag && !gn_verilog_ams_flag) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char*nm = name();
|
||||
NetExpr*rtn = 0;
|
||||
/* Only $clog2 and the builtin mathematical functions can
|
||||
* be a constant system function. */
|
||||
if (strcmp(nm, "$clog2") == 0 ||
|
||||
strcmp(nm, "$ln") == 0 ||
|
||||
strcmp(nm, "$log10") == 0 ||
|
||||
strcmp(nm, "$exp") == 0 ||
|
||||
strcmp(nm, "$sqrt") == 0 ||
|
||||
strcmp(nm, "$floor") == 0 ||
|
||||
strcmp(nm, "$ceil") == 0 ||
|
||||
strcmp(nm, "$sin") == 0 ||
|
||||
strcmp(nm, "$cos") == 0 ||
|
||||
strcmp(nm, "$tan") == 0 ||
|
||||
strcmp(nm, "$asin") == 0 ||
|
||||
strcmp(nm, "$acos") == 0 ||
|
||||
strcmp(nm, "$atan") == 0 ||
|
||||
strcmp(nm, "$sinh") == 0 ||
|
||||
strcmp(nm, "$cosh") == 0 ||
|
||||
strcmp(nm, "$tanh") == 0 ||
|
||||
strcmp(nm, "$asinh") == 0 ||
|
||||
strcmp(nm, "$acosh") == 0 ||
|
||||
strcmp(nm, "$atanh") == 0) {
|
||||
if (nparms() != 1 || parm(0) == 0) {
|
||||
cerr << get_fileline() << ": error: " << nm
|
||||
<< " takes a single argument." << endl;
|
||||
return 0;
|
||||
}
|
||||
NetExpr*arg = parm(0)->dup_expr();
|
||||
if (strcmp(nm, "$clog2") == 0) {
|
||||
rtn = evaluate_clog2(arg);
|
||||
} else {
|
||||
rtn = evaluate_math_one_arg(arg, nm);
|
||||
}
|
||||
delete arg;
|
||||
}
|
||||
|
||||
if (strcmp(nm, "$pow") == 0 ||
|
||||
strcmp(nm, "$atan2") == 0 ||
|
||||
strcmp(nm, "$hypot") == 0) {
|
||||
if (nparms() != 2 || parm(0) == 0 || parm(1) == 0) {
|
||||
cerr << get_fileline() << ": error: " << nm
|
||||
<< " takes two arguments." << endl;
|
||||
return 0;
|
||||
}
|
||||
NetExpr*arg0 = parm(0)->dup_expr();
|
||||
NetExpr*arg1 = parm(1)->dup_expr();
|
||||
rtn = evaluate_math_two_args(arg0, arg1, nm);
|
||||
delete arg0;
|
||||
delete arg1;
|
||||
}
|
||||
|
||||
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
|
||||
(strcmp(nm, "$log") == 0 || strcmp(nm, "$abs") == 0)) {
|
||||
if (nparms() != 1 || parm(0) == 0) {
|
||||
cerr << get_fileline() << ": error: " << nm
|
||||
<< " takes a single argument." << endl;
|
||||
return 0;
|
||||
}
|
||||
NetExpr*arg = parm(0)->dup_expr();
|
||||
if (strcmp(nm, "$log") == 0) {
|
||||
rtn = evaluate_math_one_arg(arg, nm);
|
||||
} else {
|
||||
rtn = evaluate_abs(arg);
|
||||
}
|
||||
delete arg;
|
||||
}
|
||||
|
||||
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
|
||||
(strcmp(nm, "$min") == 0 || strcmp(nm, "$max") == 0)) {
|
||||
if (nparms() != 2 || parm(0) == 0 || parm(1) == 0) {
|
||||
cerr << get_fileline() << ": error: " << nm
|
||||
<< " takes two arguments." << endl;
|
||||
return 0;
|
||||
}
|
||||
NetExpr*arg0 = parm(0)->dup_expr();
|
||||
NetExpr*arg1 = parm(1)->dup_expr();
|
||||
rtn = evaluate_min_max(arg0, arg1, nm);
|
||||
delete arg0;
|
||||
delete arg1;
|
||||
}
|
||||
|
||||
if (rtn != 0) {
|
||||
rtn->set_line(*this);
|
||||
if (debug_eval_tree) {
|
||||
cerr << get_fileline() << ": debug: Evaluate constant "
|
||||
<< nm << "." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
*
|
||||
* The POST_MAP compiler directive causes the GSR manipulations
|
||||
* included in the test bench to be compiled in, to simulate the chip
|
||||
* startup. Other than that, the test bench runs the post-map design
|
||||
* startup. Other then that, the test bench runs the post-map design
|
||||
* the same way the pre-synthesis design works.
|
||||
*
|
||||
* Run this design with the command:
|
||||
|
||||
+169
-398
@@ -20,56 +20,56 @@
|
||||
# include "config.h"
|
||||
# include "compiler.h"
|
||||
|
||||
# include <cstdlib>
|
||||
# include <iostream>
|
||||
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
static NetNet* convert_to_real_const(Design*des, NetScope*scope, NetEConst*expr)
|
||||
NetNet* convert_to_real_const(Design*des, NetExpr*expr, NetExpr*obj)
|
||||
{
|
||||
verireal vrl(expr->value().as_double());
|
||||
NetECReal rlval(vrl);
|
||||
NetNet* sig = rlval.synthesize(des, scope);
|
||||
NetNet* sig;
|
||||
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
|
||||
verireal vrl(tmp->value().as_double());
|
||||
NetECReal rlval(vrl);
|
||||
sig = rlval.synthesize(des);
|
||||
} else {
|
||||
cerr << obj->get_fileline() << ": sorry: Cannot convert "
|
||||
"bit based value (" << *expr << ") to real." << endl;
|
||||
des->errors += 1;
|
||||
sig = 0;
|
||||
}
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
/* Note that lsig, rsig and real_args are references. */
|
||||
static bool process_binary_args(Design*des, NetScope*scope,
|
||||
NetExpr*left, NetExpr*right,
|
||||
NetNet*&lsig, NetNet*&rsig, bool&real_args,
|
||||
NetExpr*obj)
|
||||
bool process_binary_args(Design*des, NetExpr*left, NetExpr*right,
|
||||
NetNet*&lsig, NetNet*&rsig, bool&real_args,
|
||||
NetExpr*obj)
|
||||
{
|
||||
if (left->expr_type() == IVL_VT_REAL ||
|
||||
right->expr_type() == IVL_VT_REAL) {
|
||||
real_args = true;
|
||||
|
||||
/* Convert the arguments to real. Handle the special
|
||||
cases of constants, which can be converted more directly. */
|
||||
/* Currently we will have a runtime assert if both expressions
|
||||
are not real, though we can convert constants. */
|
||||
if (left->expr_type() == IVL_VT_REAL) {
|
||||
lsig = left->synthesize(des, scope);
|
||||
} else if (NetEConst*tmpc = dynamic_cast<NetEConst*> (left)) {
|
||||
lsig = convert_to_real_const(des, scope, tmpc);
|
||||
lsig = left->synthesize(des);
|
||||
} else {
|
||||
NetNet*tmp = left->synthesize(des, scope);
|
||||
lsig = cast_to_real(des, scope, tmp);
|
||||
lsig = convert_to_real_const(des, left, obj);
|
||||
}
|
||||
|
||||
if (right->expr_type() == IVL_VT_REAL) {
|
||||
rsig = right->synthesize(des, scope);
|
||||
} else if (NetEConst*tmpc = dynamic_cast<NetEConst*> (right)) {
|
||||
rsig = convert_to_real_const(des, scope, tmpc);
|
||||
rsig = right->synthesize(des);
|
||||
} else {
|
||||
NetNet*tmp = right->synthesize(des, scope);
|
||||
rsig = cast_to_real(des, scope, tmp);
|
||||
rsig = convert_to_real_const(des, right, obj);
|
||||
}
|
||||
|
||||
} else {
|
||||
real_args = false;
|
||||
lsig = left->synthesize(des, scope);
|
||||
rsig = right->synthesize(des, scope);
|
||||
lsig = left->synthesize(des);
|
||||
rsig = right->synthesize(des);
|
||||
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ static bool process_binary_args(Design*des, NetScope*scope,
|
||||
else return false;
|
||||
}
|
||||
|
||||
NetNet* NetExpr::synthesize(Design*des, NetScope*scope)
|
||||
NetNet* NetExpr::synthesize(Design*des)
|
||||
{
|
||||
cerr << get_fileline() << ": internal error: cannot synthesize expression: "
|
||||
<< *this << endl;
|
||||
@@ -88,35 +88,25 @@ NetNet* NetExpr::synthesize(Design*des, NetScope*scope)
|
||||
/*
|
||||
* Make an LPM_ADD_SUB device from addition operators.
|
||||
*/
|
||||
NetNet* NetEBAdd::synthesize(Design*des, NetScope*scope)
|
||||
NetNet* NetEBAdd::synthesize(Design*des)
|
||||
{
|
||||
ivl_assert(*this, (op()=='+') || (op()=='-'));
|
||||
assert((op()=='+') || (op()=='-'));
|
||||
|
||||
NetNet *lsig=0, *rsig=0;
|
||||
bool real_args=false;
|
||||
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
|
||||
if (process_binary_args(des, left_, right_, lsig, rsig,
|
||||
real_args, this)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ivl_assert(*this, expr_width() >= lsig->vector_width());
|
||||
ivl_assert(*this, expr_width() >= rsig->vector_width());
|
||||
assert(expr_width() >= lsig->vector_width());
|
||||
assert(expr_width() >= rsig->vector_width());
|
||||
|
||||
unsigned width;
|
||||
if (expr_type() == IVL_VT_REAL) {
|
||||
width = 1;
|
||||
if (lsig->data_type() != IVL_VT_REAL)
|
||||
lsig = cast_to_real(des, scope, lsig);
|
||||
if (rsig->data_type() != IVL_VT_REAL)
|
||||
rsig = cast_to_real(des, scope, rsig);
|
||||
lsig = pad_to_width(des, lsig, expr_width());
|
||||
rsig = pad_to_width(des, rsig, expr_width());
|
||||
|
||||
} else {
|
||||
lsig = pad_to_width(des, lsig, expr_width(), *this);
|
||||
rsig = pad_to_width(des, rsig, expr_width(), *this);
|
||||
|
||||
assert(lsig->vector_width() == rsig->vector_width());
|
||||
width=lsig->vector_width();
|
||||
}
|
||||
assert(lsig->vector_width() == rsig->vector_width());
|
||||
unsigned width=lsig->vector_width();
|
||||
|
||||
perm_string path = lsig->scope()->local_symbol();
|
||||
NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, width);
|
||||
@@ -148,10 +138,10 @@ NetNet* NetEBAdd::synthesize(Design*des, NetScope*scope)
|
||||
* signals, then just connect a single gate to each bit of the vector
|
||||
* of the expression.
|
||||
*/
|
||||
NetNet* NetEBBits::synthesize(Design*des, NetScope*scope)
|
||||
NetNet* NetEBBits::synthesize(Design*des)
|
||||
{
|
||||
NetNet*lsig = left_->synthesize(des, scope);
|
||||
NetNet*rsig = right_->synthesize(des, scope);
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
|
||||
if (lsig == 0 || rsig == 0) return 0;
|
||||
|
||||
@@ -164,11 +154,14 @@ NetNet* NetEBBits::synthesize(Design*des, NetScope*scope)
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned width = expr_width();
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
|
||||
unsigned width = lsig->vector_width();
|
||||
if (rsig->vector_width() > width) width = rsig->vector_width();
|
||||
|
||||
lsig = pad_to_width(des, lsig, width, *this);
|
||||
rsig = pad_to_width(des, rsig, width, *this);
|
||||
lsig = pad_to_width(des, lsig, width);
|
||||
rsig = pad_to_width(des, rsig, width);
|
||||
|
||||
assert(lsig->vector_width() == rsig->vector_width());
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
@@ -212,13 +205,13 @@ NetNet* NetEBBits::synthesize(Design*des, NetScope*scope)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEBComp::synthesize(Design*des, NetScope*scope)
|
||||
NetNet* NetEBComp::synthesize(Design*des)
|
||||
{
|
||||
|
||||
NetNet *lsig=0, *rsig=0;
|
||||
unsigned width;
|
||||
bool real_args=false;
|
||||
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
|
||||
if (process_binary_args(des, left_, right_, lsig, rsig,
|
||||
real_args, this)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -229,58 +222,24 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope)
|
||||
width = lsig->vector_width();
|
||||
if (rsig->vector_width() > width) width = rsig->vector_width();
|
||||
|
||||
if (lsig->get_signed())
|
||||
lsig = pad_to_width_signed(des, lsig, width, *this);
|
||||
else
|
||||
lsig = pad_to_width(des, lsig, width, *this);
|
||||
if (rsig->get_signed())
|
||||
rsig = pad_to_width_signed(des, rsig, width, *this);
|
||||
else
|
||||
rsig = pad_to_width(des, rsig, width, *this);
|
||||
lsig = pad_to_width(des, lsig, width);
|
||||
rsig = pad_to_width(des, rsig, width);
|
||||
}
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
osig->set_line(*this);
|
||||
osig->local_flag(true);
|
||||
osig->data_type(IVL_VT_LOGIC);
|
||||
|
||||
// Test if the comparison is signed.
|
||||
//
|
||||
// Note 1: This is not the same as asking if the result is
|
||||
// signed. In fact, the result will typically be UNsigned. The
|
||||
// decision to make the comparison signed depends on the
|
||||
// operand expressions.
|
||||
//
|
||||
// Note 2: The operand expressions may be signed even if the
|
||||
// sig that comes out of synthesis is unsigned. The $signed()
|
||||
// function marks the expression but doesn't change the
|
||||
// underlying signals.
|
||||
bool signed_compare = left_->has_sign() && right_->has_sign();
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Comparison (" << op_ << ")"
|
||||
<< " is " << (signed_compare? "signed" : "unsigned")
|
||||
<< endl;
|
||||
cerr << get_fileline() << ": : lsig is "
|
||||
<< (lsig->get_signed()? "signed" : "unsigned")
|
||||
<< " rsig is " << (rsig->get_signed()? "signed" : "unsigned")
|
||||
<< endl;
|
||||
}
|
||||
|
||||
if (op_ == 'E' || op_ == 'N') {
|
||||
NetCaseCmp*gate = new NetCaseCmp(scope, scope->local_symbol(),
|
||||
width, op_=='E'?true:false);
|
||||
gate->set_line(*this);
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
connect(gate->pin(1), lsig->pin(0));
|
||||
connect(gate->pin(2), rsig->pin(0));
|
||||
des->add_node(gate);
|
||||
return osig;
|
||||
}
|
||||
bool signed_compare = lsig->get_signed() && rsig->get_signed();
|
||||
|
||||
/* Handle the special case of a single bit equality
|
||||
operation. Make an XNOR gate instead of a comparator. */
|
||||
if ((width == 1) && (op_ == 'e') && !real_args) {
|
||||
if ((width == 1) && ((op_ == 'e') || (op_ == 'E')) && !real_args) {
|
||||
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
|
||||
3, NetLogic::XNOR, 1);
|
||||
gate->set_line(*this);
|
||||
@@ -294,7 +253,7 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope)
|
||||
/* Handle the special case of a single bit inequality
|
||||
operation. This is similar to single bit equality, but uses
|
||||
an XOR instead of an XNOR gate. */
|
||||
if ((width == 1) && (op_ == 'n') && !real_args) {
|
||||
if ((width == 1) && ((op_ == 'n') || (op_ == 'N')) && !real_args) {
|
||||
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
|
||||
3, NetLogic::XOR, 1);
|
||||
gate->set_line(*this);
|
||||
@@ -362,12 +321,12 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEBPow::synthesize(Design*des, NetScope*scope)
|
||||
NetNet* NetEBPow::synthesize(Design*des)
|
||||
{
|
||||
NetNet *lsig=0, *rsig=0;
|
||||
unsigned width;
|
||||
bool real_args=false;
|
||||
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
|
||||
if (process_binary_args(des, left_, right_, lsig, rsig,
|
||||
real_args, this)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -375,6 +334,9 @@ NetNet* NetEBPow::synthesize(Design*des, NetScope*scope)
|
||||
if (real_args) width = 1;
|
||||
else width = expr_width();
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
|
||||
NetPow*powr = new NetPow(scope, scope->local_symbol(), width,
|
||||
lsig->vector_width(),
|
||||
rsig->vector_width());
|
||||
@@ -397,12 +359,12 @@ NetNet* NetEBPow::synthesize(Design*des, NetScope*scope)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEBMult::synthesize(Design*des, NetScope*scope)
|
||||
NetNet* NetEBMult::synthesize(Design*des)
|
||||
{
|
||||
NetNet *lsig=0, *rsig=0;
|
||||
unsigned width;
|
||||
bool real_args=false;
|
||||
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
|
||||
if (process_binary_args(des, left_, right_, lsig, rsig,
|
||||
real_args, this)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -410,6 +372,9 @@ NetNet* NetEBMult::synthesize(Design*des, NetScope*scope)
|
||||
if (real_args) width = 1;
|
||||
else width = expr_width();
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
|
||||
NetMult*mult = new NetMult(scope, scope->local_symbol(),
|
||||
width,
|
||||
lsig->vector_width(),
|
||||
@@ -433,12 +398,12 @@ NetNet* NetEBMult::synthesize(Design*des, NetScope*scope)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEBDiv::synthesize(Design*des, NetScope*scope)
|
||||
NetNet* NetEBDiv::synthesize(Design*des)
|
||||
{
|
||||
NetNet *lsig=0, *rsig=0;
|
||||
unsigned width;
|
||||
bool real_args=false;
|
||||
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
|
||||
if (process_binary_args(des, left_, right_, lsig, rsig,
|
||||
real_args, this)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -446,11 +411,12 @@ NetNet* NetEBDiv::synthesize(Design*des, NetScope*scope)
|
||||
if (real_args) width = 1;
|
||||
else width = expr_width();
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, width);
|
||||
osig->set_line(*this);
|
||||
osig->data_type(lsig->data_type());
|
||||
osig->set_signed(has_sign());
|
||||
osig->local_flag(true);
|
||||
|
||||
switch (op()) {
|
||||
@@ -461,7 +427,6 @@ NetNet* NetEBDiv::synthesize(Design*des, NetScope*scope)
|
||||
lsig->vector_width(),
|
||||
rsig->vector_width());
|
||||
div->set_line(*this);
|
||||
div->set_signed(has_sign());
|
||||
des->add_node(div);
|
||||
|
||||
connect(div->pin_DataA(), lsig->pin(0));
|
||||
@@ -484,7 +449,6 @@ NetNet* NetEBDiv::synthesize(Design*des, NetScope*scope)
|
||||
lsig->vector_width(),
|
||||
rsig->vector_width());
|
||||
div->set_line(*this);
|
||||
div->set_signed(has_sign());
|
||||
des->add_node(div);
|
||||
|
||||
connect(div->pin_DataA(), lsig->pin(0));
|
||||
@@ -495,7 +459,7 @@ NetNet* NetEBDiv::synthesize(Design*des, NetScope*scope)
|
||||
|
||||
default: {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "NetEBDiv has unexpected op() code: "
|
||||
<< "NetEBDiv has unexpeced op() code: "
|
||||
<< op() << endl;
|
||||
des->errors += 1;
|
||||
|
||||
@@ -507,10 +471,10 @@ NetNet* NetEBDiv::synthesize(Design*des, NetScope*scope)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEBLogic::synthesize(Design*des, NetScope*scope)
|
||||
NetNet* NetEBLogic::synthesize(Design*des)
|
||||
{
|
||||
NetNet*lsig = left_->synthesize(des, scope);
|
||||
NetNet*rsig = right_->synthesize(des, scope);
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
|
||||
if (lsig == 0 || rsig == 0) return 0;
|
||||
|
||||
@@ -523,6 +487,9 @@ NetNet* NetEBLogic::synthesize(Design*des, NetScope*scope)
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
osig->data_type(expr_type());
|
||||
@@ -584,11 +551,11 @@ NetNet* NetEBLogic::synthesize(Design*des, NetScope*scope)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEBShift::synthesize(Design*des, NetScope*scope)
|
||||
NetNet* NetEBShift::synthesize(Design*des)
|
||||
{
|
||||
eval_expr(right_);
|
||||
|
||||
NetNet*lsig = left_->synthesize(des, scope);
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
|
||||
if (lsig == 0) return 0;
|
||||
|
||||
@@ -601,8 +568,10 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope)
|
||||
return 0;
|
||||
}
|
||||
|
||||
const bool right_flag = op_ == 'r' || op_ == 'R';
|
||||
const bool signed_flag = op_ == 'R';
|
||||
bool right_flag = op_ == 'r' || op_ == 'R';
|
||||
bool signed_flag = op_ == 'R';
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
|
||||
/* Detect the special case where the shift amount is
|
||||
constant. Evaluate the shift amount, and simply reconnect
|
||||
@@ -611,7 +580,7 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope)
|
||||
verinum shift_v = rcon->value();
|
||||
long shift = shift_v.as_long();
|
||||
|
||||
if (right_flag)
|
||||
if (op() == 'r')
|
||||
shift = 0-shift;
|
||||
|
||||
if (shift == 0)
|
||||
@@ -624,13 +593,34 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope)
|
||||
|
||||
// ushift is the amount of pad created by the shift.
|
||||
unsigned long ushift = shift>=0? shift : -shift;
|
||||
ivl_assert(*this, ushift < osig->vector_width());
|
||||
if (ushift > osig->vector_width())
|
||||
ushift = osig->vector_width();
|
||||
|
||||
// part_width is the bits of the vector that survive the shift.
|
||||
unsigned long part_width = osig->vector_width() - ushift;
|
||||
|
||||
// Create a part select to reduce the width of the lsig
|
||||
// to the amount left by the shift.
|
||||
verinum znum (verinum::V0, ushift, true);
|
||||
NetConst*zcon = new NetConst(scope, scope->local_symbol(),
|
||||
znum);
|
||||
des->add_node(zcon);
|
||||
|
||||
/* Detect the special case that the shift is the size of
|
||||
the whole expression. Simply connect the pad to the
|
||||
osig and escape. */
|
||||
if (ushift >= osig->vector_width()) {
|
||||
connect(zcon->pin(0), osig->pin(0));
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet*zsig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, znum.len());
|
||||
zsig->data_type(osig->data_type());
|
||||
zsig->local_flag(true);
|
||||
zsig->set_line(*this);
|
||||
connect(zcon->pin(0), zsig->pin(0));
|
||||
|
||||
/* Create a part select to reduce the width of the lsig
|
||||
to the amount left by the shift. */
|
||||
NetPartSelect*psel = new NetPartSelect(lsig, shift<0? ushift : 0,
|
||||
part_width,
|
||||
NetPartSelect::VP);
|
||||
@@ -643,34 +633,6 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope)
|
||||
psig->set_line(*this);
|
||||
connect(psig->pin(0), psel->pin(0));
|
||||
|
||||
// Handle the special case of a signed right shift. In
|
||||
// this case, use the NetSignExtend device to pad the
|
||||
// result to the desired width.
|
||||
if (signed_flag && right_flag) {
|
||||
NetSignExtend*pad = new NetSignExtend(scope, scope->local_symbol(),
|
||||
osig->vector_width());
|
||||
des->add_node(pad);
|
||||
pad->set_line(*this);
|
||||
|
||||
connect(pad->pin(1), psig->pin(0));
|
||||
connect(pad->pin(0), osig->pin(0));
|
||||
return osig;
|
||||
}
|
||||
|
||||
// Other cases are handled by zero-extending on the
|
||||
// proper end.
|
||||
verinum znum (verinum::V0, ushift, true);
|
||||
NetConst*zcon = new NetConst(scope, scope->local_symbol(),
|
||||
znum);
|
||||
des->add_node(zcon);
|
||||
|
||||
NetNet*zsig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, znum.len());
|
||||
zsig->data_type(osig->data_type());
|
||||
zsig->local_flag(true);
|
||||
zsig->set_line(*this);
|
||||
connect(zcon->pin(0), zsig->pin(0));
|
||||
|
||||
NetConcat*ccat = new NetConcat(scope, scope->local_symbol(),
|
||||
osig->vector_width(), 2);
|
||||
ccat->set_line(*this);
|
||||
@@ -690,7 +652,7 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet*rsig = right_->synthesize(des, scope);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
|
||||
if (rsig == 0) return 0;
|
||||
|
||||
@@ -716,13 +678,13 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEConcat::synthesize(Design*des, NetScope*scope)
|
||||
NetNet* NetEConcat::synthesize(Design*des)
|
||||
{
|
||||
/* First, synthesize the operands. */
|
||||
NetNet**tmp = new NetNet*[parms_.count()];
|
||||
bool flag = true;
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
tmp[idx] = parms_[idx]->synthesize(des, scope);
|
||||
tmp[idx] = parms_[idx]->synthesize(des);
|
||||
if (tmp[idx] == 0)
|
||||
flag = false;
|
||||
}
|
||||
@@ -730,7 +692,9 @@ NetNet* NetEConcat::synthesize(Design*des, NetScope*scope)
|
||||
if (flag == false)
|
||||
return 0;
|
||||
|
||||
ivl_assert(*this, tmp[0]);
|
||||
assert(tmp[0]);
|
||||
NetScope*scope = tmp[0]->scope();
|
||||
assert(scope);
|
||||
|
||||
/* Make a NetNet object to carry the output vector. */
|
||||
perm_string path = scope->local_symbol();
|
||||
@@ -745,54 +709,45 @@ NetNet* NetEConcat::synthesize(Design*des, NetScope*scope)
|
||||
des->add_node(concat);
|
||||
connect(concat->pin(0), osig->pin(0));
|
||||
|
||||
unsigned count_input_width = 0;
|
||||
unsigned cur_pin = 1;
|
||||
for (unsigned rpt = 0; rpt < repeat(); rpt += 1) {
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
unsigned concat_item = parms_.count()-idx-1;
|
||||
ivl_assert(*this, tmp[concat_item]);
|
||||
connect(concat->pin(cur_pin), tmp[concat_item]->pin(0));
|
||||
connect(concat->pin(cur_pin), tmp[parms_.count()-idx-1]->pin(0));
|
||||
cur_pin += 1;
|
||||
count_input_width += tmp[concat_item]->vector_width();
|
||||
}
|
||||
}
|
||||
|
||||
if (count_input_width != osig->vector_width()) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "NetEConcat input width = " << count_input_width
|
||||
<< ", expecting " << osig->vector_width()
|
||||
<< " (repeat=" << repeat() << ")" << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
delete[]tmp;
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEConst::synthesize(Design*des, NetScope*scope)
|
||||
NetNet* NetEConst::synthesize(Design*des)
|
||||
{
|
||||
NetScope*scope = des->find_root_scope();
|
||||
assert(scope);
|
||||
|
||||
perm_string path = scope->local_symbol();
|
||||
unsigned width=expr_width();
|
||||
|
||||
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width);
|
||||
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width-1,0);
|
||||
osig->local_flag(true);
|
||||
osig->data_type(expr_type());
|
||||
osig->data_type(IVL_VT_LOGIC);
|
||||
osig->set_signed(has_sign());
|
||||
osig->set_line(*this);
|
||||
|
||||
NetConst*con = new NetConst(scope, scope->local_symbol(), value());
|
||||
des->add_node(con);
|
||||
con->set_line(*this);
|
||||
|
||||
connect(osig->pin(0), con->pin(0));
|
||||
|
||||
des->add_node(con);
|
||||
return osig;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a NetLiteral object to represent real valued constants.
|
||||
*/
|
||||
NetNet* NetECReal::synthesize(Design*des, NetScope*scope)
|
||||
NetNet* NetECReal::synthesize(Design*des)
|
||||
{
|
||||
NetScope*scope = des->find_root_scope();
|
||||
assert(scope);
|
||||
|
||||
perm_string path = scope->local_symbol();
|
||||
|
||||
NetNet*osig = new NetNet(scope, path, NetNet::WIRE, 1);
|
||||
@@ -813,9 +768,9 @@ NetNet* NetECReal::synthesize(Design*des, NetScope*scope)
|
||||
* The bitwise unary logic operator (there is only one) is turned
|
||||
* into discrete gates just as easily as the binary ones above.
|
||||
*/
|
||||
NetNet* NetEUBits::synthesize(Design*des, NetScope*scope)
|
||||
NetNet* NetEUBits::synthesize(Design*des)
|
||||
{
|
||||
NetNet*isig = expr_->synthesize(des, scope);
|
||||
NetNet*isig = expr_->synthesize(des);
|
||||
|
||||
if (isig == 0) return 0;
|
||||
|
||||
@@ -827,6 +782,9 @@ NetNet* NetEUBits::synthesize(Design*des, NetScope*scope)
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetScope*scope = isig->scope();
|
||||
assert(scope);
|
||||
|
||||
unsigned width = isig->vector_width();
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, width);
|
||||
@@ -852,56 +810,13 @@ NetNet* NetEUBits::synthesize(Design*des, NetScope*scope)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEUnary::synthesize(Design*des, NetScope*scope)
|
||||
NetNet* NetEUReduce::synthesize(Design*des)
|
||||
{
|
||||
if (op_ == '+')
|
||||
return expr_->synthesize(des, scope);
|
||||
|
||||
if (op_ == '-') {
|
||||
NetNet*sig = expr_->synthesize(des, scope);
|
||||
sig = sub_net_from(des, scope, 0, sig);
|
||||
return sig;
|
||||
}
|
||||
|
||||
if (op_ == 'm') {
|
||||
NetNet*sub = expr_->synthesize(des, scope);
|
||||
if (expr_->has_sign() == false)
|
||||
return sub;
|
||||
|
||||
NetNet*sig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, sub->vector_width());
|
||||
sig->set_line(*this);
|
||||
sig->local_flag(true);
|
||||
sig->data_type(sub->data_type());
|
||||
|
||||
NetAbs*tmp = new NetAbs(scope, scope->local_symbol(), sub->vector_width());
|
||||
des->add_node(tmp);
|
||||
tmp->set_line(*this);
|
||||
|
||||
connect(tmp->pin(1), sub->pin(0));
|
||||
connect(tmp->pin(0), sig->pin(0));
|
||||
return sig;
|
||||
}
|
||||
|
||||
cerr << get_fileline() << ": iternal error: "
|
||||
<< "NetEUnary::synthesize cannot handle op_=" << op_ << endl;
|
||||
des->errors += 1;
|
||||
return expr_->synthesize(des, scope);
|
||||
}
|
||||
|
||||
NetNet* NetEUReduce::synthesize(Design*des, NetScope*scope)
|
||||
{
|
||||
NetNet*isig = expr_->synthesize(des, scope);
|
||||
NetNet*isig = expr_->synthesize(des);
|
||||
|
||||
if (isig == 0) return 0;
|
||||
|
||||
if (isig->data_type() == IVL_VT_REAL) {
|
||||
if (op() == '!') {
|
||||
cerr << get_fileline() << ": sorry: ! is currently "
|
||||
"unsupported for real values." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
cerr << get_fileline() << ": error: reduction operator ("
|
||||
<< human_readable_op(op_)
|
||||
<< ") may not have a REAL operand." << endl;
|
||||
@@ -909,6 +824,9 @@ NetNet* NetEUReduce::synthesize(Design*des, NetScope*scope)
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetScope*scope = isig->scope();
|
||||
assert(scope);
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
osig->data_type(expr_type());
|
||||
@@ -931,7 +849,7 @@ NetNet* NetEUReduce::synthesize(Design*des, NetScope*scope)
|
||||
rtype = NetUReduce::XOR;
|
||||
break;
|
||||
case 'A':
|
||||
rtype = NetUReduce::NAND;
|
||||
rtype = NetUReduce::XNOR;
|
||||
break;
|
||||
case 'X':
|
||||
rtype = NetUReduce::XNOR;
|
||||
@@ -953,119 +871,22 @@ NetNet* NetEUReduce::synthesize(Design*des, NetScope*scope)
|
||||
return osig;
|
||||
}
|
||||
|
||||
/*
|
||||
* Turn a part/bit select expression into gates.
|
||||
* We know some things about the expression that elaboration enforces
|
||||
* for us:
|
||||
*
|
||||
* - Expression elaboration already converted the offset expression into
|
||||
* canonical form, so we don't have to worry about that here.
|
||||
*/
|
||||
NetNet* NetESelect::synthesize(Design *des, NetScope*scope)
|
||||
NetNet* NetESelect::synthesize(Design *des)
|
||||
{
|
||||
|
||||
NetNet*sub = expr_->synthesize(des, scope);
|
||||
NetNet*sub = expr_->synthesize(des);
|
||||
|
||||
if (sub == 0) return 0;
|
||||
|
||||
NetScope*scope = sub->scope();
|
||||
|
||||
NetNet*off = 0;
|
||||
|
||||
// Detect the special case that there is a base expression and
|
||||
// it is constant. In this case we can generate fixed part selects.
|
||||
if (NetEConst*base_const = dynamic_cast<NetEConst*>(base_)) {
|
||||
verinum base_tmp = base_const->value();
|
||||
unsigned select_width = expr_width();
|
||||
|
||||
// Return 'bx for a constant undefined selections.
|
||||
if (!base_tmp.is_defined()) {
|
||||
NetNet*result = make_const_x(des, scope, select_width);
|
||||
result->set_line(*this);
|
||||
return result;
|
||||
}
|
||||
|
||||
long base_val = base_tmp.as_long();
|
||||
|
||||
// Any below X bits?
|
||||
NetNet*below = 0;
|
||||
if (base_val < 0) {
|
||||
unsigned below_width = abs(base_val);
|
||||
base_val = 0;
|
||||
if (below_width > select_width) {
|
||||
below_width = select_width;
|
||||
select_width = 0;
|
||||
} else {
|
||||
select_width -= below_width;
|
||||
}
|
||||
|
||||
below = make_const_x(des, scope, below_width);
|
||||
below->set_line(*this);
|
||||
// All the selected bits are below the signal.
|
||||
if (select_width == 0) return below;
|
||||
}
|
||||
|
||||
// Any above bits?
|
||||
NetNet*above = 0;
|
||||
if ((unsigned)base_val+select_width > sub->vector_width()) {
|
||||
if (base_val > (long)sub->vector_width()) {
|
||||
select_width = 0;
|
||||
} else {
|
||||
select_width = sub->vector_width() - base_val;
|
||||
}
|
||||
unsigned above_width = expr_width() - select_width;
|
||||
|
||||
above = make_const_x(des, scope, above_width);
|
||||
above->set_line(*this);
|
||||
// All the selected bits are above the signal.
|
||||
if (select_width == 0) return above;
|
||||
}
|
||||
|
||||
// Make the make part select.
|
||||
NetPartSelect*sel = new NetPartSelect(sub, base_val, select_width,
|
||||
NetPartSelect::VP);
|
||||
des->add_node(sel);
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, select_width);
|
||||
tmp->data_type(sub->data_type());
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
connect(sel->pin(0), tmp->pin(0));
|
||||
|
||||
unsigned concat_count = 1;
|
||||
if (above)
|
||||
concat_count += 1;
|
||||
if (below)
|
||||
concat_count += 1;
|
||||
if (concat_count > 1) {
|
||||
NetConcat*cat = new NetConcat(scope, scope->local_symbol(),
|
||||
expr_width(), concat_count);
|
||||
cat->set_line(*this);
|
||||
des->add_node(cat);
|
||||
if (below) {
|
||||
connect(cat->pin(1), below->pin(0));
|
||||
connect(cat->pin(2), tmp->pin(0));
|
||||
} else {
|
||||
connect(cat->pin(1), tmp->pin(0));
|
||||
}
|
||||
if (above) {
|
||||
connect(cat->pin(concat_count), above->pin(0));
|
||||
}
|
||||
|
||||
tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, expr_width());
|
||||
tmp->data_type(sub->data_type());
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
connect(cat->pin(0), tmp->pin(0));
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// This handles the case that the NetESelect exists to do an
|
||||
// actual part/bit select. Generate a NetPartSelect object to
|
||||
// do the work, and replace "sub" with the selected output.
|
||||
if (base_ != 0) {
|
||||
off = base_->synthesize(des, scope);
|
||||
off = base_->synthesize(des);
|
||||
|
||||
NetPartSelect*sel = new NetPartSelect(sub, off, expr_width());
|
||||
sel->set_line(*this);
|
||||
@@ -1146,26 +967,21 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope)
|
||||
* expressions to the B and A inputs. This way, when the select input
|
||||
* is one, the B input, which is the true expression, is selected.
|
||||
*/
|
||||
NetNet* NetETernary::synthesize(Design *des, NetScope*scope)
|
||||
NetNet* NetETernary::synthesize(Design *des)
|
||||
{
|
||||
NetNet*csig = cond_->synthesize(des, scope),
|
||||
*tsig = true_val_->synthesize(des, scope),
|
||||
*fsig = false_val_->synthesize(des, scope);
|
||||
NetNet*csig = cond_->synthesize(des),
|
||||
*tsig = true_val_->synthesize(des),
|
||||
*fsig = false_val_->synthesize(des);
|
||||
|
||||
if (csig == 0 || tsig == 0 || fsig == 0) return 0;
|
||||
|
||||
if (! NetETernary::test_operand_compat(tsig->data_type(),fsig->data_type())) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< " True and False clauses of ternary expression "
|
||||
<< " have incompatible types." << endl;
|
||||
if (tsig->data_type() != fsig->data_type()) {
|
||||
cerr << get_fileline() << ": error: True and False clauses of "
|
||||
"ternary expression have different types." << endl;
|
||||
cerr << get_fileline() << ": : True clause is: "
|
||||
<< tsig->data_type()
|
||||
<< " (" << true_val_->expr_type() << "): "
|
||||
<< *true_val_ << endl;
|
||||
<< tsig->data_type() << endl;
|
||||
cerr << get_fileline() << ": : False clause is: "
|
||||
<< fsig->data_type()
|
||||
<< " (" << false_val_->expr_type() << "): "
|
||||
<< *false_val_ << endl;
|
||||
<< fsig->data_type() << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
} else if (tsig->data_type() == IVL_VT_NO_TYPE) {
|
||||
@@ -1177,7 +993,7 @@ NetNet* NetETernary::synthesize(Design *des, NetScope*scope)
|
||||
|
||||
perm_string path = csig->scope()->local_symbol();
|
||||
|
||||
ivl_assert(*this, csig->vector_width() == 1);
|
||||
assert(csig->vector_width() == 1);
|
||||
|
||||
unsigned width=expr_width();
|
||||
NetNet*osig = new NetNet(csig->scope(), path, NetNet::IMPLICIT, width);
|
||||
@@ -1185,8 +1001,8 @@ NetNet* NetETernary::synthesize(Design *des, NetScope*scope)
|
||||
osig->local_flag(true);
|
||||
|
||||
/* Make sure both value operands are the right width. */
|
||||
tsig = crop_to_width(des, pad_to_width(des, tsig, width, *this), width);
|
||||
fsig = crop_to_width(des, pad_to_width(des, fsig, width, *this), width);
|
||||
tsig = crop_to_width(des, pad_to_width(des, tsig, width), width);
|
||||
fsig = crop_to_width(des, pad_to_width(des, fsig, width), width);
|
||||
|
||||
assert(width == tsig->vector_width());
|
||||
assert(width == fsig->vector_width());
|
||||
@@ -1209,25 +1025,26 @@ NetNet* NetETernary::synthesize(Design *des, NetScope*scope)
|
||||
* a bit more work needs to be done. Return a temporary that represents
|
||||
* the selected word.
|
||||
*/
|
||||
NetNet* NetESignal::synthesize(Design*des, NetScope*scope)
|
||||
NetNet* NetESignal::synthesize(Design*des)
|
||||
{
|
||||
if (word_ == 0)
|
||||
return net_;
|
||||
|
||||
NetScope*scope = net_->scope();
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, net_->vector_width());
|
||||
tmp->set_line(*this);
|
||||
tmp->local_flag(true);
|
||||
tmp->data_type(net_->data_type());
|
||||
|
||||
// For NetExpr objects, the word index is already converted to
|
||||
// a canonical (lsb==0) address. Just use the index directly.
|
||||
|
||||
if (NetEConst*index_co = dynamic_cast<NetEConst*> (word_)) {
|
||||
|
||||
long index = index_co->value().as_long();
|
||||
connect(tmp->pin(0), net_->pin(index));
|
||||
|
||||
assert(net_->array_index_is_valid(index));
|
||||
index = net_->array_index_to_address(index);
|
||||
|
||||
connect(tmp->pin(0), net_->pin(index));
|
||||
} else {
|
||||
unsigned selwid = word_->expr_width();
|
||||
|
||||
@@ -1236,7 +1053,7 @@ NetNet* NetESignal::synthesize(Design*des, NetScope*scope)
|
||||
mux->set_line(*this);
|
||||
des->add_node(mux);
|
||||
|
||||
NetNet*index_net = word_->synthesize(des, scope);
|
||||
NetNet*index_net = word_->synthesize(des);
|
||||
connect(mux->pin_Address(), index_net->pin(0));
|
||||
|
||||
connect(tmp->pin(0), mux->pin_Result());
|
||||
@@ -1244,68 +1061,22 @@ NetNet* NetESignal::synthesize(Design*des, NetScope*scope)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetNet* NetESFunc::synthesize(Design*des, NetScope*scope)
|
||||
NetNet* NetESFunc::synthesize(Design*des)
|
||||
{
|
||||
|
||||
const struct sfunc_return_type*def = lookup_sys_func(name_);
|
||||
|
||||
/* We cannot use the default value for system functions in a
|
||||
* continuous assignment since the function name is NULL. */
|
||||
if (def == 0 || def->name == 0) {
|
||||
cerr << get_fileline() << ": error: System function "
|
||||
<< name_ << " not defined in system "
|
||||
"table or SFT file(s)." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Net system function "
|
||||
<< name_ << " returns " << def->type << endl;
|
||||
}
|
||||
|
||||
NetSysFunc*net = new NetSysFunc(scope, scope->local_symbol(),
|
||||
def, 1+nparms_);
|
||||
net->set_line(*this);
|
||||
des->add_node(net);
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, def->wid);
|
||||
osig->local_flag(true);
|
||||
osig->set_signed(def->type==IVL_VT_REAL? true : false);
|
||||
osig->data_type(def->type);
|
||||
osig->set_line(*this);
|
||||
|
||||
connect(net->pin(0), osig->pin(0));
|
||||
|
||||
unsigned errors = 0;
|
||||
for (unsigned idx = 0 ; idx < nparms_ ; idx += 1) {
|
||||
NetNet*tmp = parms_[idx]->synthesize(des, scope);
|
||||
if (tmp == 0) {
|
||||
cerr << get_fileline() << ": error: Unable to elaborate "
|
||||
<< "argument " << idx << " of call to " << name_ <<
|
||||
"." << endl;
|
||||
errors += 1;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
connect(net->pin(1+idx), tmp->pin(0));
|
||||
}
|
||||
|
||||
if (errors > 0) return 0;
|
||||
|
||||
return osig;
|
||||
cerr << get_fileline() << ": sorry: cannot synthesize system function: "
|
||||
<< *this << " in this context" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetNet* NetEUFunc::synthesize(Design*des, NetScope*scope)
|
||||
NetNet* NetEUFunc::synthesize(Design*des)
|
||||
{
|
||||
svector<NetNet*> eparms (parms_.count());
|
||||
|
||||
/* Synthesize the arguments. */
|
||||
bool errors = false;
|
||||
for (unsigned idx = 0; idx < eparms.count(); idx += 1) {
|
||||
NetNet*tmp = parms_[idx]->synthesize(des, scope);
|
||||
NetNet*tmp = parms_[idx]->synthesize(des);
|
||||
if (tmp == 0) {
|
||||
cerr << get_fileline() << ": error: Unable to synthesize "
|
||||
"port " << idx << " of call to "
|
||||
@@ -1332,8 +1103,8 @@ NetNet* NetEUFunc::synthesize(Design*des, NetScope*scope)
|
||||
/* Connect the pins to the arguments. */
|
||||
NetFuncDef*def = func_->func_def();
|
||||
for (unsigned idx = 0; idx < eparms.count(); idx += 1) {
|
||||
NetNet*tmp = pad_to_width(des, eparms[idx],
|
||||
def->port(idx)->vector_width(), *this);
|
||||
NetNet*tmp = pad_to_width(des, eparms[idx],
|
||||
def->port(idx)->vector_width());
|
||||
connect(net->pin(idx+1), tmp->pin(0));
|
||||
}
|
||||
|
||||
|
||||
+13
-5
@@ -111,12 +111,20 @@ void NetScope::run_functor(Design*des, functor_t*fun)
|
||||
|
||||
// apply to signals. Each iteration, allow for the possibility
|
||||
// that the current signal deletes itself.
|
||||
if (signals_) {
|
||||
unsigned count = 0;
|
||||
NetNet*cur = signals_->sig_next_;
|
||||
do {
|
||||
count += 1;
|
||||
cur = cur->sig_next_;
|
||||
} while (cur != signals_->sig_next_);
|
||||
|
||||
signals_map_iter_t cur = signals_map_.begin();
|
||||
while (cur != signals_map_.end()) {
|
||||
signals_map_iter_t tmp = cur;
|
||||
cur ++;
|
||||
fun->signal(des, tmp->second);
|
||||
cur = signals_->sig_next_;
|
||||
for (unsigned idx = 0 ; idx < count ; idx += 1) {
|
||||
NetNet*tmp = cur->sig_next_;
|
||||
fun->signal(des, cur);
|
||||
cur = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
.TH iverilog-vpi 1 "November 19th, 2008" "" "Version 0.9.devel"
|
||||
.TH iverilog-vpi 1 "$Date: 2004/10/04 01:10:53 $" Version "$Date: 2004/10/04 01:10:53 $"
|
||||
.SH NAME
|
||||
iverilog-vpi - Compile front end for VPI modules
|
||||
|
||||
@@ -129,7 +129,7 @@ iverilog(1), vvp(1),
|
||||
|
||||
.SH COPYRIGHT
|
||||
.nf
|
||||
Copyright \(co 2002-2008 Stephen Williams
|
||||
Copyright \(co 2002 Stephen Williams
|
||||
|
||||
This document can be freely redistributed according to the terms of the
|
||||
GNU General Public License version 2.0
|
||||
|
||||
+3
-4
@@ -17,18 +17,17 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: iverilog-vpi.sh,v 1.17 2007/02/06 05:07:31 steve Exp $"
|
||||
|
||||
# These are the variables used for compiling files
|
||||
CC=@IVCC@
|
||||
CXX=@IVCXX@
|
||||
CFLAGS="@PIC@ @IVCFLAGS@ -I@INCLUDEDIR@"
|
||||
|
||||
SUFFIX=@SUFFIX@
|
||||
|
||||
# These are used for linking...
|
||||
LD=$CC
|
||||
LDFLAGS="@SHARED@ -L@LIBDIR@"
|
||||
LDLIBS="-lveriuser$SUFFIX -lvpi$SUFFIX"
|
||||
LDLIBS="-lveriuser -lvpi"
|
||||
|
||||
CCSRC=
|
||||
CXSRC=
|
||||
@@ -102,7 +101,7 @@ do
|
||||
;;
|
||||
|
||||
--install-dir)
|
||||
echo "@LIBDIR@/ivl$SUFFIX"
|
||||
echo "@LIBDIR@/ivl"
|
||||
exit
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
EXPORTS
|
||||
|
||||
ivl_branch_island
|
||||
ivl_branch_terminal
|
||||
|
||||
ivl_design_const
|
||||
ivl_design_consts
|
||||
ivl_design_discipline
|
||||
ivl_design_disciplines
|
||||
ivl_design_flag
|
||||
ivl_design_process
|
||||
ivl_design_root
|
||||
@@ -20,11 +15,6 @@ ivl_const_signed
|
||||
ivl_const_type
|
||||
ivl_const_width
|
||||
|
||||
ivl_discipline_domain
|
||||
ivl_discipline_flow
|
||||
ivl_discipline_name
|
||||
ivl_discipline_potential
|
||||
|
||||
ivl_event_any
|
||||
ivl_event_basename
|
||||
ivl_event_name
|
||||
@@ -37,14 +27,12 @@ ivl_event_scope
|
||||
|
||||
ivl_expr_type
|
||||
ivl_expr_bits
|
||||
ivl_expr_branch
|
||||
ivl_expr_def
|
||||
ivl_expr_dvalue
|
||||
ivl_expr_event
|
||||
ivl_expr_file
|
||||
ivl_expr_lineno
|
||||
ivl_expr_name
|
||||
ivl_expr_nature
|
||||
ivl_expr_opcode
|
||||
ivl_expr_oper1
|
||||
ivl_expr_oper2
|
||||
@@ -117,15 +105,12 @@ ivl_lval_part_off
|
||||
ivl_lval_sig
|
||||
ivl_lval_width
|
||||
|
||||
ivl_nature_name
|
||||
|
||||
ivl_nexus_get_private
|
||||
ivl_nexus_name
|
||||
ivl_nexus_ptrs
|
||||
ivl_nexus_ptr
|
||||
ivl_nexus_set_private
|
||||
|
||||
ivl_nexus_ptr_branch
|
||||
ivl_nexus_ptr_con
|
||||
ivl_nexus_ptr_drive0
|
||||
ivl_nexus_ptr_drive1
|
||||
@@ -158,7 +143,6 @@ ivl_scope_def_lineno
|
||||
ivl_scope_event
|
||||
ivl_scope_events
|
||||
ivl_scope_file
|
||||
ivl_scope_is_auto
|
||||
ivl_scope_lineno
|
||||
ivl_scope_logs
|
||||
ivl_scope_log
|
||||
@@ -187,7 +171,6 @@ ivl_signal_attr_val
|
||||
ivl_signal_basename
|
||||
ivl_signal_data_type
|
||||
ivl_signal_dimensions
|
||||
ivl_signal_discipline
|
||||
ivl_signal_file
|
||||
ivl_signal_integer
|
||||
ivl_signal_lineno
|
||||
@@ -206,11 +189,8 @@ ivl_signal_width
|
||||
ivl_path_delay
|
||||
ivl_path_source
|
||||
|
||||
ivl_process_analog
|
||||
ivl_process_attr_cnt
|
||||
ivl_process_attr_val
|
||||
ivl_process_file
|
||||
ivl_process_lineno
|
||||
ivl_process_scope
|
||||
ivl_process_stmt
|
||||
ivl_process_type
|
||||
@@ -232,7 +212,6 @@ ivl_stmt_delay_val
|
||||
ivl_stmt_events
|
||||
ivl_stmt_file
|
||||
ivl_stmt_lineno
|
||||
ivl_stmt_lexp
|
||||
ivl_stmt_lval
|
||||
ivl_stmt_lvals
|
||||
ivl_stmt_lwidth
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: ivl_assert.h,v 1.1 2007/01/31 04:21:10 steve Exp $"
|
||||
#endif
|
||||
|
||||
#ifndef __ivl_assert_h
|
||||
#define __ivl_assert_h
|
||||
|
||||
+11
-106
@@ -60,9 +60,6 @@ _BEGIN_DECL
|
||||
* This object represent an array that can be a memory or a net
|
||||
* array. (They are the same from the perspective of ivl_target.h.)
|
||||
*
|
||||
* ivl_branch_t
|
||||
* this object represents an analog branch.
|
||||
*
|
||||
* ivl_design_t
|
||||
* This object represents the entire elaborated design. Various
|
||||
* global properties and methods are available from this.
|
||||
@@ -152,10 +149,8 @@ _BEGIN_DECL
|
||||
* throughout the design.
|
||||
*/
|
||||
typedef struct ivl_array_s *ivl_array_t;
|
||||
typedef struct ivl_branch_s *ivl_branch_t;
|
||||
typedef struct ivl_delaypath_s*ivl_delaypath_t;
|
||||
typedef struct ivl_design_s *ivl_design_t;
|
||||
typedef struct ivl_discipline_s*ivl_discipline_t;
|
||||
typedef struct ivl_event_s *ivl_event_t;
|
||||
typedef struct ivl_expr_s *ivl_expr_t;
|
||||
typedef struct ivl_island_s *ivl_island_t;
|
||||
@@ -164,7 +159,6 @@ typedef struct ivl_lval_s *ivl_lval_t;
|
||||
typedef struct ivl_net_const_s*ivl_net_const_t;
|
||||
typedef struct ivl_net_logic_s*ivl_net_logic_t;
|
||||
typedef struct ivl_udp_s *ivl_udp_t;
|
||||
typedef struct ivl_nature_s *ivl_nature_t;
|
||||
typedef struct ivl_net_probe_s*ivl_net_probe_t;
|
||||
typedef struct ivl_nexus_s *ivl_nexus_t;
|
||||
typedef struct ivl_nexus_ptr_s*ivl_nexus_ptr_t;
|
||||
@@ -182,12 +176,6 @@ typedef struct ivl_statement_s*ivl_statement_t;
|
||||
* changes and additions to the enumerations.
|
||||
*/
|
||||
|
||||
typedef enum ivl_dis_domain_e {
|
||||
IVL_DIS_NONE = 0,
|
||||
IVL_DIS_DISCRETE = 1,
|
||||
IVL_DIS_CONTINUOUS = 2
|
||||
} ivl_dis_domain_t;
|
||||
|
||||
typedef enum ivl_drive_e {
|
||||
IVL_DR_HiZ = 0,
|
||||
IVL_DR_SMALL = 1,
|
||||
@@ -205,7 +193,6 @@ typedef enum ivl_drive_e {
|
||||
typedef enum ivl_expr_type_e {
|
||||
IVL_EX_NONE = 0,
|
||||
IVL_EX_ARRAY = 18,
|
||||
IVL_EX_BACCESS= 19,
|
||||
IVL_EX_BINARY = 2,
|
||||
IVL_EX_CONCAT = 3,
|
||||
IVL_EX_EVENT = 17,
|
||||
@@ -267,8 +254,6 @@ typedef enum ivl_lpm_type_e {
|
||||
IVL_LPM_ABS = 32,
|
||||
IVL_LPM_ADD = 0,
|
||||
IVL_LPM_ARRAY = 30,
|
||||
IVL_LPM_CAST_INT = 34,
|
||||
IVL_LPM_CAST_REAL = 33,
|
||||
IVL_LPM_CONCAT = 16,
|
||||
IVL_LPM_CMP_EEQ= 18, /* Case EQ (===) */
|
||||
IVL_LPM_CMP_EQ = 10,
|
||||
@@ -355,7 +340,6 @@ typedef enum ivl_signal_type_e {
|
||||
typedef enum ivl_statement_type_e {
|
||||
IVL_ST_NONE = 0,
|
||||
IVL_ST_NOOP = 1,
|
||||
IVL_ST_ALLOC = 25,
|
||||
IVL_ST_ASSIGN = 2,
|
||||
IVL_ST_ASSIGN_NB = 3,
|
||||
IVL_ST_BLOCK = 4,
|
||||
@@ -365,7 +349,6 @@ typedef enum ivl_statement_type_e {
|
||||
IVL_ST_CASEZ = 7,
|
||||
IVL_ST_CASSIGN = 8,
|
||||
IVL_ST_CONDIT = 9,
|
||||
IVL_ST_CONTRIB = 27,
|
||||
IVL_ST_DEASSIGN = 10,
|
||||
IVL_ST_DELAY = 11,
|
||||
IVL_ST_DELAYX = 12,
|
||||
@@ -373,7 +356,6 @@ typedef enum ivl_statement_type_e {
|
||||
IVL_ST_FORCE = 14,
|
||||
IVL_ST_FOREVER = 15,
|
||||
IVL_ST_FORK = 16,
|
||||
IVL_ST_FREE = 26,
|
||||
IVL_ST_RELEASE = 17,
|
||||
IVL_ST_REPEAT = 18,
|
||||
IVL_ST_STASK = 19,
|
||||
@@ -420,20 +402,6 @@ struct ivl_attribute_s {
|
||||
};
|
||||
typedef const struct ivl_attribute_s*ivl_attribute_t;
|
||||
|
||||
/* BRANCH
|
||||
* Branches are analog constructs, a pair of terminals that is used in
|
||||
* branch access functions. Terminal-1 is the reference node (The
|
||||
* "ground") for the purposes of the access function that accesses it.
|
||||
*
|
||||
* SEMANTIC NOTES
|
||||
* All the branches in an island are connected by terminals or by
|
||||
* expressions. The island is the connection of branches that must be
|
||||
* solved together.
|
||||
*/
|
||||
/* extern ivl_scope_t ivl_branch_scope(ivl_branch_t obj); */
|
||||
extern ivl_nexus_t ivl_branch_terminal(ivl_branch_t obj, int idx);
|
||||
extern ivl_island_t ivl_branch_island(ivl_branch_t obj);
|
||||
|
||||
/* DELAYPATH
|
||||
* Delaypath objects represent delay paths called out by a specify
|
||||
* block in the Verilog source file. The destination signal references
|
||||
@@ -518,9 +486,6 @@ extern int ivl_design_time_precision(ivl_design_t des);
|
||||
extern unsigned ivl_design_consts(ivl_design_t des);
|
||||
extern ivl_net_const_t ivl_design_const(ivl_design_t, unsigned idx);
|
||||
|
||||
extern unsigned ivl_design_disciplines(ivl_design_t des);
|
||||
extern ivl_discipline_t ivl_design_discipline(ivl_design_t des, unsigned idx);
|
||||
|
||||
/* LITERAL CONSTANTS
|
||||
* Literal constants are nodes with no input and a single constant
|
||||
* output. The form of the output depends on the type of the node.
|
||||
@@ -534,8 +499,7 @@ extern ivl_discipline_t ivl_design_discipline(ivl_design_t des, unsigned idx);
|
||||
* ivl_const_bits
|
||||
* This returns a pointer to an array of constant characters,
|
||||
* each byte a '0', '1', 'x' or 'z'. The array is *not* nul
|
||||
* terminated. This value is only value if ivl_const_type is
|
||||
* IVL_VT_LOGIC or IVL_VT_BOOL. It returns nil otherwise.
|
||||
* terminated.
|
||||
*
|
||||
* ivl_const_nex
|
||||
* Return the ivl_nexus_t of the output for the constant.
|
||||
@@ -573,32 +537,6 @@ extern double ivl_const_real(ivl_net_const_t net);
|
||||
/* extern ivl_nexus_t ivl_const_pin(ivl_net_const_t net, unsigned idx); */
|
||||
/* extern unsigned ivl_const_pins(ivl_net_const_t net); */
|
||||
|
||||
/* DISCIPLINES
|
||||
*
|
||||
* Disciplines are Verilog-AMS construct. A discipline is a collection
|
||||
* of attributes that can be attached to a signal.
|
||||
*
|
||||
* FUNCTION SUMMARY
|
||||
*
|
||||
* ivl_discipline_name
|
||||
* This is the name of the discipline in the Verilog-AMS source.
|
||||
*
|
||||
* ivl_discipline_domain
|
||||
* This is the domain: continuous or discrete.
|
||||
*
|
||||
* SEMANTIC NOTES
|
||||
*
|
||||
* The discipline domain will not be IVL_DIS_NONE. The "none" domain
|
||||
* is a place-holder internally for incomplete parsing, and is also
|
||||
* available for code generaters to use.
|
||||
*/
|
||||
extern const char*ivl_discipline_name(ivl_discipline_t net);
|
||||
extern ivl_dis_domain_t ivl_discipline_domain(ivl_discipline_t net);
|
||||
extern ivl_nature_t ivl_discipline_potential(ivl_discipline_t net);
|
||||
extern ivl_nature_t ivl_discipline_flow(ivl_discipline_t net);
|
||||
|
||||
extern const char* ivl_nature_name(ivl_nature_t net);
|
||||
|
||||
/* EVENTS
|
||||
*
|
||||
* Events are a unification of named events and implicit events
|
||||
@@ -742,16 +680,12 @@ extern unsigned ivl_expr_lineno(ivl_expr_t net);
|
||||
|
||||
/* IVL_EX_NUMBER */
|
||||
extern const char* ivl_expr_bits(ivl_expr_t net);
|
||||
/* IVL_EX_BACCESS */
|
||||
extern ivl_branch_t ivl_expr_branch(ivl_expr_t net);
|
||||
/* IVL_EX_UFUNC */
|
||||
extern ivl_scope_t ivl_expr_def(ivl_expr_t net);
|
||||
/* IVL_EX_REALNUM */
|
||||
extern double ivl_expr_dvalue(ivl_expr_t net);
|
||||
/* IVL_EX_SIGNAL, IVL_EX_SFUNC, IVL_EX_VARIABLE */
|
||||
extern const char* ivl_expr_name(ivl_expr_t net);
|
||||
/* IVL_EX_BACCESS */
|
||||
extern ivl_nature_t ivl_expr_nature(ivl_expr_t net);
|
||||
/* IVL_EX_BINARY IVL_EX_UNARY */
|
||||
extern char ivl_expr_opcode(ivl_expr_t net);
|
||||
/* IVL_EX_BINARY IVL_EX_UNARY, IVL_EX_MEMORY IVL_EX_TERNARY */
|
||||
@@ -1052,9 +986,8 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
|
||||
* more than the width of the output, although the possibility of
|
||||
* overflow exists at run time.
|
||||
*
|
||||
* The inputs are always treated as unsigned. If the expression is
|
||||
* supposed to be signed, elaboration will generate the necessary sign
|
||||
* extension, so the target need not (must not) consider signedness.
|
||||
* Multiply may be signed. If so, the output should be sign extended
|
||||
* to fill in its result.
|
||||
*
|
||||
* - Power (IVL_LPM_POW)
|
||||
* The power takes two inputs and generates an output. Unlike other
|
||||
@@ -1318,7 +1251,7 @@ extern const char*ivl_lpm_string(ivl_lpm_t net);
|
||||
*/
|
||||
|
||||
extern unsigned ivl_lval_width(ivl_lval_t net);
|
||||
extern ivl_expr_t ivl_lval_mux(ivl_lval_t net); /* XXXX Obsolete? */
|
||||
extern ivl_expr_t ivl_lval_mux(ivl_lval_t net); // XXXX Obsolete?
|
||||
extern ivl_expr_t ivl_lval_idx(ivl_lval_t net);
|
||||
extern ivl_expr_t ivl_lval_part_off(ivl_lval_t net);
|
||||
extern ivl_signal_t ivl_lval_sig(ivl_lval_t net);
|
||||
@@ -1410,7 +1343,6 @@ extern void* ivl_nexus_get_private(ivl_nexus_t net);
|
||||
extern ivl_drive_t ivl_nexus_ptr_drive0(ivl_nexus_ptr_t net);
|
||||
extern ivl_drive_t ivl_nexus_ptr_drive1(ivl_nexus_ptr_t net);
|
||||
extern unsigned ivl_nexus_ptr_pin(ivl_nexus_ptr_t net);
|
||||
extern ivl_branch_t ivl_nexus_ptr_branch(ivl_nexus_ptr_t net);
|
||||
extern ivl_net_const_t ivl_nexus_ptr_con(ivl_nexus_ptr_t net);
|
||||
extern ivl_net_logic_t ivl_nexus_ptr_log(ivl_nexus_ptr_t net);
|
||||
extern ivl_lpm_t ivl_nexus_ptr_lpm(ivl_nexus_ptr_t net);
|
||||
@@ -1513,9 +1445,6 @@ extern unsigned ivl_parameter_lineno(ivl_parameter_t net);
|
||||
* ivl_scope_lineno
|
||||
* Returns the instantiation file and line for this scope.
|
||||
*
|
||||
* ivl_scope_is_auto
|
||||
* Is the task or function declared to be automatic?
|
||||
*
|
||||
* ivl_scope_var
|
||||
* ivl_scope_vars
|
||||
* REMOVED
|
||||
@@ -1592,7 +1521,6 @@ extern unsigned ivl_scope_def_lineno(ivl_scope_t net);
|
||||
extern unsigned ivl_scope_events(ivl_scope_t net);
|
||||
extern ivl_event_t ivl_scope_event(ivl_scope_t net, unsigned idx);
|
||||
extern const char* ivl_scope_file(ivl_scope_t net);
|
||||
extern unsigned ivl_scope_is_auto(ivl_scope_t net);
|
||||
extern unsigned ivl_scope_lineno(ivl_scope_t net);
|
||||
extern unsigned ivl_scope_logs(ivl_scope_t net);
|
||||
extern ivl_net_logic_t ivl_scope_log(ivl_scope_t net, unsigned idx);
|
||||
@@ -1645,10 +1573,6 @@ extern int ivl_scope_time_units(ivl_scope_t net);
|
||||
* The signal may be an array (of vectors) in which case this
|
||||
* function returns >0, the number of dimensions of the array.
|
||||
*
|
||||
* ivl_signal_discipline
|
||||
* If the signal has been declared with a domain (Verilog-AMS) then
|
||||
* this function wil return a non-nil ivl_discipline_t.
|
||||
*
|
||||
* ivl_signal_msb
|
||||
* ivl_signal_lsb
|
||||
* ivl_signal_width
|
||||
@@ -1716,7 +1640,6 @@ extern ivl_nexus_t ivl_signal_nex(ivl_signal_t net, unsigned word);
|
||||
extern int ivl_signal_array_base(ivl_signal_t net);
|
||||
extern unsigned ivl_signal_array_count(ivl_signal_t net);
|
||||
extern unsigned ivl_signal_dimensions(ivl_signal_t net);
|
||||
extern ivl_discipline_t ivl_signal_discipline(ivl_signal_t net);
|
||||
extern int ivl_signal_msb(ivl_signal_t net);
|
||||
extern int ivl_signal_lsb(ivl_signal_t net);
|
||||
extern unsigned ivl_signal_width(ivl_signal_t net);
|
||||
@@ -1747,16 +1670,12 @@ extern ivl_attribute_t ivl_signal_attr_val(ivl_signal_t net, unsigned idx);
|
||||
* is translated into a type and a single statement. (The statement
|
||||
* may be a compound statement.)
|
||||
*
|
||||
* ivl_process_type
|
||||
* ivl_process_analog
|
||||
* The ivl_process_type function returns the type of the process,
|
||||
* an "initial" or "always" statement. The ivl_process_analog
|
||||
* returns true if the process is analog.
|
||||
* The ivl_process_type function gets the type of the process,
|
||||
* an "initial" or "always" statement.
|
||||
*
|
||||
* ivl_process_scope
|
||||
* A process is placed in a scope. The statement within the process
|
||||
* operates within the scope of the process unless there are calls
|
||||
* outside the scope.
|
||||
* A process is placed in a scope. The statement within the process
|
||||
* operates within the scope of the process unless there are calls
|
||||
* outside the scope.
|
||||
*
|
||||
* The ivl_process_stmt function gets the statement that forms the
|
||||
* process. See the statement related functions for how to manipulate
|
||||
@@ -1766,7 +1685,6 @@ extern ivl_attribute_t ivl_signal_attr_val(ivl_signal_t net, unsigned idx);
|
||||
* attr_val methods return those attributes.
|
||||
*/
|
||||
extern ivl_process_type_t ivl_process_type(ivl_process_t net);
|
||||
extern int ivl_process_analog(ivl_process_t net);
|
||||
|
||||
extern ivl_scope_t ivl_process_scope(ivl_process_t net);
|
||||
|
||||
@@ -1775,9 +1693,6 @@ extern ivl_statement_t ivl_process_stmt(ivl_process_t net);
|
||||
extern unsigned ivl_process_attr_cnt(ivl_process_t net);
|
||||
extern ivl_attribute_t ivl_process_attr_val(ivl_process_t net, unsigned idx);
|
||||
|
||||
extern const char* ivl_process_file(ivl_process_t net);
|
||||
extern unsigned ivl_process_lineno(ivl_process_t net);
|
||||
|
||||
/*
|
||||
* These functions manage statements of various type. This includes
|
||||
* all the different kinds of statements (as enumerated in
|
||||
@@ -1862,12 +1777,6 @@ extern unsigned ivl_stmt_lineno(ivl_statement_t net);
|
||||
* that constant value. If the expression is non-constant, the code
|
||||
* generator is supposed to know what to do about that, too.
|
||||
*
|
||||
* - IVL_ST_CONTRIB
|
||||
* This is an analog contribution statement. The ivl_stmt_lexp
|
||||
* function returns the l-value expression which is guaranteed to be a
|
||||
* branch access expression. The ivl_stmt_rval returns the r-value
|
||||
* expression for the assignment.
|
||||
*
|
||||
* - IVL_ST_DELAY, IVL_ST_DELAYX
|
||||
* These statement types are delay statements. They are a way to
|
||||
* attach a delay to a statement. The ivl_stmt_sub_stmt() function
|
||||
@@ -1933,8 +1842,6 @@ extern uint64_t ivl_stmt_delay_val(ivl_statement_t net);
|
||||
/* IVL_ST_WAIT IVL_ST_TRIGGER */
|
||||
extern unsigned ivl_stmt_nevent(ivl_statement_t net);
|
||||
extern ivl_event_t ivl_stmt_events(ivl_statement_t net, unsigned idx);
|
||||
/* IVL_ST_CONTRIB */
|
||||
extern ivl_expr_t ivl_stmt_lexp(ivl_statement_t net);
|
||||
/* IVL_ST_ASSIGN IVL_ST_ASSIGN_NB IVL_ST_CASSIGN IVL_ST_DEASSIGN
|
||||
IVL_ST_FORCE IVL_ST_RELEASE */
|
||||
extern ivl_lval_t ivl_stmt_lval(ivl_statement_t net, unsigned idx);
|
||||
@@ -1949,8 +1856,7 @@ extern const char* ivl_stmt_name(ivl_statement_t net);
|
||||
extern ivl_expr_t ivl_stmt_parm(ivl_statement_t net, unsigned idx);
|
||||
/* IVL_ST_STASK */
|
||||
extern unsigned ivl_stmt_parm_count(ivl_statement_t net);
|
||||
/* IVL_ST_ASSIGN IVL_ST_ASSIGN_NB IVL_ST_CASSIGN IVL_ST_CONTRIB
|
||||
IVL_ST_FORCE */
|
||||
/* IVL_ST_ASSIGN IVL_ST_ASSIGN_NB IVL_ST_CASSIGN IVL_ST_FORCE */
|
||||
extern ivl_expr_t ivl_stmt_rval(ivl_statement_t net);
|
||||
/* IVL_ST_DELAY, IVL_ST_DELAYX, IVL_ST_FOREVER, IVL_ST_REPEAT
|
||||
IVL_ST_WAIT, IVL_ST_WHILE */
|
||||
@@ -2011,7 +1917,7 @@ extern unsigned ivl_switch_lineno(ivl_switch_t net);
|
||||
#endif
|
||||
|
||||
extern DLLEXPORT int target_design(ivl_design_t des);
|
||||
extern DLLEXPORT const char* target_query(const char*key);
|
||||
|
||||
|
||||
/* target_design
|
||||
|
||||
@@ -2029,7 +1935,6 @@ extern DLLEXPORT const char* target_query(const char*key);
|
||||
ivl core. This function is how the target module is invoked. */
|
||||
|
||||
typedef int (*target_design_f)(ivl_design_t des);
|
||||
typedef const char* (*target_query_f) (const char*key);
|
||||
|
||||
|
||||
_END_DECL
|
||||
|
||||
+6
-44
@@ -1,5 +1,5 @@
|
||||
#ifndef __ivl_target_priv_H
|
||||
#define __ivl_target_priv_H
|
||||
#define __ivl_target_H
|
||||
/*
|
||||
* Copyright (c) 2008 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
@@ -19,64 +19,26 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "ivl_target.h"
|
||||
# include <inttypes.h>
|
||||
# include <vector>
|
||||
# include <valarray>
|
||||
|
||||
/*
|
||||
* This header has declarations related to the ivl_target.h API that
|
||||
* This deader has declarations related to the ivl_target.h API that
|
||||
* are not to be exported outside of the core via the ivl_target.h
|
||||
* interface.
|
||||
*
|
||||
* (NOTE: A lot of similar definitions exist in the t-dll.h header
|
||||
* file. That is a legacy from an earlier time before the
|
||||
* ivl_target_priv.h header file was started, and those definitions
|
||||
* should gradually be moved over to this header file.)
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is the root of a design, from the ivl_target point of few. The
|
||||
* ivl_target API uses this as the root for getting at everything else
|
||||
* in the design.
|
||||
*/
|
||||
struct ivl_design_s {
|
||||
|
||||
int time_precision;
|
||||
|
||||
ivl_process_t threads_;
|
||||
|
||||
ivl_scope_t *roots_;
|
||||
unsigned nroots_;
|
||||
|
||||
// Keep an array of constants objects.
|
||||
std::valarray<ivl_net_const_t> consts;
|
||||
|
||||
// Keep a handy array of all of the disciplines in the design.
|
||||
std::valarray<ivl_discipline_t> disciplines;
|
||||
|
||||
const class Design*self;
|
||||
};
|
||||
|
||||
/*
|
||||
* A branch is a pair of terminals. The elaborator assures that the
|
||||
* terminals have compatible disciplines.
|
||||
*/
|
||||
struct ivl_branch_s {
|
||||
ivl_nexus_t pins[2];
|
||||
ivl_island_t island;
|
||||
};
|
||||
|
||||
/*
|
||||
* Information about islands. Connected branches within a net are
|
||||
* collected into islands. Branches that are purely ddiscrete do not
|
||||
* have disciplines and do not belong to islands.
|
||||
*/
|
||||
|
||||
class discipline_t;
|
||||
|
||||
struct ivl_island_s {
|
||||
ivl_discipline_t discipline;
|
||||
discipline_t*discipline;
|
||||
// user accessible flags. They are initially false, always.
|
||||
std::vector<bool> flags;
|
||||
vector<bool> flags;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+10
-9
@@ -18,11 +18,12 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.18 2006/10/30 22:45:37 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.9.devel
|
||||
|
||||
suffix = @install_suffix@
|
||||
VERSION = 0.0
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
@@ -39,7 +40,7 @@ INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
CPPFLAGS = -I. -I.. -I$(srcdir)/.. -I$(srcdir) -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@
|
||||
CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir)/.. -I$(srcdir) @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = -Wall @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
@@ -59,16 +60,16 @@ ivlpp@EXEEXT@: $O
|
||||
lexor.c: lexor.lex
|
||||
flex -olexor.c $(srcdir)/lexor.lex
|
||||
|
||||
install: all installdirs $(libdir)/ivl$(suffix)/ivlpp@EXEEXT@
|
||||
install: all installdirs $(libdir)/ivl/ivlpp@EXEEXT@
|
||||
|
||||
$(libdir)/ivl$(suffix)/ivlpp@EXEEXT@: ivlpp@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./ivlpp@EXEEXT@ $(DESTDIR)$(libdir)/ivl$(suffix)/ivlpp@EXEEXT@
|
||||
$(libdir)/ivl/ivlpp@EXEEXT@: ivlpp@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./ivlpp@EXEEXT@ $(libdir)/ivl/ivlpp@EXEEXT@
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs $(DESTDIR)$(libdir)/ivl$(suffix)
|
||||
$(srcdir)/../mkinstalldirs $(libdir)/ivl
|
||||
|
||||
uninstall:
|
||||
rm -f $(DESTDIR)$(libdir)/ivl$(suffix)/ivlpp@EXEEXT@
|
||||
rm -f $(libdir)/ivl/ivlpp@EXEEXT@
|
||||
|
||||
lexor.o: lexor.c globals.h
|
||||
main.o: main.c globals.h
|
||||
|
||||
+1
-3
@@ -1,7 +1,7 @@
|
||||
#ifndef __globals_H
|
||||
#define __globals_H
|
||||
/*
|
||||
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2007 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -22,11 +22,9 @@
|
||||
# include <stdio.h>
|
||||
|
||||
extern void reset_lexor(FILE*out, char*paths[]);
|
||||
extern void destroy_lexor();
|
||||
extern void load_precompiled_defines(FILE*src);
|
||||
extern void define_macro(const char*name, const char*value, int keyword,
|
||||
int argc);
|
||||
extern void free_macros();
|
||||
extern void dump_precompiled_defines(FILE*out);
|
||||
|
||||
/* These variables contain the include directories to be searched when
|
||||
|
||||
+18
-76
@@ -78,9 +78,6 @@ struct include_stack_t
|
||||
YY_BUFFER_STATE yybs;
|
||||
|
||||
struct include_stack_t* next;
|
||||
|
||||
/* A single line comment can be associated with this include. */
|
||||
char* comment;
|
||||
};
|
||||
|
||||
static void emit_pathline(struct include_stack_t* isp);
|
||||
@@ -118,7 +115,7 @@ static void ifdef_enter(void)
|
||||
struct ifdef_stack_t*cur;
|
||||
|
||||
cur = (struct ifdef_stack_t*) calloc(1, sizeof(struct ifdef_stack_t));
|
||||
if (istack->path) cur->path = strdup(istack->path);
|
||||
cur->path = strdup(istack->path);
|
||||
cur->lineno = istack->lineno;
|
||||
cur->next = ifdef_stack;
|
||||
|
||||
@@ -134,10 +131,8 @@ static void ifdef_leave(void)
|
||||
cur = ifdef_stack;
|
||||
ifdef_stack = cur->next;
|
||||
|
||||
/* If either path is from a non-file context e.g.(macro expansion)
|
||||
* we assume that the non-file part is from this file. */
|
||||
if (istack->path != NULL && cur->path != NULL &&
|
||||
strcmp(istack->path,cur->path) != 0) {
|
||||
if (strcmp(istack->path,cur->path) != 0)
|
||||
{
|
||||
fprintf
|
||||
(
|
||||
stderr,
|
||||
@@ -298,10 +293,9 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
||||
|
||||
/* Catch single-line comments that share the line with an include
|
||||
* directive. And while I'm at it, I might as well preserve the
|
||||
* comment in the output stream. This will be printed after the
|
||||
* file has been included.
|
||||
* comment in the output stream.
|
||||
*/
|
||||
<PPINCLUDE>"//"[^\r\n]* { standby->comment = strdup(yytext); }
|
||||
<PPINCLUDE>"//"[^\r\n]* { ECHO; }
|
||||
|
||||
/* These finish the include directive (EOF or EOL) so I revert the
|
||||
* lexor state and execute the inclusion.
|
||||
@@ -702,7 +696,7 @@ static int is_defined(const char*name)
|
||||
* These variables are also used for storing the actual arguments when
|
||||
* a macro is instantiated.
|
||||
*/
|
||||
#define MAX_DEF_ARG 256 /* allows argument IDs to be stored in a single char */
|
||||
#define MAX_DEF_ARG 256 // allows argument IDs to be stored in a single char
|
||||
|
||||
#define DEF_BUF_CHUNK 256
|
||||
|
||||
@@ -711,14 +705,14 @@ static int def_buf_size = 0;
|
||||
static int def_buf_free = 0;
|
||||
|
||||
static int def_argc = 0;
|
||||
static int def_argo[MAX_DEF_ARG]; /* offset of first character in arg */
|
||||
static int def_argl[MAX_DEF_ARG]; /* length of arg string. */
|
||||
static int def_argo[MAX_DEF_ARG]; // offset of first character in arg
|
||||
static int def_argl[MAX_DEF_ARG]; // length of arg string.
|
||||
|
||||
/*
|
||||
* Return a pointer to the start of argument 'arg'. Returned pointers
|
||||
* may go stale after a call to def_buf_grow_to_fit.
|
||||
*/
|
||||
static /* inline */ char* def_argv(int arg)
|
||||
static inline char* def_argv(int arg)
|
||||
{
|
||||
return def_buf + def_argo[arg];
|
||||
}
|
||||
@@ -833,21 +827,6 @@ void define_macro(const char* name, const char* value, int keyword, int argc)
|
||||
}
|
||||
}
|
||||
|
||||
static void free_macro(struct define_t* def)
|
||||
{
|
||||
if (def == 0) return;
|
||||
free_macro(def->left);
|
||||
free_macro(def->right);
|
||||
free(def->name);
|
||||
free(def->value);
|
||||
free(def);
|
||||
}
|
||||
|
||||
void free_macros()
|
||||
{
|
||||
free_macro(def_table);
|
||||
}
|
||||
|
||||
/*
|
||||
* The do_define function accumulates the defined value in these
|
||||
* variables. When the define is over, the def_finish() function
|
||||
@@ -877,7 +856,6 @@ static int define_continue_flag = 0;
|
||||
static char *find_arg(char*ptr, char*head, char*arg)
|
||||
{
|
||||
char *cp = ptr;
|
||||
size_t len = strlen(arg);
|
||||
|
||||
while (1) {
|
||||
/* Look for a candidate match, just return if none is found. */
|
||||
@@ -888,8 +866,7 @@ static char *find_arg(char*ptr, char*head, char*arg)
|
||||
* match is not in the middle of another identifier.
|
||||
*/
|
||||
if (cp != head &&
|
||||
(isalnum(*(cp-1)) || *(cp-1) == '_' || *(cp-1) == '$' ||
|
||||
isalnum(*(cp+len)) || *(cp+len) == '_' || *(cp+len) == '$')) {
|
||||
(isalnum(*(cp-1)) || *(cp-1) == '_' || *(cp-1) == '$')) {
|
||||
cp++;
|
||||
continue;
|
||||
}
|
||||
@@ -964,7 +941,7 @@ static void do_define()
|
||||
}
|
||||
|
||||
/* Detect the continuation sequence. If I find it, remove it
|
||||
* and the white space that precedes it, then replace all that
|
||||
* and the white space that preceeds it, then replace all that
|
||||
* with a single newline.
|
||||
*/
|
||||
if ((cp > yytext) && (cp[-1] == '\\'))
|
||||
@@ -1437,7 +1414,6 @@ static void include_filename()
|
||||
standby->path = strdup(yytext+1);
|
||||
standby->path[strlen(standby->path)-1] = 0;
|
||||
standby->lineno = 0;
|
||||
standby->comment = NULL;
|
||||
}
|
||||
|
||||
static void do_include()
|
||||
@@ -1463,7 +1439,12 @@ static void do_include()
|
||||
else
|
||||
{
|
||||
*cp = '\0';
|
||||
include_dir[0] = strdup(path);
|
||||
|
||||
/* We do not need a strdup here since the path is read before
|
||||
* it is overridden. If the search order is changed add a
|
||||
* strdup here and a free below.
|
||||
*/
|
||||
include_dir[0] = path;
|
||||
}
|
||||
|
||||
for (idx = start ; idx < include_cnt ; idx += 1)
|
||||
@@ -1472,8 +1453,6 @@ static void do_include()
|
||||
|
||||
if ((standby->file = fopen(path, "r")))
|
||||
{
|
||||
/* Free the original path before we overwrite it. */
|
||||
free(standby->path);
|
||||
standby->path = strdup(path);
|
||||
goto code_that_switches_buffers;
|
||||
}
|
||||
@@ -1485,15 +1464,11 @@ static void do_include()
|
||||
|
||||
code_that_switches_buffers:
|
||||
|
||||
/* Clear the current files path from the search list. */
|
||||
free(include_dir[0]);
|
||||
include_dir[0] = 0;
|
||||
|
||||
if(depend_file)
|
||||
fprintf(depend_file, "%s\n", standby->path);
|
||||
|
||||
if (line_direct_flag)
|
||||
fprintf(yyout, "\n`line 1 \"%s\" 1\n", standby->path);
|
||||
fprintf(yyout, "\n`line %u \"%s\" 1\n", istack->lineno+1, standby->path);
|
||||
|
||||
standby->next = istack;
|
||||
standby->stringify_flag = 0;
|
||||
@@ -1551,17 +1526,6 @@ static int load_next_input()
|
||||
/* Delete the current input buffers, and free the cell. */
|
||||
yy_delete_buffer(YY_CURRENT_BUFFER);
|
||||
|
||||
/* If there was a comment for this include print it before we
|
||||
* return to the previous input stream. This technically belongs
|
||||
* to the previous stream, but it should not create any problems
|
||||
* since it is only a comment.
|
||||
*/
|
||||
if (isp->comment) {
|
||||
fprintf(yyout, "%s\n", isp->comment);
|
||||
free(isp->comment);
|
||||
isp->comment = NULL;
|
||||
}
|
||||
|
||||
if (isp->file)
|
||||
{
|
||||
free(isp->path);
|
||||
@@ -1620,12 +1584,6 @@ static int load_next_input()
|
||||
if(depend_file)
|
||||
fprintf(depend_file, "%s\n", istack->path);
|
||||
|
||||
/* This works around an issue in flex yyrestart() where it
|
||||
* uses yyin to create a new buffer when one does not exist.
|
||||
* I would have assumed that it would use the file argument.
|
||||
* The problem is that we have deleted the buffer and freed
|
||||
* yyin (isp->file) above. */
|
||||
yyin = 0;
|
||||
yyrestart(istack->file);
|
||||
return 1;
|
||||
}
|
||||
@@ -1758,7 +1716,6 @@ void reset_lexor(FILE* out, char* paths[])
|
||||
isp->ebs = 0;
|
||||
isp->lineno = 0;
|
||||
isp->stringify_flag = 0;
|
||||
isp->comment = NULL;
|
||||
|
||||
if (isp->file == 0)
|
||||
{
|
||||
@@ -1789,7 +1746,6 @@ void reset_lexor(FILE* out, char* paths[])
|
||||
isp->next = 0;
|
||||
isp->lineno = 0;
|
||||
isp->stringify_flag = 0;
|
||||
isp->comment = NULL;
|
||||
|
||||
if (tail)
|
||||
tail->next = isp;
|
||||
@@ -1799,17 +1755,3 @@ void reset_lexor(FILE* out, char* paths[])
|
||||
tail = isp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Modern version of flex (>=2.5.9) can clean up the scanner data.
|
||||
*/
|
||||
void destroy_lexor()
|
||||
{
|
||||
# ifdef FLEX_SCANNER
|
||||
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
|
||||
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
|
||||
yylex_destroy();
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
}
|
||||
|
||||
+13
-37
@@ -17,8 +17,7 @@ const char COPYRIGHT[] =
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
# include "version.h"
|
||||
# include "config.h"
|
||||
|
||||
const char NOTICE[] =
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
@@ -31,11 +30,13 @@ const char NOTICE[] =
|
||||
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
||||
" GNU General Public License for more details.\n"
|
||||
"\n"
|
||||
" You should have received a copy of the GNU General Public License along\n"
|
||||
" with this program; if not, write to the Free Software Foundation, Inc.,\n"
|
||||
" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n"
|
||||
" You should have received a copy of the GNU General Public License\n"
|
||||
" along with this program; if not, write to the Free Software\n"
|
||||
" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\n"
|
||||
;
|
||||
|
||||
const char VERSION[] = "$Name: $ $State: Exp $";
|
||||
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
#ifdef HAVE_MALLOC_H
|
||||
@@ -102,8 +103,6 @@ static int flist_read_flags(const char*path)
|
||||
char*cp = line_buf + strspn(line_buf, " \t\r\b\f");
|
||||
/* Remove trailing white space. */
|
||||
char*tail = cp + strlen(cp);
|
||||
char*arg;
|
||||
|
||||
while (tail > cp) {
|
||||
if (! isspace(tail[-1]))
|
||||
break;
|
||||
@@ -119,7 +118,7 @@ static int flist_read_flags(const char*path)
|
||||
continue;
|
||||
|
||||
/* The arg points to the argument to the keyword. */
|
||||
arg = strchr(cp, ':');
|
||||
char*arg = strchr(cp, ':');
|
||||
if (arg) *arg++ = 0;
|
||||
|
||||
if (strcmp(cp,"D") == 0) {
|
||||
@@ -189,14 +188,12 @@ static int flist_read_names(const char*path)
|
||||
add_source_file(cp);
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char*argv[])
|
||||
{
|
||||
int opt, idx;
|
||||
unsigned lp;
|
||||
const char*flist_path = 0;
|
||||
unsigned flag_errors = 0;
|
||||
char*out_path = 0;
|
||||
@@ -232,7 +229,7 @@ int main(int argc, char*argv[])
|
||||
include_dir[0] = 0; /* 0 is reserved for the current files path. */
|
||||
include_dir[1] = strdup(".");
|
||||
|
||||
while ((opt=getopt(argc, argv, "F:f:K:Lo:p:P:vV")) != EOF) switch (opt) {
|
||||
while ((opt=getopt(argc, argv, "F:f:K:Lo:p:P:v")) != EOF) switch (opt) {
|
||||
|
||||
case 'F':
|
||||
flist_read_flags(optarg);
|
||||
@@ -285,21 +282,14 @@ int main(int argc, char*argv[])
|
||||
fclose(src);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 'v':
|
||||
fprintf(stderr, "Icarus Verilog Preprocessor version "
|
||||
VERSION " (" VERSION_TAG ")\n\n");
|
||||
fprintf(stderr, "%s\n\n", COPYRIGHT);
|
||||
fprintf(stderr, "Icarus Verilog Preprocessor version %s\n",
|
||||
VERSION);
|
||||
fprintf(stderr, "%s\n", COPYRIGHT);
|
||||
fputs(NOTICE, stderr);
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
fprintf(stdout, "Icarus Verilog Preprocessor version "
|
||||
VERSION " (" VERSION_TAG ")\n\n");
|
||||
fprintf(stdout, "%s\n", COPYRIGHT);
|
||||
fputs(NOTICE, stdout);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
flag_errors += 1;
|
||||
break;
|
||||
@@ -314,8 +304,7 @@ int main(int argc, char*argv[])
|
||||
" -o<fil> - Send the output to <fil>\n"
|
||||
" -p<fil> - Write precompiled defines to <fil>\n"
|
||||
" -P<fil> - Read precompiled defines from <fil>\n"
|
||||
" -v - Verbose\n"
|
||||
" -V - Print version information and quit\n",
|
||||
" -v - Print version information\n",
|
||||
argv[0]);
|
||||
return flag_errors;
|
||||
}
|
||||
@@ -370,7 +359,6 @@ int main(int argc, char*argv[])
|
||||
start scanning. */
|
||||
reset_lexor(out, source_list);
|
||||
if (yylex()) return -1;
|
||||
destroy_lexor();
|
||||
|
||||
if(depend_file) {
|
||||
fclose(depend_file);
|
||||
@@ -381,17 +369,5 @@ int main(int argc, char*argv[])
|
||||
fclose(precomp_out);
|
||||
}
|
||||
|
||||
/* Free the source and include directory lists. */
|
||||
for (lp = 0; lp < source_cnt; lp += 1) {
|
||||
free(source_list[lp]);
|
||||
}
|
||||
free(source_list);
|
||||
for (lp = 0; lp < include_cnt; lp += 1) {
|
||||
free(include_dir[lp]);
|
||||
}
|
||||
free(include_dir);
|
||||
|
||||
free_macros();
|
||||
|
||||
return error_count;
|
||||
}
|
||||
|
||||
@@ -87,7 +87,6 @@ static void process_timescale(const char*txt);
|
||||
static list<int> keyword_mask_stack;
|
||||
|
||||
static int comment_enter;
|
||||
static bool in_module = false;
|
||||
%}
|
||||
|
||||
%x CCOMMENT
|
||||
@@ -124,8 +123,8 @@ S [afpnumkKMGT]
|
||||
/* The contents of C-style comments are ignored, like white space. */
|
||||
|
||||
"/*" { comment_enter = YY_START; BEGIN(CCOMMENT); }
|
||||
<CCOMMENT>. { ; }
|
||||
<CCOMMENT>\n { yylloc.first_line += 1; }
|
||||
<CCOMMENT>. { yymore(); }
|
||||
<CCOMMENT>\n { yylloc.first_line += 1; yymore(); }
|
||||
<CCOMMENT>"*/" { BEGIN(comment_enter); }
|
||||
|
||||
|
||||
@@ -228,15 +227,6 @@ S [afpnumkKMGT]
|
||||
BEGIN(EDGES);
|
||||
break;
|
||||
|
||||
case K_module:
|
||||
case K_macromodule:
|
||||
in_module = true;
|
||||
break;
|
||||
|
||||
case K_endmodule:
|
||||
in_module = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
yylval.text = 0;
|
||||
break;
|
||||
@@ -247,7 +237,7 @@ S [afpnumkKMGT]
|
||||
value instead. */
|
||||
if (rc == IDENTIFIER && gn_verilog_ams_flag) {
|
||||
perm_string tmp = lex_strings.make(yylval.text);
|
||||
map<perm_string,ivl_discipline_t>::iterator cur = disciplines.find(tmp);
|
||||
map<perm_string,discipline_t*>::iterator cur = disciplines.find(tmp);
|
||||
if (cur != disciplines.end()) {
|
||||
yylval.discipline = (*cur).second;
|
||||
rc = DISCIPLINE_IDENTIFIER;
|
||||
@@ -353,12 +343,6 @@ S [afpnumkKMGT]
|
||||
^{W}?`timescale { BEGIN(PPTIMESCALE); }
|
||||
<PPTIMESCALE>.* { process_timescale(yytext); }
|
||||
<PPTIMESCALE>\n {
|
||||
if (in_module) {
|
||||
cerr << yylloc.text << ":" << yylloc.first_line << ": error: "
|
||||
"`timescale directive can not be inside a module "
|
||||
"definition." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
yylloc.first_line += 1;
|
||||
BEGIN(0); }
|
||||
|
||||
@@ -455,7 +439,7 @@ S [afpnumkKMGT]
|
||||
|
||||
} else {
|
||||
cerr << yylloc.text << ":" << yylloc.first_line
|
||||
<< ": error: Net type " << yytext
|
||||
<< " error: Net type " << yytext
|
||||
<< " is not a valid (and supported)"
|
||||
<< " default net type." << endl;
|
||||
net_type = NetNet::WIRE;
|
||||
@@ -473,37 +457,37 @@ S [afpnumkKMGT]
|
||||
|
||||
^{W}?`define{W}?.* {
|
||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||
": warning: `define not supported. Use an external preprocessor."
|
||||
": `define not supported. Use an external preprocessor."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
^{W}?`else{W}?.* {
|
||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||
": warning: `else not supported. Use an external preprocessor."
|
||||
": `else not supported. Use an external preprocessor."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
^{W}?`endif{W}?.* {
|
||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||
": warning: `endif not supported. Use an external preprocessor."
|
||||
": `endif not supported. Use an external preprocessor."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
^{W}?`ifdef{W}?.* {
|
||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||
": warning: `ifdef not supported. Use an external preprocessor."
|
||||
": `ifdef not supported. Use an external preprocessor."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
^`include{W}?.* {
|
||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||
": warning: `include not supported. Use an external preprocessor."
|
||||
": `include not supported. Use an external preprocessor."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
^`undef{W}?.* {
|
||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||
": warning: `undef not supported. Use an external preprocessor."
|
||||
": `undef not supported. Use an external preprocessor."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
@@ -859,7 +843,7 @@ static verinum*make_unsized_dec(const char*ptr)
|
||||
if (ptr[0] == '\'') {
|
||||
/* The number has decorations of the form 'sd<digits>,
|
||||
possibly with space between the d and the <digits>.
|
||||
Also, the 's' is optional, and marks the number as
|
||||
Also, the 's' is optional, and markes the number as
|
||||
signed. */
|
||||
ptr += 1;
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ assign, GN_KEYWORDS_1364_1995, K_assign
|
||||
atan, GN_KEYWORDS_VAMS_2_3, K_atan
|
||||
atan2, GN_KEYWORDS_VAMS_2_3, K_atan2
|
||||
atanh, GN_KEYWORDS_VAMS_2_3, K_atanh
|
||||
automatic, GN_KEYWORDS_1364_2001, K_automatic
|
||||
begin, GN_KEYWORDS_1364_1995, K_begin
|
||||
bool, GN_KEYWORDS_ICARUS, K_bool
|
||||
buf, GN_KEYWORDS_1364_1995, K_buf
|
||||
|
||||
@@ -18,7 +18,19 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: lexor_keyword.h,v 1.2 2002/08/12 01:34:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
extern int lexor_keyword_code (const char*str, unsigned len);
|
||||
|
||||
/*
|
||||
* $Log: lexor_keyword.h,v $
|
||||
* Revision 1.2 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.1 2000/03/12 17:09:41 steve
|
||||
* Support localparam.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.36 2007/02/06 05:07:32 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
suffix = @install_suffix@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
@@ -35,7 +37,7 @@ INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
CPPFLAGS = -I. -I.. -I$(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@ @PICFLAG@
|
||||
CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@ @PICFLAG@
|
||||
CFLAGS = -Wall @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
RANLIB = @RANLIB@
|
||||
@@ -84,15 +86,15 @@ clean:
|
||||
distclean: clean
|
||||
rm -f Makefile config.status config.log config.cache config.h
|
||||
|
||||
install:: all installdirs $(libdir)/libveriuser$(suffix).a $(INSTALL32)
|
||||
install:: all installdirs $(libdir)/libveriuser.a $(INSTALL32)
|
||||
|
||||
$(libdir)/libveriuser$(suffix).a: ./libveriuser.a
|
||||
$(INSTALL_DATA) ./libveriuser.a $(DESTDIR)$(libdir)/libveriuser$(suffix).a
|
||||
$(libdir)/libveriuser.a: ./libveriuser.a
|
||||
$(INSTALL_DATA) ./libveriuser.a $(libdir)/libveriuser.a
|
||||
|
||||
installdirs: mkinstalldirs
|
||||
$(srcdir)/mkinstalldirs $(DESTDIR)$(includedir) $(DESTDIR)$(libdir)
|
||||
$(srcdir)/mkinstalldirs $(includedir) $(libdir)
|
||||
|
||||
uninstall::
|
||||
rm -f $(DESTDIR)$(libdir)/libveriuser$(suffix).a
|
||||
rm -f $(libdir)/libveriuser.a
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O)
|
||||
|
||||
@@ -99,7 +99,7 @@ PLI_INT32 acc_fetch_fulltype(handle obj)
|
||||
return accTopModule;
|
||||
else
|
||||
return accModuleInstance;
|
||||
/* FIXME accCellInstance */
|
||||
// FIXME accCellInstance
|
||||
|
||||
case vpiNamedEvent: return accNamedEvent;
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ handle acc_next(PLI_INT32 *type, handle scope, handle prev)
|
||||
* rescan all the items up to the previous one, then return
|
||||
* the next one.
|
||||
*/
|
||||
iter = vpi_iterate(vpiScope, scope); /* ICARUS extension */
|
||||
iter = vpi_iterate(vpiScope, scope); // ICARUS extension
|
||||
if (prev) {
|
||||
while ((hand = vpi_scan(iter))) {
|
||||
if (hand == prev) break;
|
||||
|
||||
@@ -35,7 +35,7 @@ int acc_object_of_type(handle object, PLI_INT32 type)
|
||||
|
||||
if (pli_trace) {
|
||||
fprintf(pli_trace, "acc_object_of_type(%p \"%s\", %d)",
|
||||
object, vpi_get_str(vpiName, object), type);
|
||||
object, vpi_get_str(vpiName, object), type);
|
||||
fflush(pli_trace);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: config.h.in,v 1.2 2003/08/26 16:26:02 steve Exp $"
|
||||
#endif
|
||||
|
||||
# define SIZEOF_UNSIGNED_LONG_LONG 0
|
||||
# define SIZEOF_UNSIGNED_LONG 0
|
||||
@@ -37,4 +40,19 @@ typedef unsigned long ivl_u64_t;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $Log: config.h.in,v $
|
||||
* Revision 1.2 2003/08/26 16:26:02 steve
|
||||
* ifdef idents correctly.
|
||||
*
|
||||
* Revision 1.1 2003/06/04 01:56:20 steve
|
||||
* 1) Adds configure logic to clean up compiler warnings
|
||||
* 2) adds acc_compare_handle, acc_fetch_range, acc_next_scope and
|
||||
* tf_isetrealdelay, acc_handle_scope
|
||||
* 3) makes acc_next reentrant
|
||||
* 4) adds basic vpiWire type support
|
||||
* 5) fills in some acc_object_of_type() and acc_fetch_{full}type()
|
||||
* 6) add vpiLeftRange/RigthRange to signals
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
||||
@@ -8,8 +8,7 @@ AC_PROG_INSTALL
|
||||
AC_PROG_RANLIB
|
||||
|
||||
AC_EXEEXT
|
||||
|
||||
AX_ENABLE_SUFFIX
|
||||
AX_CPP_IDENT
|
||||
|
||||
AC_CHECK_HEADERS(malloc.h)
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: priv.h,v 1.2 2003/05/18 00:16:35 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdio.h>
|
||||
|
||||
@@ -33,4 +36,21 @@ extern char* __acc_newstring(const char*txt);
|
||||
*/
|
||||
FILE* pli_trace;
|
||||
|
||||
/*
|
||||
* $Log: priv.h,v $
|
||||
* Revision 1.2 2003/05/18 00:16:35 steve
|
||||
* Add PLI_TRACE tracing of PLI1 modules.
|
||||
*
|
||||
* Add tf_isetdelay and friends, and add
|
||||
* callback return values for acc_vcl support.
|
||||
*
|
||||
* Revision 1.1 2003/02/17 06:39:47 steve
|
||||
* Add at least minimal implementations for several
|
||||
* acc_ functions. Add support for standard ACC
|
||||
* string handling.
|
||||
*
|
||||
* Add the _pli_types.h header file to carry the
|
||||
* IEEE1364-2001 standard PLI type declarations.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
||||
@@ -366,7 +366,7 @@ PLI_INT32 tf_isetrealdelay(double dly, void*obj)
|
||||
s_cb_data cb;
|
||||
s_vpi_time ti = {vpiSimTime};
|
||||
|
||||
/* Scale delay to SimTime */
|
||||
// Scale delay to SimTime
|
||||
ivl_u64_t delay = ((dly
|
||||
* pow(10, tf_gettimeprecision() - tf_gettimeunit()))
|
||||
+ 0.5);
|
||||
|
||||
+84
-5
@@ -16,6 +16,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: link_const.cc,v 1.18 2007/04/14 03:10:51 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
@@ -57,9 +60,8 @@ bool Nexus::drivers_constant() const
|
||||
|
||||
if (cur_dir == Link::PASSIVE) {
|
||||
|
||||
const NetPins*obj = cur->get_obj();
|
||||
const NetObj*as_obj = dynamic_cast<const NetObj*>(obj);
|
||||
if (as_obj == 0 || as_obj->scope()->parent() != 0)
|
||||
const NetObj*obj = cur->get_obj();
|
||||
if (obj->scope()->parent() != 0)
|
||||
continue;
|
||||
|
||||
sig = dynamic_cast<const NetNet*>(cur->get_obj());
|
||||
@@ -78,8 +80,8 @@ bool Nexus::drivers_constant() const
|
||||
|
||||
/* If there is a supply net, then this nexus will have a
|
||||
constant value independent of any drivers. */
|
||||
if (const NetNet*s = dynamic_cast<const NetNet*>(cur->get_obj()))
|
||||
switch (s->type()) {
|
||||
if (const NetNet*sig = dynamic_cast<const NetNet*>(cur->get_obj()))
|
||||
switch (sig->type()) {
|
||||
case NetNet::SUPPLY0:
|
||||
driven_ = V0;
|
||||
return true;
|
||||
@@ -172,3 +174,80 @@ verinum::V Nexus::driven_value() const
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: link_const.cc,v $
|
||||
* Revision 1.18 2007/04/14 03:10:51 steve
|
||||
* Properly account for tri0 connected to otherwise open mux input.
|
||||
*
|
||||
* Revision 1.17 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
* Revision 1.16 2003/06/21 01:21:43 steve
|
||||
* Harmless fixup of warnings.
|
||||
*
|
||||
* Revision 1.15 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.14 2002/06/25 01:33:22 steve
|
||||
* Cache calculated driven value.
|
||||
*
|
||||
* Revision 1.13 2002/06/24 01:49:39 steve
|
||||
* Make link_drive_constant cache its results in
|
||||
* the Nexus, to improve cprop performance.
|
||||
*
|
||||
* Revision 1.12 2002/06/19 04:18:46 steve
|
||||
* Shuffle link_drivers_constant for speed.
|
||||
*
|
||||
* Revision 1.11 2001/08/25 23:50:03 steve
|
||||
* Change the NetAssign_ class to refer to the signal
|
||||
* instead of link into the netlist. This is faster
|
||||
* and uses less space. Make the NetAssignNB carry
|
||||
* the delays instead of the NetAssign_ lval objects.
|
||||
*
|
||||
* Change the vvp code generator to support multiple
|
||||
* l-values, i.e. concatenations of part selects.
|
||||
*
|
||||
* Revision 1.10 2001/07/25 03:10:49 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.9 2001/07/07 03:01:37 steve
|
||||
* Detect and make available to t-dll the right shift.
|
||||
*
|
||||
* Revision 1.8 2001/02/16 03:27:07 steve
|
||||
* links to root inputs are not constant.
|
||||
*
|
||||
* Revision 1.7 2000/11/20 01:41:12 steve
|
||||
* Whoops, return the calculated constant value rom driven_value.
|
||||
*
|
||||
* Revision 1.6 2000/11/20 00:58:40 steve
|
||||
* Add support for supply nets (PR#17)
|
||||
*
|
||||
* Revision 1.5 2000/07/14 06:12:57 steve
|
||||
* Move inital value handling from NetNet to Nexus
|
||||
* objects. This allows better propogation of inital
|
||||
* values.
|
||||
*
|
||||
* Clean up constant propagation a bit to account
|
||||
* for regs that are not really values.
|
||||
*
|
||||
* Revision 1.4 2000/06/25 19:59:42 steve
|
||||
* Redesign Links to include the Nexus class that
|
||||
* carries properties of the connected set of links.
|
||||
*
|
||||
* Revision 1.3 2000/05/14 17:55:04 steve
|
||||
* Support initialization of FF Q value.
|
||||
*
|
||||
* Revision 1.2 2000/05/07 04:37:56 steve
|
||||
* Carry strength values from Verilog source to the
|
||||
* pform and netlist for gates.
|
||||
*
|
||||
* Change vvm constants to use the driver_t to drive
|
||||
* a constant value. This works better if there are
|
||||
* multiple drivers on a signal.
|
||||
*
|
||||
* Revision 1.1 2000/04/20 00:28:03 steve
|
||||
* Catch some simple identity compareoptimizations.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user